diff --git a/DEPS b/DEPS
index b1efbe0..069ffc96 100644
--- a/DEPS
+++ b/DEPS
@@ -181,7 +181,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '2cd5d43f022caeb462d3d6519cafbf38d166354a',
+  'skia_revision': 'd58b643f10f5e2f8fc9273865a6a5c7929ba20ad',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -193,15 +193,15 @@
   # 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': 'bdb0f8a524147f183f84c6013860384fb12934a3',
+  'angle_revision': '41f6150edb165f66a2ded18d258cc5ddb9ee9e95',
   # 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': '5c6a3c247590d8057a1cc03e67e7d0576a970941',
+  'swiftshader_revision': '2cb1db08e5f1be1fbfd9847800515caa5fc1dfb0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'c86e356c31a90805c4e4c54e894b0097c111f09e',
+  'pdfium_revision': '7891b46fd46e5c88913da0c3111f7090985526d4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # 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': '251c7653021328d5d27e26e18a05b7cae9205b8e',
+  'catapult_revision': '91096f77a5815f668aff303866b0face7784c63f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -539,7 +539,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c2500e4ea9dc2b99a080df244247abaae061a198',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'dc9529ad1077730cb7a57b05b77c9260d027b6d4',
       'condition': 'checkout_ios',
   },
 
@@ -904,7 +904,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e9730d75a00548a22e4392567243969d85c02dd4',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '05b001c28df8e2811c24656e7ad260d7232afb9d',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1297,7 +1297,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '11c11a1a891c7731511d3cc302c3a9adbcb3575f',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '649f757cc08b3dd69a301b499e0332618d394ab9',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1498,7 +1498,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '4f3976e9b368ccfe7b9dd02014351936296dc72c',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '4c1086a36adea880087aa22b0a4439611e0e3f73',
+    Var('webrtc_git') + '/src.git' + '@' + '3f0bc2c1766a938ae47e81ad56c573cda85da1a5',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1568,7 +1568,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@57a0ce4db8710075a899dff84a49bffa3388aca2',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2182260bce542eec0dc003b707192c2b6ce2979b',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.cc b/android_webview/browser/metrics/aw_metrics_service_client.cc
index 93a2f7ad0..862457e 100644
--- a/android_webview/browser/metrics/aw_metrics_service_client.cc
+++ b/android_webview/browser/metrics/aw_metrics_service_client.cc
@@ -28,6 +28,7 @@
 #include "components/metrics/cpu_metrics_provider.h"
 #include "components/metrics/drive_metrics_provider.h"
 #include "components/metrics/enabled_state_provider.h"
+#include "components/metrics/entropy_state_provider.h"
 #include "components/metrics/gpu/gpu_metrics_provider.h"
 #include "components/metrics/metrics_log_uploader.h"
 #include "components/metrics/metrics_pref_names.h"
@@ -131,6 +132,8 @@
   service->RegisterMetricsProvider(
       std::make_unique<metrics::CPUMetricsProvider>());
   service->RegisterMetricsProvider(
+      std::make_unique<metrics::EntropyStateProvider>(prefs));
+  service->RegisterMetricsProvider(
       std::make_unique<metrics::GPUMetricsProvider>());
   service->RegisterMetricsProvider(
       std::make_unique<metrics::DriveMetricsProvider>(
diff --git a/android_webview/renderer/BUILD.gn b/android_webview/renderer/BUILD.gn
index 88b25c6..16324e80 100644
--- a/android_webview/renderer/BUILD.gn
+++ b/android_webview/renderer/BUILD.gn
@@ -30,8 +30,6 @@
     "js_java_interaction/js_binding.h",
     "js_java_interaction/js_java_configurator.cc",
     "js_java_interaction/js_java_configurator.h",
-    "print_render_frame_observer.cc",
-    "print_render_frame_observer.h",
   ]
 
   deps = [
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index bc23390..0db6fa3 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -20,7 +20,6 @@
 #include "android_webview/renderer/aw_websocket_handshake_throttle_provider.h"
 #include "android_webview/renderer/browser_exposed_renderer_interfaces.h"
 #include "android_webview/renderer/js_java_interaction/js_java_configurator.h"
-#include "android_webview/renderer/print_render_frame_observer.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
 #include "base/metrics/histogram_macros.h"
@@ -148,7 +147,6 @@
 void AwContentRendererClient::RenderFrameCreated(
     content::RenderFrame* render_frame) {
   new AwContentSettingsClient(render_frame);
-  new PrintRenderFrameObserver(render_frame);
   new printing::PrintRenderFrameHelper(
       render_frame, std::make_unique<AwPrintRenderFrameHelperDelegate>());
   new AwRenderFrameExt(render_frame);
diff --git a/android_webview/renderer/print_render_frame_observer.cc b/android_webview/renderer/print_render_frame_observer.cc
deleted file mode 100644
index d723917..0000000
--- a/android_webview/renderer/print_render_frame_observer.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "android_webview/renderer/print_render_frame_observer.h"
-
-#include "components/printing/common/print_messages.h"
-#include "components/printing/renderer/print_render_frame_helper.h"
-#include "content/public/renderer/render_frame.h"
-#include "third_party/blink/public/web/web_local_frame.h"
-
-namespace android_webview {
-
-PrintRenderFrameObserver::PrintRenderFrameObserver(
-    content::RenderFrame* render_frame)
-    : content::RenderFrameObserver(render_frame) {
-}
-
-PrintRenderFrameObserver::~PrintRenderFrameObserver() {
-}
-
-bool PrintRenderFrameObserver::OnMessageReceived(
-    const IPC::Message& message) {
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(PrintRenderFrameObserver, message)
-    IPC_MESSAGE_HANDLER(PrintMsg_PrintNodeUnderContextMenu,
-                        OnPrintNodeUnderContextMenu)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-
-  return handled;
-}
-
-void PrintRenderFrameObserver::OnPrintNodeUnderContextMenu() {
-  printing::PrintRenderFrameHelper* helper =
-      printing::PrintRenderFrameHelper::Get(render_frame());
-  if (helper)
-    helper->PrintNode(render_frame()->GetWebFrame()->ContextMenuNode());
-}
-
-void PrintRenderFrameObserver::OnDestruct() {
-  delete this;
-}
-
-}  // namespace android_webview
diff --git a/android_webview/renderer/print_render_frame_observer.h b/android_webview/renderer/print_render_frame_observer.h
deleted file mode 100644
index c19c48b..0000000
--- a/android_webview/renderer/print_render_frame_observer.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_WEBVIEW_RENDERER_PRINT_RENDER_FRAME_OBSERVER_H_
-#define ANDROID_WEBVIEW_RENDERER_PRINT_RENDER_FRAME_OBSERVER_H_
-
-#include "base/macros.h"
-#include "content/public/renderer/render_frame_observer.h"
-
-namespace android_webview {
-
-class PrintRenderFrameObserver : public content::RenderFrameObserver {
- public:
-  explicit PrintRenderFrameObserver(content::RenderFrame* render_view);
-
- private:
-  ~PrintRenderFrameObserver() override;
-
-  // RenderFrameObserver implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void OnDestruct() override;
-
-  // IPC handlers
-  void OnPrintNodeUnderContextMenu();
-
-  DISALLOW_COPY_AND_ASSIGN(PrintRenderFrameObserver);
-};
-
-}  // namespace android_webview
-
-#endif  // ANDROID_WEBVIEW_RENDERER_PRINT_RENDER_FRAME_OBSERVER_H_
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index e7e6d49..e0919cc0 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1165,6 +1165,8 @@
     "wm/fullscreen_window_finder.h",
     "wm/gestures/back_gesture/back_gesture_affordance.cc",
     "wm/gestures/back_gesture/back_gesture_affordance.h",
+    "wm/gestures/back_gesture/back_gesture_event_handler.cc",
+    "wm/gestures/back_gesture/back_gesture_event_handler.h",
     "wm/gestures/back_gesture/back_gesture_metrics.cc",
     "wm/gestures/back_gesture/back_gesture_metrics.h",
     "wm/gestures/wm_gesture_handler.cc",
@@ -1942,6 +1944,7 @@
     "wm/drag_window_resizer_unittest.cc",
     "wm/fullscreen_window_finder_unittest.cc",
     "wm/gestures/back_gesture/back_gesture_affordance_unittest.cc",
+    "wm/gestures/back_gesture/back_gesture_event_handler_unittest.cc",
     "wm/gestures/wm_gesture_handler_unittest.cc",
     "wm/immersive_fullscreen_controller_unittest.cc",
     "wm/lock_action_handler_layout_manager_unittest.cc",
diff --git a/ash/app_list/views/app_list_drag_and_drop_host.h b/ash/app_list/views/app_list_drag_and_drop_host.h
index 9ff334d..3acc5cfd 100644
--- a/ash/app_list/views/app_list_drag_and_drop_host.h
+++ b/ash/app_list/views/app_list_drag_and_drop_host.h
@@ -20,7 +20,7 @@
 namespace ash {
 
 // This class will get used by the AppListView to drag and drop Application
-// shortcuts onto another host (the launcher).
+// shortcuts onto another host (the shelf).
 class ApplicationDragAndDropHost {
  public:
   // Creates an OS dependent drag proxy icon which can escape the given view.
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc
index 3a8365d5..717375e 100644
--- a/ash/app_list/views/apps_grid_view.cc
+++ b/ash/app_list/views/apps_grid_view.cc
@@ -2116,12 +2116,6 @@
   if (!drag_view_ || !drag_and_drop_host_)
     return;
 
-  // Determine the mouse offset to the center of the icon so that the drag and
-  // drop host follows this layer.
-  gfx::Vector2d delta =
-      drag_view_offset_ - drag_view_->GetLocalBounds().CenterPoint();
-  delta.set_y(delta.y() + drag_view_->title()->size().height() / 2);
-
   // We have to hide the original item since the drag and drop host will do
   // the OS dependent code to "lift off the dragged item". Apply the scale
   // factor of this view's transform to the dragged view as well.
diff --git a/ash/shell.cc b/ash/shell.cc
index b1fec30d..b936d71 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -127,6 +127,7 @@
 #include "ash/wm/cursor_manager_chromeos.h"
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/event_client_impl.h"
+#include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
 #include "ash/wm/immersive_context_ash.h"
 #include "ash/wm/lock_state_controller.h"
 #include "ash/wm/mru_window_tracker.h"
@@ -613,6 +614,8 @@
 
   RemovePreTargetHandler(accelerator_filter_.get());
   RemovePreTargetHandler(event_transformation_handler_.get());
+  if (back_gesture_event_handler_)
+    RemovePreTargetHandler(back_gesture_event_handler_.get());
   RemovePreTargetHandler(toplevel_window_event_handler_.get());
   RemovePostTargetHandler(toplevel_window_event_handler_.get());
   RemovePreTargetHandler(system_gesture_filter_.get());
@@ -992,6 +995,11 @@
   event_transformation_handler_.reset(new EventTransformationHandler);
   AddPreTargetHandler(event_transformation_handler_.get());
 
+  if (features::IsSwipingFromLeftEdgeToGoBackEnabled()) {
+    back_gesture_event_handler_ = std::make_unique<BackGestureEventHandler>();
+    AddPreTargetHandler(back_gesture_event_handler_.get());
+  }
+
   toplevel_window_event_handler_ =
       std::make_unique<ToplevelWindowEventHandler>();
 
diff --git a/ash/shell.h b/ash/shell.h
index 8aa3d9d6..5d37b3a 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -94,6 +94,7 @@
 class AshTouchTransformController;
 class AssistantController;
 class AutoclickController;
+class BackGestureEventHandler;
 class BacklightsForcedOffSetter;
 class BluetoothNotificationController;
 class BluetoothPowerController;
@@ -493,6 +494,9 @@
   WindowTreeHostManager* window_tree_host_manager() {
     return window_tree_host_manager_.get();
   }
+  BackGestureEventHandler* back_gesture_event_handler() {
+    return back_gesture_event_handler_.get();
+  }
   ToplevelWindowEventHandler* toplevel_window_event_handler() {
     return toplevel_window_event_handler_.get();
   }
@@ -698,6 +702,9 @@
   // screenshot UI or the keyboard overlay is active.
   std::unique_ptr<OverlayEventFilter> overlay_filter_;
 
+  // An event filter which handles swiping back from left side of the window.
+  std::unique_ptr<BackGestureEventHandler> back_gesture_event_handler_;
+
   // An event filter which handles moving and resizing windows.
   std::unique_ptr<ToplevelWindowEventHandler> toplevel_window_event_handler_;
 
diff --git a/ash/system/tray/tray_utils.cc b/ash/system/tray/tray_utils.cc
index 7a9583188..e4bd1ce4 100644
--- a/ash/system/tray/tray_utils.cc
+++ b/ash/system/tray/tray_utils.cc
@@ -61,7 +61,8 @@
   int height_compensation = kTrayBubbleInsetHotseatCompensation;
   switch (shelf->GetBackgroundType()) {
     case ShelfBackgroundType::kInApp:
-      // In-app mode does not require a height compensation.
+    case ShelfBackgroundType::kOverview:
+      // Certain modes do not require a height compensation.
       height_compensation = 0;
       break;
     case ShelfBackgroundType::kLogin:
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index e646e426..a6cf9da 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -118,6 +118,8 @@
  public:
   ~DeskAnimationBase() override = default;
 
+  const Desk* ending_desk() const { return ending_desk_; }
+
   // Launches the animation. This should be done once all animators
   // are created and added to `desk_switch_animators_`. This is to avoid any
   // potential race conditions that might happen if one animator finished phase
@@ -200,8 +202,11 @@
   }
 
  protected:
-  explicit DeskAnimationBase(DesksController* controller)
-      : controller_(controller) {}
+  DeskAnimationBase(DesksController* controller, const Desk* ending_desk)
+      : controller_(controller), ending_desk_(ending_desk) {
+    DCHECK(controller_);
+    DCHECK(ending_desk_);
+  }
 
   // Abstract functions that can be overridden by child classes to do different
   // things when phase (1), and phase (3) completes. Note that
@@ -224,6 +229,9 @@
   std::vector<std::unique_ptr<RootWindowDeskSwitchAnimator>>
       desk_switch_animators_;
 
+  // The desk that will be active after this animation ends.
+  const Desk* const ending_desk_;
+
  private:
   // Computes the animation smoothness and reports an UMA stat for it.
   void ComputeAnimationSmoothnessAndReport() {
@@ -249,7 +257,7 @@
   DeskActivationAnimation(DesksController* controller,
                           const Desk* ending_desk,
                           bool move_left)
-      : DeskAnimationBase(controller) {
+      : DeskAnimationBase(controller, ending_desk) {
     for (auto* root : Shell::GetAllRootWindows()) {
       desk_switch_animators_.emplace_back(
           std::make_unique<RootWindowDeskSwitchAnimator>(root, ending_desk,
@@ -262,6 +270,7 @@
 
   // DesksController::AbstractDeskSwitchAnimation:
   void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override {
+    DCHECK_EQ(ending_desk_, ending_desk);
     // The order here matters. Overview must end before ending tablet split view
     // before switching desks. (If clamshell split view is active on one or more
     // displays, then it simply will end when we end overview.) That's because
@@ -312,7 +321,7 @@
                        const Desk* desk_to_activate,
                        bool move_left,
                        DesksCreationRemovalSource source)
-      : DeskAnimationBase(controller),
+      : DeskAnimationBase(controller, desk_to_activate),
         desk_to_remove_(desk_to_remove),
         request_source_(source) {
     DCHECK(!Shell::Get()->overview_controller()->InOverviewSession());
@@ -330,6 +339,7 @@
 
   // DesksController::AbstractDeskSwitchAnimation:
   void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override {
+    DCHECK_EQ(ending_desk_, ending_desk);
     DCHECK_EQ(controller_->active_desk(), desk_to_remove_);
     // We are removing the active desk, which may have tablet split view active.
     // We will restore the split view state of the newly activated desk at the
@@ -393,6 +403,12 @@
   return Shell::Get()->desks_controller();
 }
 
+const Desk* DesksController::GetTargetActiveDesk() const {
+  if (!animations_.empty())
+    return animations_.back()->ending_desk();
+  return active_desk();
+}
+
 void DesksController::Shutdown() {
   animations_.clear();
 }
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 240af6a..38b0967a 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -71,6 +71,10 @@
 
   const Desk* active_desk() const { return active_desk_; }
 
+  // Returns the current |active_desk()| or the soon-to-be active desk if a desk
+  // switch animation is in progress.
+  const Desk* GetTargetActiveDesk() const;
+
   // Destroys any pending animations in preparation for shutdown.
   void Shutdown();
 
diff --git a/ash/wm/desks/desks_test_util.cc b/ash/wm/desks/desks_test_util.cc
index 2d6ce1fd..28a18a9 100644
--- a/ash/wm/desks/desks_test_util.cc
+++ b/ash/wm/desks/desks_test_util.cc
@@ -43,8 +43,9 @@
 void ActivateDesk(const Desk* desk) {
   ASSERT_FALSE(desk->is_active());
   DeskSwitchAnimationWaiter waiter;
-  DesksController::Get()->ActivateDesk(desk,
-                                       DesksSwitchSource::kMiniViewButton);
+  auto* desks_controller = DesksController::Get();
+  desks_controller->ActivateDesk(desk, DesksSwitchSource::kMiniViewButton);
+  EXPECT_EQ(desk, desks_controller->GetTargetActiveDesk());
   waiter.Wait();
   ASSERT_TRUE(desk->is_active());
 }
diff --git a/ash/wm/desks/desks_util.h b/ash/wm/desks/desks_util.h
index 2558a1c..65f84eb0 100644
--- a/ash/wm/desks/desks_util.h
+++ b/ash/wm/desks/desks_util.h
@@ -29,6 +29,11 @@
 
 ASH_EXPORT bool IsDeskContainerId(int id);
 
+// NOTE: The below *ActiveDesk* functions work with the currently active desk.
+// If they can be called during a desk-switch animation, you might be interested
+// in the soon-to-be active desk when the animation ends.
+// See `DesksController::GetTargetActiveDesk()`.
+
 ASH_EXPORT int GetActiveDeskContainerId();
 
 ASH_EXPORT bool IsActiveDeskContainer(const aura::Window* container);
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc
new file mode 100644
index 0000000..0d652ce7
--- /dev/null
+++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc
@@ -0,0 +1,342 @@
+// 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 "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
+
+#include "ash/app_list/app_list_controller_impl.h"
+#include "ash/display/screen_orientation_controller.h"
+#include "ash/home_screen/home_screen_controller.h"
+#include "ash/public/cpp/ash_features.h"
+#include "ash/session/session_controller_impl.h"
+#include "ash/shell.h"
+#include "ash/wm/gestures/back_gesture/back_gesture_affordance.h"
+#include "ash/wm/overview/overview_controller.h"
+#include "ash/wm/splitview/split_view_divider.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "ash/wm/tablet_mode/tablet_mode_window_manager.h"
+#include "ash/wm/window_state.h"
+#include "ash/wm/window_util.h"
+#include "ash/wm/wm_event.h"
+#include "base/metrics/user_metrics.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/wm/core/coordinate_conversion.h"
+
+namespace ash {
+
+namespace {
+
+// Distance from the divider's center point that reserved for splitview
+// resizing in landscape orientation.
+constexpr int kDistanceForSplitViewResize = 49;
+
+// Called by CanStartGoingBack() to check whether we can start swiping from the
+// split view divider to go back.
+bool CanStartGoingBackFromSplitViewDivider(const gfx::Point& screen_location) {
+  if (!IsCurrentScreenOrientationLandscape())
+    return false;
+
+  auto* root_window = window_util::GetRootWindowAt(screen_location);
+  auto* split_view_controller = SplitViewController::Get(root_window);
+  if (!split_view_controller->InTabletSplitViewMode())
+    return false;
+
+  // Do not enable back gesture if |screen_location| is inside the extended
+  // hotseat, let the hotseat handle the event instead.
+  Shelf* shelf = Shelf::ForWindow(root_window);
+  if (shelf->shelf_layout_manager()->hotseat_state() ==
+          HotseatState::kExtended &&
+      shelf->shelf_widget()
+          ->hotseat_widget()
+          ->GetWindowBoundsInScreen()
+          .Contains(screen_location)) {
+    return false;
+  }
+
+  // Do not enable back gesture if |screen_location| is inside the shelf widget,
+  // let the shelf handle the event instead.
+  if (shelf->shelf_widget()->GetWindowBoundsInScreen().Contains(
+          screen_location)) {
+    return false;
+  }
+
+  gfx::Rect divider_bounds =
+      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
+          /*is_dragging=*/false);
+  const int y_center = divider_bounds.CenterPoint().y();
+  // Do not enable back gesture if swiping starts from splitview divider's
+  // resizable area.
+  if (screen_location.y() >= (y_center - kDistanceForSplitViewResize) &&
+      screen_location.y() <= (y_center + kDistanceForSplitViewResize)) {
+    return false;
+  }
+
+  divider_bounds.set_x(divider_bounds.x() -
+                       SplitViewDivider::kDividerEdgeInsetForTouch);
+  divider_bounds.set_width(
+      divider_bounds.width() + SplitViewDivider::kDividerEdgeInsetForTouch +
+      BackGestureEventHandler::kStartGoingBackLeftEdgeInset);
+  return divider_bounds.Contains(screen_location);
+}
+
+// Activate the given |window|.
+void ActivateWindow(aura::Window* window) {
+  if (!window)
+    return;
+  WindowState::Get(window)->Activate();
+}
+
+// Activate the snapped window that is underneath the start |location| for back
+// gesture. This is necessary since the snapped window that is underneath is not
+// always the current active window.
+void ActivateUnderneathWindowInSplitViewMode(
+    const gfx::Point& location,
+    bool dragged_from_splitview_divider) {
+  auto* split_view_controller =
+      SplitViewController::Get(window_util::GetRootWindowAt(location));
+  if (!split_view_controller->InTabletSplitViewMode())
+    return;
+
+  auto* left_window = split_view_controller->left_window();
+  auto* right_window = split_view_controller->right_window();
+  const OrientationLockType current_orientation = GetCurrentScreenOrientation();
+  if (current_orientation == OrientationLockType::kLandscapePrimary) {
+    ActivateWindow(dragged_from_splitview_divider ? right_window : left_window);
+  } else if (current_orientation == OrientationLockType::kLandscapeSecondary) {
+    ActivateWindow(dragged_from_splitview_divider ? left_window : right_window);
+  } else {
+    if (left_window &&
+        split_view_controller
+            ->GetSnappedWindowBoundsInScreen(
+                SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr)
+            .Contains(location)) {
+      ActivateWindow(left_window);
+    } else if (right_window && split_view_controller
+                                   ->GetSnappedWindowBoundsInScreen(
+                                       SplitViewController::RIGHT,
+                                       /*window_for_minimum_size=*/nullptr)
+                                   .Contains(location)) {
+      ActivateWindow(right_window);
+    } else if (split_view_controller->split_view_divider()
+                   ->GetDividerBoundsInScreen(
+                       /*is_dragging=*/false)
+                   .Contains(location)) {
+      // Activate the window that above the splitview divider if back gesture
+      // starts from splitview divider.
+      ActivateWindow(IsCurrentScreenOrientationPrimary() ? left_window
+                                                         : right_window);
+    }
+  }
+}
+
+}  // namespace
+
+BackGestureEventHandler::BackGestureEventHandler()
+    : gesture_provider_(this, this) {
+  display::Screen::GetScreen()->AddObserver(this);
+}
+
+BackGestureEventHandler::~BackGestureEventHandler() {
+  display::Screen::GetScreen()->RemoveObserver(this);
+}
+
+void BackGestureEventHandler::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t metrics) {
+  // Cancel the left edge swipe back during screen rotation.
+  if (metrics & DISPLAY_METRIC_ROTATION) {
+    back_gesture_affordance_.reset();
+    going_back_started_ = false;
+  }
+}
+
+void BackGestureEventHandler::OnGestureEvent(ui::GestureEvent* event) {}
+
+void BackGestureEventHandler::OnTouchEvent(ui::TouchEvent* event) {
+  if (first_touch_id_ == ui::kPointerIdUnknown)
+    first_touch_id_ = event->pointer_details().id;
+
+  if (event->pointer_details().id != first_touch_id_)
+    return;
+
+  if (event->type() == ui::ET_TOUCH_RELEASED)
+    first_touch_id_ = ui::kPointerIdUnknown;
+
+  if (event->type() == ui::ET_TOUCH_PRESSED) {
+    x_drag_amount_ = y_drag_amount_ = 0;
+    during_reverse_dragging_ = false;
+  } else {
+    // TODO(oshima): Convert to PointF/float.
+    const gfx::Point current_location = event->location();
+    x_drag_amount_ += (current_location.x() - last_touch_point_.x());
+    y_drag_amount_ += (current_location.y() - last_touch_point_.y());
+
+    // Do not update |during_reverse_dragging_| if touch point's location
+    // doesn't change.
+    if (current_location.x() < last_touch_point_.x())
+      during_reverse_dragging_ = true;
+    else if (current_location.x() > last_touch_point_.x())
+      during_reverse_dragging_ = false;
+  }
+  last_touch_point_ = event->location();
+
+  ui::TouchEvent touch_event_copy = *event;
+  if (!gesture_provider_.OnTouchEvent(&touch_event_copy))
+    return;
+
+  gesture_provider_.OnTouchEventAck(
+      touch_event_copy.unique_event_id(), /*event_consumed=*/false,
+      /*is_source_touch_event_set_non_blocking=*/false);
+
+  // Get the event target from TouchEvent since target of the GestureEvent from
+  // GetAndResetPendingGestures is nullptr.
+  aura::Window* target = static_cast<aura::Window*>(event->target());
+  const std::vector<std::unique_ptr<ui::GestureEvent>> gestures =
+      gesture_provider_.GetAndResetPendingGestures();
+  for (const auto& gesture : gestures) {
+    if (MaybeHandleBackGesture(gesture.get(), target))
+      event->StopPropagation();
+  }
+}
+
+void BackGestureEventHandler::OnGestureEvent(GestureConsumer* consumer,
+                                             ui::GestureEvent* event) {
+  // Gesture events here are generated by |gesture_provider_|, and they're
+  // handled at OnTouchEvent() by calling MaybeHandleBackGesture().
+}
+
+bool BackGestureEventHandler::MaybeHandleBackGesture(ui::GestureEvent* event,
+                                                     aura::Window* target) {
+  DCHECK(features::IsSwipingFromLeftEdgeToGoBackEnabled());
+  DCHECK(target);
+  gfx::Point screen_location = event->location();
+  ::wm::ConvertPointToScreen(target, &screen_location);
+  switch (event->type()) {
+    case ui::ET_GESTURE_TAP_DOWN:
+      going_back_started_ = CanStartGoingBack(target, screen_location);
+      if (!going_back_started_)
+        break;
+      back_gesture_affordance_ = std::make_unique<BackGestureAffordance>(
+          screen_location, dragged_from_splitview_divider_);
+      return true;
+    case ui::ET_GESTURE_SCROLL_BEGIN:
+      if (!going_back_started_)
+        break;
+      back_start_location_ = screen_location;
+
+      base::RecordAction(base::UserMetricsAction("Ash_Tablet_BackGesture"));
+      back_gesture_start_scenario_type_ = GetStartScenarioType(
+          dragged_from_splitview_divider_, back_start_location_);
+      RecordStartScenarioType(back_gesture_start_scenario_type_);
+      break;
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      if (!going_back_started_)
+        break;
+      DCHECK(back_gesture_affordance_);
+      back_gesture_affordance_->Update(x_drag_amount_, y_drag_amount_,
+                                       during_reverse_dragging_);
+      return true;
+    case ui::ET_GESTURE_SCROLL_END:
+    case ui::ET_SCROLL_FLING_START: {
+      if (!going_back_started_)
+        break;
+      DCHECK(back_gesture_affordance_);
+      BackGestureEndType end_type = BackGestureEndType::kNone;
+      if (back_gesture_affordance_->IsActivated() ||
+          (event->type() == ui::ET_SCROLL_FLING_START &&
+           event->details().velocity_x() >= kFlingVelocityForGoingBack)) {
+        ActivateUnderneathWindowInSplitViewMode(
+            back_start_location_, dragged_from_splitview_divider_);
+        auto* top_window_state =
+            WindowState::Get(TabletModeWindowManager::GetTopWindow());
+        if (top_window_state && top_window_state->IsFullscreen() &&
+            !Shell::Get()->overview_controller()->InOverviewSession()) {
+          const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
+          top_window_state->OnWMEvent(&event);
+          RecordEndScenarioType(BackGestureEndScenarioType::kExitFullscreen);
+          return true;
+        }
+
+        if (TabletModeWindowManager::ShouldMinimizeTopWindowOnBack()) {
+          top_window_state->Minimize();
+          end_type = BackGestureEndType::kMinimize;
+        } else {
+          aura::Window* root_window =
+              window_util::GetRootWindowAt(screen_location);
+          ui::KeyEvent press_key_event(ui::ET_KEY_PRESSED,
+                                       ui::VKEY_BROWSER_BACK, ui::EF_NONE);
+          ignore_result(
+              root_window->GetHost()->SendEventToSink(&press_key_event));
+          ui::KeyEvent release_key_event(ui::ET_KEY_RELEASED,
+                                         ui::VKEY_BROWSER_BACK, ui::EF_NONE);
+          ignore_result(
+              root_window->GetHost()->SendEventToSink(&release_key_event));
+          end_type = BackGestureEndType::kBack;
+        }
+        back_gesture_affordance_->Complete();
+      } else {
+        back_gesture_affordance_->Abort();
+        end_type = BackGestureEndType::kAbort;
+      }
+      RecordEndScenarioType(
+          GetEndScenarioType(back_gesture_start_scenario_type_, end_type));
+      RecordUnderneathWindowType(
+          GetUnderneathWindowType(back_gesture_start_scenario_type_));
+      return true;
+    }
+    case ui::ET_GESTURE_END:
+      going_back_started_ = false;
+      dragged_from_splitview_divider_ = false;
+      break;
+    default:
+      break;
+  }
+
+  return going_back_started_;
+}
+
+bool BackGestureEventHandler::CanStartGoingBack(
+    aura::Window* target,
+    const gfx::Point& screen_location) {
+  DCHECK(features::IsSwipingFromLeftEdgeToGoBackEnabled());
+
+  Shell* shell = Shell::Get();
+  if (!shell->tablet_mode_controller()->InTabletMode())
+    return false;
+
+  // Do not enable back gesture if it is not in an ACTIVE session. e.g, login
+  // screen, lock screen.
+  if (shell->session_controller()->GetSessionState() !=
+      session_manager::SessionState::ACTIVE) {
+    return false;
+  }
+
+  // Do not enable back gesture if home screen is visible but not in
+  // |kFullscreenSearch| state.
+  if (shell->home_screen_controller()->IsHomeScreenVisible() &&
+      shell->app_list_controller()->GetAppListViewState() !=
+          AppListViewState::kFullscreenSearch) {
+    return false;
+  }
+
+  // Do not enable back gesture if MRU window list is empty and it is not in
+  // overview mode.
+  if (!Shell::Get()->overview_controller()->InOverviewSession() &&
+      !TabletModeWindowManager::GetTopWindow()) {
+    return false;
+  }
+
+  gfx::Rect hit_bounds_in_screen(display::Screen::GetScreen()
+                                     ->GetDisplayNearestWindow(target)
+                                     .work_area());
+  hit_bounds_in_screen.set_width(kStartGoingBackLeftEdgeInset);
+  if (hit_bounds_in_screen.Contains(screen_location))
+    return true;
+
+  dragged_from_splitview_divider_ =
+      CanStartGoingBackFromSplitViewDivider(screen_location);
+  return dragged_from_splitview_divider_;
+}
+
+}  // namespace ash
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler.h b/ash/wm/gestures/back_gesture/back_gesture_event_handler.h
new file mode 100644
index 0000000..3526414
--- /dev/null
+++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler.h
@@ -0,0 +1,107 @@
+// 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 ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_
+#define ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_
+
+#include "ash/wm/gestures/back_gesture/back_gesture_metrics.h"
+#include "ui/display/display_observer.h"
+#include "ui/events/event_handler.h"
+#include "ui/events/gestures/gesture_provider_aura.h"
+
+namespace aura {
+class Window;
+}  // namespace aura
+
+namespace ash {
+
+class BackGestureAffordance;
+
+class BackGestureEventHandler : public display::DisplayObserver,
+                                public ui::EventHandler,
+                                public ui::GestureConsumer,
+                                public ui::GestureProviderAuraClient {
+ public:
+  // The threshold of the fling velocity while fling from left edge to go
+  // previous page.
+  static constexpr int kFlingVelocityForGoingBack = 1000;
+
+  // How many dips are reserved for gesture events to start swiping to previous
+  // page from the left edge of the screen in tablet mode.
+  static constexpr int kStartGoingBackLeftEdgeInset = 16;
+
+  BackGestureEventHandler();
+  ~BackGestureEventHandler() override;
+
+  // display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t metrics) override;
+
+  // ui::EventHandler:
+  void OnGestureEvent(ui::GestureEvent* event) override;
+  void OnTouchEvent(ui::TouchEvent* event) override;
+
+  // ui::GestureProviderAuraClient:
+  void OnGestureEvent(GestureConsumer* consumer,
+                      ui::GestureEvent* event) override;
+
+ private:
+  // Returns true if |event| was handled as a go-back gesture. |event| is
+  // generated by |gesture_provider_| from touch event, its target will be
+  // nullptr. Gets |target| from corresponding touch event instead.
+  bool MaybeHandleBackGesture(ui::GestureEvent* event, aura::Window* target);
+
+  // True if we can start swiping from left edge of the display or splitview
+  // divider to go back.
+  bool CanStartGoingBack(aura::Window* window,
+                         const gfx::Point& screen_location);
+
+  // True if swiping from left edge to go to previous page is in progress.
+  bool going_back_started_ = false;
+
+  // Tracks the x-axis and y-axis drag amount through touch events. Used for
+  // back gesture affordance in tablet mode. The gesture movement of back
+  // gesture can't be recognized by GestureRecognizer, which leads to wrong
+  // gesture locations of back gesture. See crbug.com/1015464 for the details.
+  int x_drag_amount_ = 0;
+  int y_drag_amount_ = 0;
+
+  // True if back gesture dragging on the negative direction of x-axis.
+  bool during_reverse_dragging_ = false;
+
+  // Position of last touch event. Used to calculate |y_drag_amount_|. Note,
+  // only touch events from |first_touch_id_| will be recorded.
+  gfx::Point last_touch_point_;
+  ui::PointerId first_touch_id_ = ui::kPointerIdUnknown;
+
+  // Used to show the affordance while swiping from left edge to go to the
+  // previout page.
+  std::unique_ptr<BackGestureAffordance> back_gesture_affordance_;
+
+  // True if back gesture dragged from splitview divider.
+  bool dragged_from_splitview_divider_ = false;
+
+  // Start location of the back gesture in screen coordinate. Used by
+  // ActivateUnderneathWindowInSplitViewMode() to determine the snapped window
+  // that should be activated for going back.
+  gfx::Point back_start_location_;
+
+  // A GestureProvider that is created for back gesture. Used to handle tap down
+  // and the possibly following gesture scroll sequence for back gesture in
+  // OnTouchEvent session. This is done to avoid tap down event be used by the
+  // window that is underneath to do other things (e.g, highlight a menu item)
+  // instead of going back.
+  ui::GestureProviderAura gesture_provider_;
+
+  // Start scenario type of the back gesture, used for related metrics.
+  BackGestureStartScenarioType back_gesture_start_scenario_type_ =
+      BackGestureStartScenarioType::kMaxValue;
+
+  BackGestureEventHandler(const BackGestureEventHandler&) = delete;
+  BackGestureEventHandler& operator=(const BackGestureEventHandler&) = delete;
+};
+
+}  // namespace ash
+
+#endif  // ASH_WM_GESTURES_BACK_GESTURE_BACK_GESTURE_EVENT_HANDLER_H_
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler_unittest.cc b/ash/wm/gestures/back_gesture/back_gesture_event_handler_unittest.cc
new file mode 100644
index 0000000..b32a31c
--- /dev/null
+++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler_unittest.cc
@@ -0,0 +1,502 @@
+// 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 "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
+
+#include "ash/accelerators/accelerator_controller_impl.h"
+#include "ash/app_list/test/app_list_test_helper.h"
+#include "ash/app_list/views/app_list_view.h"
+#include "ash/app_list/views/search_box_view.h"
+#include "ash/display/screen_orientation_controller.h"
+#include "ash/display/screen_orientation_controller_test_api.h"
+#include "ash/home_screen/home_screen_controller.h"
+#include "ash/public/cpp/ash_features.h"
+#include "ash/screen_util.h"
+#include "ash/session/session_controller_impl.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "ash/test_shell_delegate.h"
+#include "ash/wm/overview/overview_controller.h"
+#include "ash/wm/splitview/split_view_divider.h"
+#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
+#include "ash/wm/tablet_mode/tablet_mode_window_manager.h"
+#include "ash/wm/window_state.h"
+#include "ash/wm/window_util.h"
+#include "ash/wm/wm_event.h"
+#include "base/test/scoped_feature_list.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/accelerators/test_accelerator_target.h"
+#include "ui/display/test/display_manager_test_api.h"
+
+namespace ash {
+
+class BackGestureEventHandlerTest : public AshTestBase {
+ public:
+  // Distance that swiping from left edge to let the affordance achieve
+  // activated state.
+  static constexpr int kSwipingDistanceForGoingBack = 80;
+
+  BackGestureEventHandlerTest() = default;
+  ~BackGestureEventHandlerTest() override = default;
+
+  void SetUp() override {
+    AshTestBase::SetUp();
+
+    feature_list_.InitAndEnableFeature(features::kSwipingFromLeftEdgeToGoBack);
+    top_window_ = CreateAppWindow(gfx::Rect(), AppType::BROWSER);
+    TabletModeControllerTestApi().EnterTabletMode();
+  }
+
+  void TearDown() override {
+    top_window_.reset();
+    AshTestBase::TearDown();
+  }
+
+  void RegisterBackPressAndRelease(ui::TestAcceleratorTarget* back_press,
+                                   ui::TestAcceleratorTarget* back_release) {
+    AcceleratorControllerImpl* controller =
+        Shell::Get()->accelerator_controller();
+
+    // Register an accelerator that looks for back presses.
+    ui::Accelerator accelerator_back_press(ui::VKEY_BROWSER_BACK, ui::EF_NONE);
+    accelerator_back_press.set_key_state(ui::Accelerator::KeyState::PRESSED);
+    controller->Register({accelerator_back_press}, back_press);
+
+    // Register an accelerator that looks for back releases.
+    ui::Accelerator accelerator_back_release(ui::VKEY_BROWSER_BACK,
+                                             ui::EF_NONE);
+    accelerator_back_release.set_key_state(ui::Accelerator::KeyState::RELEASED);
+    controller->Register({accelerator_back_release}, back_release);
+  }
+
+  // Send touch event with |type| to the toplevel window event handler.
+  void SendTouchEvent(const gfx::Point& position, ui::EventType type) {
+    ui::TouchEvent event = ui::TouchEvent(
+        type, position, base::TimeTicks::Now(),
+        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
+                           /*pointer_id=*/5, /*radius_x=*/5.0f,
+                           /*radius_y=*/5.0, /*force=*/1.0f));
+    ui::Event::DispatcherApi(&event).set_target(top_window_.get());
+    Shell::Get()->back_gesture_event_handler()->OnTouchEvent(&event);
+  }
+
+  aura::Window* top_window() { return top_window_.get(); }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+  std::unique_ptr<aura::Window> top_window_;
+
+  BackGestureEventHandlerTest(const BackGestureEventHandlerTest&) = delete;
+  BackGestureEventHandlerTest& operator=(const BackGestureEventHandlerTest&) =
+      delete;
+};
+
+TEST_F(BackGestureEventHandlerTest, SwipingFromLeftEdgeToGoBack) {
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  // Tests that swiping from the left less than |kSwipingDistanceForGoingBack|
+  // should not go to previous page.
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  const gfx::Point start(0, 100);
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack - 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+
+  // Tests that swiping from the left more than |kSwipingDistanceForGoingBack|
+  // should go to previous page.
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+}
+
+TEST_F(BackGestureEventHandlerTest, FlingFromLeftEdgeToGoBack) {
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  // Tests that fling from the left with velocity smaller than
+  // |kFlingVelocityForGoingBack| should not go to previous page.
+  // Drag further than |touch_slop| in GestureDetector to trigger scroll
+  // sequence. Note, |touch_slop| equals to 15.05, which is the value of
+  // |max_touch_move_in_pixels_for_click_| + |kSlopEpsilon|. Generate the scroll
+  // sequence with short duration and only one step for FLING scroll gestures.
+  // X-velocity here will be 800 dips/seconds.
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(16, 0),
+                                   base::TimeDelta::FromMilliseconds(20),
+                                   /*steps=*/1);
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+
+  // Tests that fling from the left with velocity larger than
+  // |kFlingVelocityForGoingBack| should go to previous page. X-velocity here
+  // will be 1600 dips/seconds.
+  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(16, 0),
+                                   base::TimeDelta::FromMilliseconds(1),
+                                   /*steps=*/1);
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+
+  // Tests that fling from the left with velocity smaller than
+  // |kFlingVelocityForGoingBack| but dragged further enough to trigger
+  // activated affordance should still go back to previous page. X-velocity here
+  // will be 800 dips/seconds and drag distance is 160, which is larger than
+  // |kSwipingDistanceForGoingBack|.
+  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(160, 0),
+                                   base::TimeDelta::FromMilliseconds(200),
+                                   /*steps=*/1);
+  EXPECT_EQ(2, target_back_press.accelerator_count());
+  EXPECT_EQ(2, target_back_release.accelerator_count());
+}
+
+TEST_F(BackGestureEventHandlerTest, GoBackInOverviewMode) {
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  ash_test_helper()->test_shell_delegate()->SetCanGoBack(false);
+  ASSERT_FALSE(WindowState::Get(top_window())->IsMinimized());
+  ASSERT_TRUE(TabletModeWindowManager::ShouldMinimizeTopWindowOnBack());
+  GetEventGenerator()->GestureScrollSequence(
+      gfx::Point(0, 100), gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  // Should trigger window minimize instead of go back.
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+  EXPECT_TRUE(WindowState::Get(top_window())->IsMinimized());
+
+  WindowState::Get(top_window())->Unminimize();
+  ASSERT_FALSE(WindowState::Get(top_window())->IsMinimized());
+  auto* shell = Shell::Get();
+  shell->overview_controller()->StartOverview();
+  ASSERT_TRUE(shell->overview_controller()->InOverviewSession());
+  GetEventGenerator()->GestureScrollSequence(
+      gfx::Point(0, 100), gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  // Should trigger go back instead of minimize the window since it is in
+  // overview mode.
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+}
+
+TEST_F(BackGestureEventHandlerTest, DonotStartGoingBack) {
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  auto* shell = Shell::Get();
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  const gfx::Point start(0, 100);
+
+  // Should not go back if it is not in ACTIVE session.
+  ASSERT_FALSE(shell->overview_controller()->InOverviewSession());
+  ASSERT_FALSE(shell->home_screen_controller()->IsHomeScreenVisible());
+  GetSessionControllerClient()->SetSessionState(
+      session_manager::SessionState::LOCKED);
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+
+  // Should not go back if home screen is visible and in |kFullscreenAllApps|
+  // state.
+  GetSessionControllerClient()->SetSessionState(
+      session_manager::SessionState::ACTIVE);
+  shell->home_screen_controller()->GoHome(GetPrimaryDisplay().id());
+  ASSERT_TRUE(shell->home_screen_controller()->IsHomeScreenVisible());
+  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+
+  // Should exit |kFullscreenSearch| to enter |kFullscreenAllApps| state while
+  // home screen search result page is opened.
+  generator->GestureTapAt(GetAppListTestHelper()
+                              ->GetAppListView()
+                              ->search_box_view()
+                              ->GetBoundsInScreen()
+                              .CenterPoint());
+  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
+}
+
+TEST_F(BackGestureEventHandlerTest, CancelOnScreenRotation) {
+  UpdateDisplay("807x407");
+  int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+  display::test::ScopedSetInternalDisplayId set_internal(display_manager,
+                                                         display_id);
+  ScreenOrientationControllerTestApi test_api(
+      Shell::Get()->screen_orientation_controller());
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  // Set the screen orientation to LANDSCAPE_PRIMARY.
+  test_api.SetDisplayRotation(display::Display::ROTATE_0,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kLandscapePrimary);
+
+  gfx::Point start(0, 100);
+  gfx::Point update_and_end(200, 100);
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  // Rotate the screen by 270 degree during drag.
+  test_api.SetDisplayRotation(display::Display::ROTATE_270,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kPortraitPrimary);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Left edge swipe back should be cancelled due to screen rotation, so the
+  // fling event with velocity larger than |kFlingVelocityForGoingBack| above
+  // will not trigger actual going back.
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+}
+
+// Tests back gesture while in split view mode.
+TEST_F(BackGestureEventHandlerTest, DragFromSplitViewDivider) {
+  std::unique_ptr<aura::Window> window1 = CreateTestWindow();
+  std::unique_ptr<aura::Window> window2 = CreateTestWindow();
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  gfx::Rect display_bounds =
+      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
+          window1.get());
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  auto* split_view_controller =
+      SplitViewController::Get(Shell::GetPrimaryRootWindow());
+  split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
+  split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
+  ASSERT_TRUE(split_view_controller->InSplitViewMode());
+  ASSERT_EQ(SplitViewController::State::kBothSnapped,
+            split_view_controller->state());
+
+  gfx::Rect divider_bounds =
+      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
+          false);
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  // Drag from the splitview divider's non-resizable area with larger than
+  // |kSwipingDistanceForGoingBack| distance should trigger back gesture. The
+  // snapped window should go to previous page and divider's position will not
+  // be changed.
+  gfx::Point start(divider_bounds.x(), 10);
+  gfx::Point end(start.x() + kSwipingDistanceForGoingBack + 10, 10);
+  EXPECT_GT(split_view_controller->divider_position(),
+            0.33f * display_bounds.width());
+  EXPECT_LE(split_view_controller->divider_position(),
+            0.5f * display_bounds.width());
+  generator->GestureScrollSequence(start, end,
+                                   base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(SplitViewController::State::kBothSnapped,
+            split_view_controller->state());
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+  EXPECT_GT(split_view_controller->divider_position(),
+            0.33f * display_bounds.width());
+  EXPECT_LE(split_view_controller->divider_position(),
+            0.5f * display_bounds.width());
+
+  // Drag from the divider's resizable area should trigger splitview resizing.
+  // Divider's position will be changed and back gesture should not be
+  // triggered.
+  start = divider_bounds.CenterPoint();
+  end = gfx::Point(0.67f * display_bounds.width(), start.y());
+  generator->GestureScrollSequence(start, end,
+                                   base::TimeDelta::FromMilliseconds(100), 3);
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+  EXPECT_GT(split_view_controller->divider_position(),
+            0.5f * display_bounds.width());
+  EXPECT_LE(split_view_controller->divider_position(),
+            0.67f * display_bounds.width());
+  split_view_controller->EndSplitView();
+}
+
+// Tests that in different screen orientations should always activate the
+// snapped window in splitview that is underneath the finger. And should be the
+// snapped window that is underneath to go back to the previous page.
+TEST_F(BackGestureEventHandlerTest, BackInSplitViewMode) {
+  int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
+  display::DisplayManager* display_manager = Shell::Get()->display_manager();
+  display::test::ScopedSetInternalDisplayId set_internal(display_manager,
+                                                         display_id);
+  ScreenOrientationControllerTestApi test_api(
+      Shell::Get()->screen_orientation_controller());
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  std::unique_ptr<aura::Window> left_window = CreateTestWindow();
+  std::unique_ptr<aura::Window> right_window = CreateTestWindow();
+  auto* split_view_controller =
+      SplitViewController::Get(Shell::GetPrimaryRootWindow());
+  split_view_controller->SnapWindow(left_window.get(),
+                                    SplitViewController::LEFT);
+  split_view_controller->SnapWindow(right_window.get(),
+                                    SplitViewController::RIGHT);
+
+  // Set the screen orientation to LANDSCAPE_PRIMARY.
+  test_api.SetDisplayRotation(display::Display::ROTATE_0,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kLandscapePrimary);
+
+  ASSERT_EQ(right_window.get(), window_util::GetActiveWindow());
+  gfx::Point start(0, 10);
+  gfx::Point update_and_end(kSwipingDistanceForGoingBack + 10, 10);
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the display in LandscapePrimary further than
+  // |kSwipingDistanceForGoingBack| should activate the physically left snapped
+  // window, which is |left_window| and it should go back to the previous page.
+  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+
+  gfx::Rect divider_bounds =
+      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
+          false);
+  start = gfx::Point(divider_bounds.x(), 10);
+  update_and_end =
+      gfx::Point(divider_bounds.x() + kSwipingDistanceForGoingBack + 10, 10);
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the split view divider in LandscapePrimary further than
+  // |kSwipingDistanceForGoingBack| should activate the physically right snapped
+  // window, which is |right_window| and it should go back to the previous page.
+  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(2, target_back_press.accelerator_count());
+  EXPECT_EQ(2, target_back_release.accelerator_count());
+
+  // Rotate the screen by 180 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_180,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kLandscapeSecondary);
+
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the split view divider in LandscapeSecondary further than
+  // |kSwipingDistanceForGoingBack| should activate the physically right snapped
+  // window, which is |left_window| and it should go back to the previous page.
+  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(3, target_back_press.accelerator_count());
+  EXPECT_EQ(3, target_back_release.accelerator_count());
+
+  start = gfx::Point(0, 10);
+  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, 10);
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the display in LandscapeSecondary further than
+  // |kSwipingDistanceForGoingBack| should activate the physically left snapped
+  // window, which is |right_window| and it should go back to the previous page.
+  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(4, target_back_press.accelerator_count());
+  EXPECT_EQ(4, target_back_release.accelerator_count());
+
+  // Rotate the screen by 270 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_270,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kPortraitPrimary);
+
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the top half of the display in PortraitPrimary
+  // further than |kSwipingDistanceForGoingBack| should activate the physically
+  // top snapped window, which is |right_window|, and it should go back to the
+  // previous page.
+  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(5, target_back_press.accelerator_count());
+  EXPECT_EQ(5, target_back_release.accelerator_count());
+
+  divider_bounds =
+      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
+          false);
+  start = gfx::Point(0, divider_bounds.bottom() + 10);
+  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, start.y());
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the bottom half of the display in PortraitPrimary
+  // further than |kSwipingDistanceForGoingBack| should activate the physically
+  // bottom snapped window, which is |right_window|, and it should go back to
+  // the previous page.
+  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(6, target_back_press.accelerator_count());
+  EXPECT_EQ(6, target_back_release.accelerator_count());
+
+  // Rotate the screen by 90 degree.
+  test_api.SetDisplayRotation(display::Display::ROTATE_90,
+                              display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(test_api.GetCurrentOrientation(),
+            OrientationLockType::kPortraitSecondary);
+
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the bottom half of the display in
+  // PortraitSecondary further than |kSwipingDistanceForGoingBack| should
+  // activate the physically bottom snapped window, which is |left_window|, and
+  // it should go back to the previous page.
+  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(7, target_back_press.accelerator_count());
+  EXPECT_EQ(7, target_back_release.accelerator_count());
+
+  start = gfx::Point(0, 10);
+  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, 10);
+  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
+  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
+  // Swiping from the left of the top half of the display in PortraitSecondary
+  // further than |kSwipingDistanceForGoingBack| should activate the physically
+  // top snapped window, which is |right_window| and it should go back to the
+  // previous page.
+  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
+  EXPECT_EQ(8, target_back_press.accelerator_count());
+  EXPECT_EQ(8, target_back_release.accelerator_count());
+}
+
+// Tests the back gesture behavior on a fullscreen'ed window.
+TEST_F(BackGestureEventHandlerTest, FullscreenedWindow) {
+  ui::TestAcceleratorTarget target_back_press, target_back_release;
+  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
+
+  WindowState* window_state = WindowState::Get(top_window());
+  const WMEvent fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
+  window_state->OnWMEvent(&fullscreen_event);
+  EXPECT_TRUE(window_state->IsFullscreen());
+
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  const gfx::Point start(0, 100);
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  // First back gesture should let the window exit fullscreen mode instead of
+  // triggering go back.
+  EXPECT_FALSE(window_state->IsFullscreen());
+  EXPECT_EQ(0, target_back_press.accelerator_count());
+  EXPECT_EQ(0, target_back_release.accelerator_count());
+
+  generator->GestureScrollSequence(
+      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
+      base::TimeDelta::FromMilliseconds(100), 3);
+  // Second back gesture should trigger go back.
+  EXPECT_EQ(1, target_back_press.accelerator_count());
+  EXPECT_EQ(1, target_back_release.accelerator_count());
+}
+
+}  // namespace ash
diff --git a/ash/wm/mru_window_tracker.h b/ash/wm/mru_window_tracker.h
index 3f813d4..800f943 100644
--- a/ash/wm/mru_window_tracker.h
+++ b/ash/wm/mru_window_tracker.h
@@ -21,6 +21,11 @@
   kAllDesks,
 
   // The MRU window list will exclude windows from the inactive desks.
+  //
+  // NOTE: During an on-going desk-switch animation, getting the MRU window list
+  // for the active desk can be inconsistent, depending on at which stage of the
+  // animation it is done. If you want the MRU windows in the soon-to-be active
+  // desk, then wait for the animation to finish.
   kActiveDesk,
 };
 
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 4225dc20..475a8678 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -33,6 +33,7 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/drag_window_resizer.h"
+#include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_constants.h"
 #include "ash/wm/overview/overview_controller.h"
@@ -2915,7 +2916,7 @@
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   GetEventGenerator()->GestureTapAt(
-      gfx::Point(ToplevelWindowEventHandler::kStartGoingBackLeftEdgeInset, 10));
+      gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset, 10));
   ShellTestApi().WaitForOverviewAnimationState(
       OverviewAnimationState::kExitAnimationComplete);
 
@@ -3173,13 +3174,11 @@
   OverviewItem* leftmost_window = GetOverviewItemForWindow(windows[0].get());
 
   GenerateScrollSequence(
-      gfx::Point(ToplevelWindowEventHandler::kStartGoingBackLeftEdgeInset + 5,
-                 50),
+      gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset + 5, 50),
       gfx::Point(5000, 50));
   const gfx::RectF left_bounds = leftmost_window->target_bounds();
   GenerateScrollSequence(
-      gfx::Point(ToplevelWindowEventHandler::kStartGoingBackLeftEdgeInset + 5,
-                 50),
+      gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset + 5, 50),
       gfx::Point(5000, 50));
   EXPECT_EQ(left_bounds, leftmost_window->target_bounds());
 
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index ed1b4d8..0c818c88 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -4,29 +4,15 @@
 
 #include "ash/wm/toplevel_window_event_handler.h"
 
-#include "ash/app_list/app_list_controller_impl.h"
-#include "ash/display/screen_orientation_controller.h"
-#include "ash/home_screen/home_screen_controller.h"
-#include "ash/public/cpp/app_list/app_list_types.h"
 #include "ash/public/cpp/app_types.h"
-#include "ash/public/cpp/ash_features.h"
-#include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
-#include "ash/wm/gestures/back_gesture/back_gesture_affordance.h"
-#include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/resize_shadow_controller.h"
-#include "ash/wm/splitview/split_view_divider.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_manager.h"
 #include "ash/wm/window_resizer.h"
-#include "ash/wm/window_state.h"
 #include "ash/wm/window_state_observer.h"
 #include "ash/wm/window_util.h"
-#include "ash/wm/wm_event.h"
-#include "base/metrics/user_metrics.h"
 #include "base/run_loop.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/window_types.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -36,7 +22,6 @@
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/hit_test.h"
 #include "ui/events/event.h"
-#include "ui/events/gestures/gesture_recognizer.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
 
@@ -48,10 +33,6 @@
 // window from the top of the screen in tablet mode.
 constexpr int kDragStartTopEdgeInset = 8;
 
-// Distance from the divider's center point that reserved for splitview
-// resizing in landscape orientation.
-constexpr int kDistanceForSplitViewResize = 49;
-
 // Returns whether |window| can be moved via a two finger drag given
 // the hittest results of the two fingers.
 bool CanStartTwoFingerMove(aura::Window* window,
@@ -109,105 +90,6 @@
   run_loop->Quit();
 }
 
-// Called by CanStartGoingBack() to check whether we can start swiping from the
-// split view divider to go back.
-bool CanStartGoingBackFromSplitViewDivider(const gfx::Point& screen_location) {
-  if (!IsCurrentScreenOrientationLandscape())
-    return false;
-
-  auto* root_window = window_util::GetRootWindowAt(screen_location);
-  auto* split_view_controller = SplitViewController::Get(root_window);
-  if (!split_view_controller->InTabletSplitViewMode())
-    return false;
-
-  // Do not enable back gesture if |screen_location| is inside the extended
-  // hotseat, let the hotseat handle the event instead.
-  Shelf* shelf = Shelf::ForWindow(root_window);
-  if (shelf->shelf_layout_manager()->hotseat_state() ==
-          HotseatState::kExtended &&
-      shelf->shelf_widget()
-          ->hotseat_widget()
-          ->GetWindowBoundsInScreen()
-          .Contains(screen_location)) {
-    return false;
-  }
-
-  // Do not enable back gesture if |screen_location| is inside the shelf widget,
-  // let the shelf handle the event instead.
-  if (shelf->shelf_widget()->GetWindowBoundsInScreen().Contains(
-          screen_location)) {
-    return false;
-  }
-
-  gfx::Rect divider_bounds =
-      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
-          /*is_dragging=*/false);
-  const int y_center = divider_bounds.CenterPoint().y();
-  // Do not enable back gesture if swiping starts from splitview divider's
-  // resizable area.
-  if (screen_location.y() >= (y_center - kDistanceForSplitViewResize) &&
-      screen_location.y() <= (y_center + kDistanceForSplitViewResize)) {
-    return false;
-  }
-
-  divider_bounds.set_x(divider_bounds.x() -
-                       SplitViewDivider::kDividerEdgeInsetForTouch);
-  divider_bounds.set_width(
-      divider_bounds.width() + SplitViewDivider::kDividerEdgeInsetForTouch +
-      ToplevelWindowEventHandler::kStartGoingBackLeftEdgeInset);
-  return divider_bounds.Contains(screen_location);
-}
-
-// Activate the given |window|.
-void ActivateWindow(aura::Window* window) {
-  if (!window)
-    return;
-  WindowState::Get(window)->Activate();
-}
-
-// Activate the snapped window that is underneath the start |location| for back
-// gesture. This is necessary since the snapped window that is underneath is not
-// always the current active window.
-void ActivateUnderneathWindowInSplitViewMode(
-    const gfx::Point& location,
-    bool dragged_from_splitview_divider) {
-  auto* split_view_controller =
-      SplitViewController::Get(window_util::GetRootWindowAt(location));
-  if (!split_view_controller->InTabletSplitViewMode())
-    return;
-
-  auto* left_window = split_view_controller->left_window();
-  auto* right_window = split_view_controller->right_window();
-  const OrientationLockType current_orientation = GetCurrentScreenOrientation();
-  if (current_orientation == OrientationLockType::kLandscapePrimary) {
-    ActivateWindow(dragged_from_splitview_divider ? right_window : left_window);
-  } else if (current_orientation == OrientationLockType::kLandscapeSecondary) {
-    ActivateWindow(dragged_from_splitview_divider ? left_window : right_window);
-  } else {
-    if (left_window &&
-        split_view_controller
-            ->GetSnappedWindowBoundsInScreen(
-                SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr)
-            .Contains(location)) {
-      ActivateWindow(left_window);
-    } else if (right_window && split_view_controller
-                                   ->GetSnappedWindowBoundsInScreen(
-                                       SplitViewController::RIGHT,
-                                       /*window_for_minimum_size=*/nullptr)
-                                   .Contains(location)) {
-      ActivateWindow(right_window);
-    } else if (split_view_controller->split_view_divider()
-                   ->GetDividerBoundsInScreen(
-                       /*is_dragging=*/false)
-                   .Contains(location)) {
-      // Activate the window that above the splitview divider if back gesture
-      // starts from splitview divider.
-      ActivateWindow(IsCurrentScreenOrientationPrimary() ? left_window
-                                                         : right_window);
-    }
-  }
-}
-
 }  // namespace
 
 // -----------------------------------------------------------------------------
@@ -305,7 +187,7 @@
 // ToplevelWindowEventHandler:
 
 ToplevelWindowEventHandler::ToplevelWindowEventHandler()
-    : first_finger_hittest_(HTNOWHERE), gesture_provider_(this, this) {
+    : first_finger_hittest_(HTNOWHERE) {
   Shell::Get()->window_tree_host_manager()->AddObserver(this);
   display::Screen::GetScreen()->AddObserver(this);
 }
@@ -318,12 +200,6 @@
 void ToplevelWindowEventHandler::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t metrics) {
-  // Cancel the left edge swipe back during screen rotation.
-  if (metrics & DISPLAY_METRIC_ROTATION) {
-    back_gesture_affordance_.reset();
-    going_back_started_ = false;
-  }
-
   if (!window_resizer_ || !(metrics & DISPLAY_METRIC_ROTATION))
     return;
 
@@ -568,63 +444,6 @@
   }
 }
 
-void ToplevelWindowEventHandler::OnTouchEvent(ui::TouchEvent* event) {
-  // The logic inside OnTouchEvent is only for back gesture currently.
-  if (!features::IsSwipingFromLeftEdgeToGoBackEnabled())
-    return;
-
-  if (first_touch_id_ == ui::kPointerIdUnknown)
-    first_touch_id_ = event->pointer_details().id;
-
-  if (event->pointer_details().id != first_touch_id_)
-    return;
-
-  if (event->type() == ui::ET_TOUCH_RELEASED)
-    first_touch_id_ = ui::kPointerIdUnknown;
-
-  if (event->type() == ui::ET_TOUCH_PRESSED) {
-    x_drag_amount_ = y_drag_amount_ = 0;
-    during_reverse_dragging_ = false;
-  } else {
-    // TODO(oshima): Convert to PointF/float.
-    const gfx::Point current_location = event->location();
-    x_drag_amount_ += (current_location.x() - last_touch_point_.x());
-    y_drag_amount_ += (current_location.y() - last_touch_point_.y());
-
-    // Do not update |during_reverse_dragging_| if touch point's location
-    // doesn't change.
-    if (current_location.x() < last_touch_point_.x())
-      during_reverse_dragging_ = true;
-    else if (current_location.x() > last_touch_point_.x())
-      during_reverse_dragging_ = false;
-  }
-  last_touch_point_ = event->location();
-
-  ui::TouchEvent touch_event_copy = *event;
-  if (!gesture_provider_.OnTouchEvent(&touch_event_copy))
-    return;
-
-  gesture_provider_.OnTouchEventAck(
-      touch_event_copy.unique_event_id(), /*event_consumed=*/false,
-      /*is_source_touch_event_set_non_blocking=*/false);
-
-  // Get the event target from TouchEvent since target of the GestureEvent from
-  // GetAndResetPendingGestures is nullptr.
-  aura::Window* target = static_cast<aura::Window*>(event->target());
-  const std::vector<std::unique_ptr<ui::GestureEvent>> gestures =
-      gesture_provider_.GetAndResetPendingGestures();
-  for (const auto& gesture : gestures) {
-    if (MaybeHandleBackGesture(gesture.get(), target))
-      event->StopPropagation();
-  }
-}
-
-void ToplevelWindowEventHandler::OnGestureEvent(GestureConsumer* consumer,
-                                                ui::GestureEvent* event) {
-  // Gesture events here are generated by |gesture_provider_|, and they're
-  // handled at OnTouchEvent() by calling MaybeHandleBackGesture().
-}
-
 bool ToplevelWindowEventHandler::AttemptToStartDrag(
     aura::Window* window,
     const gfx::PointF& point_in_parent,
@@ -974,138 +793,4 @@
     gesture_target_->AddObserver(this);
 }
 
-bool ToplevelWindowEventHandler::MaybeHandleBackGesture(ui::GestureEvent* event,
-                                                        aura::Window* target) {
-  DCHECK(features::IsSwipingFromLeftEdgeToGoBackEnabled());
-  DCHECK(target);
-  gfx::Point screen_location = event->location();
-  ::wm::ConvertPointToScreen(target, &screen_location);
-  switch (event->type()) {
-    case ui::ET_GESTURE_TAP_DOWN:
-      going_back_started_ = CanStartGoingBack(target, screen_location);
-      if (!going_back_started_)
-        break;
-      back_gesture_affordance_ = std::make_unique<BackGestureAffordance>(
-          screen_location, dragged_from_splitview_divider_);
-      return true;
-    case ui::ET_GESTURE_SCROLL_BEGIN:
-      if (!going_back_started_)
-        break;
-      back_start_location_ = screen_location;
-
-      base::RecordAction(base::UserMetricsAction("Ash_Tablet_BackGesture"));
-      back_gesture_start_scenario_type_ = GetStartScenarioType(
-          dragged_from_splitview_divider_, back_start_location_);
-      RecordStartScenarioType(back_gesture_start_scenario_type_);
-      break;
-    case ui::ET_GESTURE_SCROLL_UPDATE:
-      if (!going_back_started_)
-        break;
-      DCHECK(back_gesture_affordance_);
-      back_gesture_affordance_->Update(x_drag_amount_, y_drag_amount_,
-                                       during_reverse_dragging_);
-      return true;
-    case ui::ET_GESTURE_SCROLL_END:
-    case ui::ET_SCROLL_FLING_START: {
-      if (!going_back_started_)
-        break;
-      DCHECK(back_gesture_affordance_);
-      BackGestureEndType end_type = BackGestureEndType::kNone;
-      if (back_gesture_affordance_->IsActivated() ||
-          (event->type() == ui::ET_SCROLL_FLING_START &&
-           event->details().velocity_x() >= kFlingVelocityForGoingBack)) {
-        ActivateUnderneathWindowInSplitViewMode(
-            back_start_location_, dragged_from_splitview_divider_);
-        auto* top_window_state =
-            WindowState::Get(TabletModeWindowManager::GetTopWindow());
-        if (top_window_state && top_window_state->IsFullscreen() &&
-            !Shell::Get()->overview_controller()->InOverviewSession()) {
-          const WMEvent event(WM_EVENT_TOGGLE_FULLSCREEN);
-          top_window_state->OnWMEvent(&event);
-          RecordEndScenarioType(BackGestureEndScenarioType::kExitFullscreen);
-          return true;
-        }
-
-        if (TabletModeWindowManager::ShouldMinimizeTopWindowOnBack()) {
-          top_window_state->Minimize();
-          end_type = BackGestureEndType::kMinimize;
-        } else {
-          aura::Window* root_window =
-              window_util::GetRootWindowAt(screen_location);
-          ui::KeyEvent press_key_event(ui::ET_KEY_PRESSED,
-                                       ui::VKEY_BROWSER_BACK, ui::EF_NONE);
-          ignore_result(
-              root_window->GetHost()->SendEventToSink(&press_key_event));
-          ui::KeyEvent release_key_event(ui::ET_KEY_RELEASED,
-                                         ui::VKEY_BROWSER_BACK, ui::EF_NONE);
-          ignore_result(
-              root_window->GetHost()->SendEventToSink(&release_key_event));
-          end_type = BackGestureEndType::kBack;
-        }
-        back_gesture_affordance_->Complete();
-      } else {
-        back_gesture_affordance_->Abort();
-        end_type = BackGestureEndType::kAbort;
-      }
-      RecordEndScenarioType(
-          GetEndScenarioType(back_gesture_start_scenario_type_, end_type));
-      RecordUnderneathWindowType(
-          GetUnderneathWindowType(back_gesture_start_scenario_type_));
-      return true;
-    }
-    case ui::ET_GESTURE_END:
-      going_back_started_ = false;
-      dragged_from_splitview_divider_ = false;
-      break;
-    default:
-      break;
-  }
-
-  return going_back_started_;
-}
-
-bool ToplevelWindowEventHandler::CanStartGoingBack(
-    aura::Window* target,
-    const gfx::Point& screen_location) {
-  DCHECK(features::IsSwipingFromLeftEdgeToGoBackEnabled());
-
-  Shell* shell = Shell::Get();
-  if (!shell->tablet_mode_controller()->InTabletMode())
-    return false;
-
-  // Do not enable back gesture if it is not in an ACTIVE session. e.g, login
-  // screen, lock screen.
-  if (shell->session_controller()->GetSessionState() !=
-      session_manager::SessionState::ACTIVE) {
-    return false;
-  }
-
-  // Do not enable back gesture if home screen is visible but not in
-  // |kFullscreenSearch| state.
-  if (shell->home_screen_controller()->IsHomeScreenVisible() &&
-      shell->app_list_controller()->GetAppListViewState() !=
-          AppListViewState::kFullscreenSearch) {
-    return false;
-  }
-
-  // Do not enable back gesture if MRU window list is empty and it is not in
-  // overview mode.
-  if (!Shell::Get()->overview_controller()->InOverviewSession() &&
-      !TabletModeWindowManager::GetTopWindow()) {
-    return false;
-  }
-
-  gfx::Rect hit_bounds_in_screen(display::Screen::GetScreen()
-                                     ->GetDisplayNearestWindow(target)
-                                     .work_area());
-  hit_bounds_in_screen.set_width(
-      ToplevelWindowEventHandler::kStartGoingBackLeftEdgeInset);
-  if (hit_bounds_in_screen.Contains(screen_location))
-    return true;
-
-  dragged_from_splitview_divider_ =
-      CanStartGoingBackFromSplitViewDivider(screen_location);
-  return dragged_from_splitview_divider_;
-}
-
 }  // namespace ash
diff --git a/ash/wm/toplevel_window_event_handler.h b/ash/wm/toplevel_window_event_handler.h
index d6508e4..3d37d3b 100644
--- a/ash/wm/toplevel_window_event_handler.h
+++ b/ash/wm/toplevel_window_event_handler.h
@@ -9,14 +9,12 @@
 
 #include "ash/ash_export.h"
 #include "ash/display/window_tree_host_manager.h"
-#include "ash/wm/gestures/back_gesture/back_gesture_metrics.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/aura/window_observer.h"
 #include "ui/display/display_observer.h"
 #include "ui/events/event_handler.h"
-#include "ui/events/gestures/gesture_provider_aura.h"
 #include "ui/events/gestures/gesture_types.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/wm/public/window_move_client.h"
@@ -33,7 +31,6 @@
 }  // namespace ui
 
 namespace ash {
-class BackGestureAffordance;
 namespace mojom {
 enum class WindowStateType;
 }
@@ -45,18 +42,8 @@
       public aura::WindowObserver,
       public display::DisplayObserver,
       public ui::EventHandler,
-      public ui::GestureConsumer,
-      public ui::GestureProviderAuraClient,
       public ::wm::WindowMoveClient {
  public:
-  // The threshold of the fling velocity while fling from left edge to go
-  // previous page.
-  static constexpr int kFlingVelocityForGoingBack = 1000;
-
-  // How many dips are reserved for gesture events to start swiping to previous
-  // page from the left edge of the screen in tablet mode.
-  static constexpr int kStartGoingBackLeftEdgeInset = 16;
-
   // Describes what triggered ending the drag.
   enum class DragResult {
     // The drag successfully completed.
@@ -80,11 +67,6 @@
   void OnKeyEvent(ui::KeyEvent* event) override;
   void OnMouseEvent(ui::MouseEvent* event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
-  void OnTouchEvent(ui::TouchEvent* event) override;
-
-  // ui::GestureProviderAuraClient:
-  void OnGestureEvent(GestureConsumer* consumer,
-                      ui::GestureEvent* event) override;
 
   // Attempts to start a drag if one is not already in progress. Returns true if
   // successful. |end_closure| is run when the drag completes, including if the
@@ -176,16 +158,6 @@
   void UpdateGestureTarget(aura::Window* window,
                            const gfx::PointF& location = gfx::PointF());
 
-  // Returns true if |event| was handled as a go-back gesture. |event| is
-  // generated by |gesture_provider_| from touch event, its target will be
-  // nullptr. Gets |target| from corresponding touch event instead.
-  bool MaybeHandleBackGesture(ui::GestureEvent* event, aura::Window* target);
-
-  // True if we can start swiping from left edge of the display or splitview
-  // divider to go back.
-  bool CanStartGoingBack(aura::Window* window,
-                         const gfx::Point& screen_location);
-
   // The hittest result for the first finger at the time that it initially
   // touched the screen. |first_finger_hittest_| is one of ui/base/hit_test.h
   int first_finger_hittest_;
@@ -207,47 +179,6 @@
   // Are we running a nested run loop from RunMoveLoop().
   bool in_move_loop_ = false;
 
-  // True if swiping from left edge to go to previous page is in progress.
-  bool going_back_started_ = false;
-
-  // Tracks the x-axis and y-axis drag amount through touch events. Used for
-  // back gesture affordance in tablet mode. The gesture movement of back
-  // gesture can't be recognized by GestureRecognizer, which leads to wrong
-  // gesture locations of back gesture. See crbug.com/1015464 for the details.
-  int x_drag_amount_ = 0;
-  int y_drag_amount_ = 0;
-
-  // True if back gesture dragging on the negative direction of x-axis.
-  bool during_reverse_dragging_ = false;
-
-  // Position of last touch event. Used to calculate |y_drag_amount_|. Note,
-  // only touch events from |first_touch_id_| will be recorded.
-  gfx::Point last_touch_point_;
-  ui::PointerId first_touch_id_ = ui::kPointerIdUnknown;
-
-  // Used to show the affordance while swiping from left edge to go to the
-  // previout page.
-  std::unique_ptr<BackGestureAffordance> back_gesture_affordance_;
-
-  // True if back gesture dragged from splitview divider.
-  bool dragged_from_splitview_divider_ = false;
-
-  // Start location of the back gesture in screen coordinate. Used by
-  // ActivateUnderneathWindowInSplitViewMode() to determine the snapped window
-  // that should be activated for going back.
-  gfx::Point back_start_location_;
-
-  // A GestureProvider that is created for back gesture. Used to handle tap down
-  // and the possibly following gesture scroll sequence for back gesture in
-  // OnTouchEvent session. This is done to avoid tap down event be used by the
-  // window that is underneath to do other things (e.g, highlight a menu item)
-  // instead of going back.
-  ui::GestureProviderAura gesture_provider_;
-
-  // Start scenario type of the back gesture, used for related metrics.
-  BackGestureStartScenarioType back_gesture_start_scenario_type_ =
-      BackGestureStartScenarioType::kMaxValue;
-
   base::WeakPtrFactory<ToplevelWindowEventHandler> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandler);
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 243ddcc3..dd91c54 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -5,25 +5,16 @@
 #include "ash/wm/toplevel_window_event_handler.h"
 
 #include "ash/accelerators/accelerator_controller_impl.h"
-#include "ash/app_list/test/app_list_test_helper.h"
-#include "ash/app_list/views/app_list_view.h"
-#include "ash/app_list/views/search_box_view.h"
 #include "ash/display/screen_orientation_controller.h"
 #include "ash/display/screen_orientation_controller_test_api.h"
-#include "ash/home_screen/home_screen_controller.h"
 #include "ash/public/cpp/app_types.h"
-#include "ash/public/cpp/ash_features.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
-#include "ash/screen_util.h"
-#include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
-#include "ash/shell_delegate.h"
 #include "ash/system/overview/overview_button_tray.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/test_shell_delegate.h"
 #include "ash/window_factory.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/overview/overview_controller.h"
@@ -31,9 +22,7 @@
 #include "ash/wm/overview/overview_item.h"
 #include "ash/wm/resize_shadow.h"
 #include "ash/wm/resize_shadow_controller.h"
-#include "ash/wm/splitview/split_view_divider.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
-#include "ash/wm/tablet_mode/tablet_mode_window_manager.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
@@ -50,8 +39,6 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_observer.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/accelerators/test_accelerator_target.h"
 #include "ui/base/hit_test.h"
 #include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
@@ -1021,472 +1008,6 @@
   EXPECT_EQ("10,11 100x100", window1->bounds().ToString());
 }
 
-class ToplevelWindowEventHandlerBackGestureTest : public AshTestBase {
- public:
-  // Distance that swiping from left edge to let the affordance achieve
-  // activated state.
-  static constexpr int kSwipingDistanceForGoingBack = 80;
-
-  ToplevelWindowEventHandlerBackGestureTest() = default;
-  ~ToplevelWindowEventHandlerBackGestureTest() override = default;
-
-  void SetUp() override {
-    AshTestBase::SetUp();
-
-    feature_list_.InitAndEnableFeature(features::kSwipingFromLeftEdgeToGoBack);
-    top_window_ = CreateAppWindow(gfx::Rect(), AppType::BROWSER);
-    TabletModeControllerTestApi().EnterTabletMode();
-  }
-
-  void TearDown() override {
-    top_window_.reset();
-    AshTestBase::TearDown();
-  }
-
-  void RegisterBackPressAndRelease(ui::TestAcceleratorTarget* back_press,
-                                   ui::TestAcceleratorTarget* back_release) {
-    AcceleratorControllerImpl* controller =
-        Shell::Get()->accelerator_controller();
-
-    // Register an accelerator that looks for back presses.
-    ui::Accelerator accelerator_back_press(ui::VKEY_BROWSER_BACK, ui::EF_NONE);
-    accelerator_back_press.set_key_state(ui::Accelerator::KeyState::PRESSED);
-    controller->Register({accelerator_back_press}, back_press);
-
-    // Register an accelerator that looks for back releases.
-    ui::Accelerator accelerator_back_release(ui::VKEY_BROWSER_BACK,
-                                             ui::EF_NONE);
-    accelerator_back_release.set_key_state(ui::Accelerator::KeyState::RELEASED);
-    controller->Register({accelerator_back_release}, back_release);
-  }
-
-  // Send touch event with |type| to the toplevel window event handler.
-  void SendTouchEvent(const gfx::Point& position, ui::EventType type) {
-    ui::TouchEvent event = ui::TouchEvent(
-        type, position, base::TimeTicks::Now(),
-        ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
-                           /*pointer_id=*/5, /*radius_x=*/5.0f,
-                           /*radius_y=*/5.0, /*force=*/1.0f));
-    ui::Event::DispatcherApi(&event).set_target(top_window_.get());
-    Shell::Get()->toplevel_window_event_handler()->OnTouchEvent(&event);
-  }
-
-  aura::Window* top_window() { return top_window_.get(); }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-  std::unique_ptr<aura::Window> top_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(ToplevelWindowEventHandlerBackGestureTest);
-};
-
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, SwipingFromLeftEdgeToGoBack) {
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  // Tests that swiping from the left less than |kSwipingDistanceForGoingBack|
-  // should not go to previous page.
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  const gfx::Point start(0, 100);
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack - 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-
-  // Tests that swiping from the left more than |kSwipingDistanceForGoingBack|
-  // should go to previous page.
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-}
-
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, FlingFromLeftEdgeToGoBack) {
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  // Tests that fling from the left with velocity smaller than
-  // |kFlingVelocityForGoingBack| should not go to previous page.
-  // Drag further than |touch_slop| in GestureDetector to trigger scroll
-  // sequence. Note, |touch_slop| equals to 15.05, which is the value of
-  // |max_touch_move_in_pixels_for_click_| + |kSlopEpsilon|. Generate the scroll
-  // sequence with short duration and only one step for FLING scroll gestures.
-  // X-velocity here will be 800 dips/seconds.
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(16, 0),
-                                   base::TimeDelta::FromMilliseconds(20),
-                                   /*steps=*/1);
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-
-  // Tests that fling from the left with velocity larger than
-  // |kFlingVelocityForGoingBack| should go to previous page. X-velocity here
-  // will be 1600 dips/seconds.
-  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(16, 0),
-                                   base::TimeDelta::FromMilliseconds(1),
-                                   /*steps=*/1);
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-
-  // Tests that fling from the left with velocity smaller than
-  // |kFlingVelocityForGoingBack| but dragged further enough to trigger
-  // activated affordance should still go back to previous page. X-velocity here
-  // will be 800 dips/seconds and drag distance is 160, which is larger than
-  // |kSwipingDistanceForGoingBack|.
-  generator->GestureScrollSequence(gfx::Point(0, 0), gfx::Point(160, 0),
-                                   base::TimeDelta::FromMilliseconds(200),
-                                   /*steps=*/1);
-  EXPECT_EQ(2, target_back_press.accelerator_count());
-  EXPECT_EQ(2, target_back_release.accelerator_count());
-}
-
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, GoBackInOverviewMode) {
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  ash_test_helper()->test_shell_delegate()->SetCanGoBack(false);
-  ASSERT_FALSE(WindowState::Get(top_window())->IsMinimized());
-  ASSERT_TRUE(TabletModeWindowManager::ShouldMinimizeTopWindowOnBack());
-  GetEventGenerator()->GestureScrollSequence(
-      gfx::Point(0, 100), gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  // Should trigger window minimize instead of go back.
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-  EXPECT_TRUE(WindowState::Get(top_window())->IsMinimized());
-
-  WindowState::Get(top_window())->Unminimize();
-  ASSERT_FALSE(WindowState::Get(top_window())->IsMinimized());
-  auto* shell = Shell::Get();
-  shell->overview_controller()->StartOverview();
-  ASSERT_TRUE(shell->overview_controller()->InOverviewSession());
-  GetEventGenerator()->GestureScrollSequence(
-      gfx::Point(0, 100), gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  // Should trigger go back instead of minimize the window since it is in
-  // overview mode.
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-}
-
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, DonotStartGoingBack) {
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  auto* shell = Shell::Get();
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  const gfx::Point start(0, 100);
-
-  // Should not go back if it is not in ACTIVE session.
-  ASSERT_FALSE(shell->overview_controller()->InOverviewSession());
-  ASSERT_FALSE(shell->home_screen_controller()->IsHomeScreenVisible());
-  GetSessionControllerClient()->SetSessionState(
-      session_manager::SessionState::LOCKED);
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-
-  // Should not go back if home screen is visible and in |kFullscreenAllApps|
-  // state.
-  GetSessionControllerClient()->SetSessionState(
-      session_manager::SessionState::ACTIVE);
-  shell->home_screen_controller()->GoHome(GetPrimaryDisplay().id());
-  ASSERT_TRUE(shell->home_screen_controller()->IsHomeScreenVisible());
-  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-
-  // Should exit |kFullscreenSearch| to enter |kFullscreenAllApps| state while
-  // home screen search result page is opened.
-  generator->GestureTapAt(GetAppListTestHelper()
-                              ->GetAppListView()
-                              ->search_box_view()
-                              ->GetBoundsInScreen()
-                              .CenterPoint());
-  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
-}
-
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, CancelOnScreenRotation) {
-  UpdateDisplay("807x407");
-  int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-  display::test::ScopedSetInternalDisplayId set_internal(display_manager,
-                                                         display_id);
-  ScreenOrientationControllerTestApi test_api(
-      Shell::Get()->screen_orientation_controller());
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  // Set the screen orientation to LANDSCAPE_PRIMARY.
-  test_api.SetDisplayRotation(display::Display::ROTATE_0,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kLandscapePrimary);
-
-  gfx::Point start(0, 100);
-  gfx::Point update_and_end(200, 100);
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  // Rotate the screen by 270 degree during drag.
-  test_api.SetDisplayRotation(display::Display::ROTATE_270,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kPortraitPrimary);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Left edge swipe back should be cancelled due to screen rotation, so the
-  // fling event with velocity larger than |kFlingVelocityForGoingBack| above
-  // will not trigger actual going back.
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-}
-
-// Tests back gesture while in split view mode.
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, DragFromSplitViewDivider) {
-  std::unique_ptr<aura::Window> window1 = CreateTestWindow();
-  std::unique_ptr<aura::Window> window2 = CreateTestWindow();
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  gfx::Rect display_bounds =
-      screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
-          window1.get());
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  auto* split_view_controller =
-      SplitViewController::Get(Shell::GetPrimaryRootWindow());
-  split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
-  split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
-  ASSERT_TRUE(split_view_controller->InSplitViewMode());
-  ASSERT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller->state());
-
-  gfx::Rect divider_bounds =
-      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
-          false);
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  // Drag from the splitview divider's non-resizable area with larger than
-  // |kSwipingDistanceForGoingBack| distance should trigger back gesture. The
-  // snapped window should go to previous page and divider's position will not
-  // be changed.
-  gfx::Point start(divider_bounds.x(), 10);
-  gfx::Point end(start.x() + kSwipingDistanceForGoingBack + 10, 10);
-  EXPECT_GT(split_view_controller->divider_position(),
-            0.33f * display_bounds.width());
-  EXPECT_LE(split_view_controller->divider_position(),
-            0.5f * display_bounds.width());
-  generator->GestureScrollSequence(start, end,
-                                   base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(SplitViewController::State::kBothSnapped,
-            split_view_controller->state());
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-  EXPECT_GT(split_view_controller->divider_position(),
-            0.33f * display_bounds.width());
-  EXPECT_LE(split_view_controller->divider_position(),
-            0.5f * display_bounds.width());
-
-  // Drag from the divider's resizable area should trigger splitview resizing.
-  // Divider's position will be changed and back gesture should not be
-  // triggered.
-  start = divider_bounds.CenterPoint();
-  end = gfx::Point(0.67f * display_bounds.width(), start.y());
-  generator->GestureScrollSequence(start, end,
-                                   base::TimeDelta::FromMilliseconds(100), 3);
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-  EXPECT_GT(split_view_controller->divider_position(),
-            0.5f * display_bounds.width());
-  EXPECT_LE(split_view_controller->divider_position(),
-            0.67f * display_bounds.width());
-  split_view_controller->EndSplitView();
-}
-
-// Tests that in different screen orientations should always activate the
-// snapped window in splitview that is underneath the finger. And should be the
-// snapped window that is underneath to go back to the previous page.
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, BackInSplitViewMode) {
-  int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
-  display::DisplayManager* display_manager = Shell::Get()->display_manager();
-  display::test::ScopedSetInternalDisplayId set_internal(display_manager,
-                                                         display_id);
-  ScreenOrientationControllerTestApi test_api(
-      Shell::Get()->screen_orientation_controller());
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  std::unique_ptr<aura::Window> left_window = CreateTestWindow();
-  std::unique_ptr<aura::Window> right_window = CreateTestWindow();
-  auto* split_view_controller =
-      SplitViewController::Get(Shell::GetPrimaryRootWindow());
-  split_view_controller->SnapWindow(left_window.get(),
-                                    SplitViewController::LEFT);
-  split_view_controller->SnapWindow(right_window.get(),
-                                    SplitViewController::RIGHT);
-
-  // Set the screen orientation to LANDSCAPE_PRIMARY.
-  test_api.SetDisplayRotation(display::Display::ROTATE_0,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kLandscapePrimary);
-
-  ASSERT_EQ(right_window.get(), window_util::GetActiveWindow());
-  gfx::Point start(0, 10);
-  gfx::Point update_and_end(kSwipingDistanceForGoingBack + 10, 10);
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the display in LandscapePrimary further than
-  // |kSwipingDistanceForGoingBack| should activate the physically left snapped
-  // window, which is |left_window| and it should go back to the previous page.
-  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-
-  gfx::Rect divider_bounds =
-      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
-          false);
-  start = gfx::Point(divider_bounds.x(), 10);
-  update_and_end =
-      gfx::Point(divider_bounds.x() + kSwipingDistanceForGoingBack + 10, 10);
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the split view divider in LandscapePrimary further than
-  // |kSwipingDistanceForGoingBack| should activate the physically right snapped
-  // window, which is |right_window| and it should go back to the previous page.
-  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(2, target_back_press.accelerator_count());
-  EXPECT_EQ(2, target_back_release.accelerator_count());
-
-  // Rotate the screen by 180 degree.
-  test_api.SetDisplayRotation(display::Display::ROTATE_180,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kLandscapeSecondary);
-
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the split view divider in LandscapeSecondary further than
-  // |kSwipingDistanceForGoingBack| should activate the physically right snapped
-  // window, which is |left_window| and it should go back to the previous page.
-  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(3, target_back_press.accelerator_count());
-  EXPECT_EQ(3, target_back_release.accelerator_count());
-
-  start = gfx::Point(0, 10);
-  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, 10);
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the display in LandscapeSecondary further than
-  // |kSwipingDistanceForGoingBack| should activate the physically left snapped
-  // window, which is |right_window| and it should go back to the previous page.
-  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(4, target_back_press.accelerator_count());
-  EXPECT_EQ(4, target_back_release.accelerator_count());
-
-  // Rotate the screen by 270 degree.
-  test_api.SetDisplayRotation(display::Display::ROTATE_270,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kPortraitPrimary);
-
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the top half of the display in PortraitPrimary
-  // further than |kSwipingDistanceForGoingBack| should activate the physically
-  // top snapped window, which is |right_window|, and it should go back to the
-  // previous page.
-  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(5, target_back_press.accelerator_count());
-  EXPECT_EQ(5, target_back_release.accelerator_count());
-
-  divider_bounds =
-      split_view_controller->split_view_divider()->GetDividerBoundsInScreen(
-          false);
-  start = gfx::Point(0, divider_bounds.bottom() + 10);
-  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, start.y());
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the bottom half of the display in PortraitPrimary
-  // further than |kSwipingDistanceForGoingBack| should activate the physically
-  // bottom snapped window, which is |right_window|, and it should go back to
-  // the previous page.
-  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(6, target_back_press.accelerator_count());
-  EXPECT_EQ(6, target_back_release.accelerator_count());
-
-  // Rotate the screen by 90 degree.
-  test_api.SetDisplayRotation(display::Display::ROTATE_90,
-                              display::Display::RotationSource::ACTIVE);
-  EXPECT_EQ(test_api.GetCurrentOrientation(),
-            OrientationLockType::kPortraitSecondary);
-
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the bottom half of the display in
-  // PortraitSecondary further than |kSwipingDistanceForGoingBack| should
-  // activate the physically bottom snapped window, which is |left_window|, and
-  // it should go back to the previous page.
-  EXPECT_EQ(left_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(7, target_back_press.accelerator_count());
-  EXPECT_EQ(7, target_back_release.accelerator_count());
-
-  start = gfx::Point(0, 10);
-  update_and_end = gfx::Point(kSwipingDistanceForGoingBack + 10, 10);
-  SendTouchEvent(start, ui::ET_TOUCH_PRESSED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_MOVED);
-  SendTouchEvent(update_and_end, ui::ET_TOUCH_RELEASED);
-  // Swiping from the left of the top half of the display in PortraitSecondary
-  // further than |kSwipingDistanceForGoingBack| should activate the physically
-  // top snapped window, which is |right_window| and it should go back to the
-  // previous page.
-  EXPECT_EQ(right_window.get(), window_util::GetActiveWindow());
-  EXPECT_EQ(8, target_back_press.accelerator_count());
-  EXPECT_EQ(8, target_back_release.accelerator_count());
-}
-
-// Tests the back gesture behavior on a fullscreen'ed window.
-TEST_F(ToplevelWindowEventHandlerBackGestureTest, FullscreenedWindow) {
-  ui::TestAcceleratorTarget target_back_press, target_back_release;
-  RegisterBackPressAndRelease(&target_back_press, &target_back_release);
-
-  WindowState* window_state = WindowState::Get(top_window());
-  const WMEvent fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
-  window_state->OnWMEvent(&fullscreen_event);
-  EXPECT_TRUE(window_state->IsFullscreen());
-
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  const gfx::Point start(0, 100);
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  // First back gesture should let the window exit fullscreen mode instead of
-  // triggering go back.
-  EXPECT_FALSE(window_state->IsFullscreen());
-  EXPECT_EQ(0, target_back_press.accelerator_count());
-  EXPECT_EQ(0, target_back_release.accelerator_count());
-
-  generator->GestureScrollSequence(
-      start, gfx::Point(kSwipingDistanceForGoingBack + 10, 100),
-      base::TimeDelta::FromMilliseconds(100), 3);
-  // Second back gesture should trigger go back.
-  EXPECT_EQ(1, target_back_press.accelerator_count());
-  EXPECT_EQ(1, target_back_release.accelerator_count());
-}
-
 namespace {
 
 void SendMouseReleaseAndReleaseCapture(ui::test::EventGenerator* generator,
diff --git a/ash/wm/window_cycle_controller.cc b/ash/wm/window_cycle_controller.cc
index 1888638..1de474859 100644
--- a/ash/wm/window_cycle_controller.cc
+++ b/ash/wm/window_cycle_controller.cc
@@ -10,6 +10,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
+#include "ash/wm/desks/desk.h"
 #include "ash/wm/desks/desks_controller.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/mru_window_tracker.h"
@@ -33,11 +34,18 @@
 void ReportPossibleDesksSwitchStats(int active_desk_container_id_before_cycle) {
   // Report only for users who have 2 or more desks, since we're only interested
   // in seeing how users of Virtual Desks use window cycling.
-  if (DesksController::Get()->desks().size() < 2)
+  auto* desks_controller = DesksController::Get();
+  if (!desks_controller)
     return;
 
+  if (desks_controller->desks().size() < 2)
+    return;
+
+  // Note that this functions is called while a potential desk switch animation
+  // is starting, in this case we want the target active desk (i.e. the soon-to-
+  // be active desk after the animation finishes).
   const int active_desk_container_id_after_cycle =
-      desks_util::GetActiveDeskContainerId();
+      desks_controller->GetTargetActiveDesk()->container_id();
   DCHECK_NE(active_desk_container_id_before_cycle, kShellWindowId_Invalid);
   DCHECK_NE(active_desk_container_id_after_cycle, kShellWindowId_Invalid);
 
@@ -119,8 +127,12 @@
 void WindowCycleController::StopCycling() {
   window_cycle_list_.reset();
 
-  aura::Window* active_window_after_window_cycle = GetActiveWindow(
-      Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk));
+  // We can't use the MRU window list here to get the active window, since
+  // cycling can activate a window on a different desk, leading to a desk-switch
+  // animation launching. Getting the MRU window list for the active desk now
+  // will always be for the current active desk, not the target active desk.
+  aura::Window* active_window_after_window_cycle =
+      window_util::GetActiveWindow();
 
   // Remove our key event filter.
   event_filter_.reset();
diff --git a/ash/wm/window_cycle_controller_unittest.cc b/ash/wm/window_cycle_controller_unittest.cc
index 71e9c39..ffdd4b4 100644
--- a/ash/wm/window_cycle_controller_unittest.cc
+++ b/ash/wm/window_cycle_controller_unittest.cc
@@ -30,6 +30,7 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/screen_position_client.h"
@@ -719,11 +720,15 @@
   auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
   auto* desks_controller = DesksController::Get();
   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
-  ASSERT_EQ(2u, desks_controller->desks().size());
+  desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
+  ASSERT_EQ(3u, desks_controller->desks().size());
   const Desk* desk_2 = desks_controller->desks()[1].get();
   ActivateDesk(desk_2);
   EXPECT_EQ(desk_2, desks_controller->active_desk());
   auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
+  const Desk* desk_3 = desks_controller->desks()[2].get();
+  ActivateDesk(desk_3);
+  EXPECT_EQ(desk_3, desks_controller->active_desk());
   auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
 
   WindowCycleController* cycle_controller =
@@ -740,13 +745,36 @@
   // The MRU order is {win3, win2, win1, win0}. We're now at win2. Cycling one
   // more time and completing the cycle, will activate win1 which exists on a
   // desk_1. This should activate desk_1.
-  DeskSwitchAnimationWaiter waiter;
-  cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
-  cycle_controller->CompleteCycling();
-  waiter.Wait();
-  Desk* desk_1 = desks_controller->desks()[0].get();
-  EXPECT_EQ(desk_1, desks_controller->active_desk());
-  EXPECT_EQ(win1.get(), window_util::GetActiveWindow());
+  {
+    base::HistogramTester histogram_tester;
+    DeskSwitchAnimationWaiter waiter;
+    cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
+    cycle_controller->CompleteCycling();
+    waiter.Wait();
+    Desk* desk_1 = desks_controller->desks()[0].get();
+    EXPECT_EQ(desk_1, desks_controller->active_desk());
+    EXPECT_EQ(win1.get(), window_util::GetActiveWindow());
+    histogram_tester.ExpectUniqueSample(
+        "Ash.WindowCycleController.DesksSwitchDistance",
+        /*desk distance of 3 - 1 = */ 2, /*expected_count=*/1);
+  }
+
+  // Cycle again and activate win2, which exist on desk_2. Expect that desk to
+  // be activated, and a histogram sample of distance of 1 is recorded.
+  // MRU is {win1, win3, win2, win0}.
+  {
+    base::HistogramTester histogram_tester;
+    DeskSwitchAnimationWaiter waiter;
+    cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
+    cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
+    cycle_controller->CompleteCycling();
+    waiter.Wait();
+    EXPECT_EQ(desk_2, desks_controller->active_desk());
+    EXPECT_EQ(win2.get(), window_util::GetActiveWindow());
+    histogram_tester.ExpectUniqueSample(
+        "Ash.WindowCycleController.DesksSwitchDistance",
+        /*desk distance of 2 - 1 = */ 1, /*expected_count=*/1);
+  }
 }
 
 }  // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 9d9e2022..c2e9c26 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2846,7 +2846,6 @@
     sources += [
       "allocator/allocator_interception_mac_unittest.mm",
       "allocator/malloc_zone_functions_mac_unittest.cc",
-      "enterprise_util_mac_unittest.cc",
       "mac/bind_objc_block_unittest.mm",
       "mac/call_with_eh_frame_unittest.mm",
       "mac/dispatch_source_mach_unittest.cc",
diff --git a/base/enterprise_util.h b/base/enterprise_util.h
index e14116e..d5ecbde 100644
--- a/base/enterprise_util.h
+++ b/base/enterprise_util.h
@@ -6,7 +6,6 @@
 #define BASE_ENTERPRISE_UTIL_H_
 
 #include "base/base_export.h"
-#include "build/build_config.h"
 
 namespace base {
 
@@ -16,47 +15,6 @@
 // outside administrator.
 BASE_EXPORT bool IsMachineExternallyManaged();
 
-#if defined(OS_MACOSX)
-
-// Returns true if the device is being managed by an MDM system. Uses an old API
-// not intended for the purpose.
-enum class MacDeviceManagementStateOld {
-  kFailureAPIUnavailable = 0,
-  kFailureUnableToParseResult = 1,
-  kNoEnrollment = 2,
-  kMDMEnrollment = 3,
-
-  kMaxValue = kMDMEnrollment
-};
-BASE_EXPORT MacDeviceManagementStateOld IsDeviceRegisteredWithManagementOld();
-
-// Returns the state of the management of the device. Uses a new API so results
-// aren't always available. For more details, this is documented at
-// https://blog.fleetsmith.com/what-is-user-approved-mdm-uamdm/ .
-
-// These values are persisted to logs. Entries must not be renumbered and
-// numeric values must never be reused.
-enum class MacDeviceManagementStateNew {
-  kFailureAPIUnavailable = 0,
-  kFailureUnableToParseResult = 1,
-  kNoEnrollment = 2,
-  kLimitedMDMEnrollment = 3,
-  kFullMDMEnrollment = 4,
-  kDEPMDMEnrollment = 5,
-
-  kMaxValue = kDEPMDMEnrollment
-};
-BASE_EXPORT MacDeviceManagementStateNew IsDeviceRegisteredWithManagementNew();
-
-// Returns whether the device and/or the current user is enrolled to a domain.
-struct DeviceUserDomainJoinState {
-  bool device_joined;
-  bool user_joined;
-};
-BASE_EXPORT DeviceUserDomainJoinState AreDeviceAndUserJoinedToDomain();
-
-#endif  // OS_MACOSX
-
 }  // namespace base
 
 #endif  // BASE_ENTERPRISE_UTIL_H_
diff --git a/base/enterprise_util_mac.mm b/base/enterprise_util_mac.mm
index 621c5e4e..8d5c732 100644
--- a/base/enterprise_util_mac.mm
+++ b/base/enterprise_util_mac.mm
@@ -6,161 +6,18 @@
 
 #import <OpenDirectory/OpenDirectory.h>
 
-#include <string>
-#include <vector>
-
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/sdk_forward_declarations.h"
-#include "base/process/launch.h"
-#include "base/stl_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/sys_string_conversions.h"
 
 namespace base {
 
 bool IsMachineExternallyManaged() {
-  DeviceUserDomainJoinState join_state = AreDeviceAndUserJoinedToDomain();
-  return join_state.device_joined || join_state.user_joined;
-}
-
-MacDeviceManagementStateOld IsDeviceRegisteredWithManagementOld() {
-  @autoreleasepool {
-    std::vector<std::string> profiler_argv{"/usr/sbin/system_profiler",
-                                           "SPConfigurationProfileDataType",
-                                           "-detailLevel",
-                                           "mini",
-                                           "-timeout",
-                                           "15",
-                                           "-xml"};
-
-    std::string profiler_stdout;
-    if (!GetAppOutput(profiler_argv, &profiler_stdout)) {
-      LOG(WARNING) << "Could not get system_profiler output.";
-      return MacDeviceManagementStateOld::kFailureAPIUnavailable;
-    };
-
-    NSArray* root = base::mac::ObjCCast<NSArray>([NSPropertyListSerialization
-        propertyListWithData:[SysUTF8ToNSString(profiler_stdout)
-                                 dataUsingEncoding:NSUTF8StringEncoding]
-                     options:NSPropertyListImmutable
-                      format:nil
-                       error:nil]);
-    if (!root) {
-      LOG(WARNING) << "Could not parse system_profiler output.";
-      return MacDeviceManagementStateOld::kFailureUnableToParseResult;
-    };
-
-    for (NSDictionary* results in root) {
-      for (NSDictionary* dict in results[@"_items"]) {
-        for (NSDictionary* device_config_profiles in dict[@"_items"]) {
-          for (NSDictionary* profile_item in
-                   device_config_profiles[@"_items"]) {
-            if (![profile_item[@"_name"] isEqual:@"com.apple.mdm"])
-              continue;
-
-            NSString* payload_data =
-                profile_item[@"spconfigprofile_payload_data"];
-            NSDictionary* payload_data_dict = base::mac::ObjCCast<
-                NSDictionary>([NSPropertyListSerialization
-                propertyListWithData:[payload_data
-                                         dataUsingEncoding:NSUTF8StringEncoding]
-                             options:NSPropertyListImmutable
-                              format:nil
-                               error:nil]);
-
-            if (!payload_data_dict)
-              continue;
-
-            // Verify that the URL validates.
-            if ([NSURL URLWithString:payload_data_dict[@"CheckInURL"]])
-              return MacDeviceManagementStateOld::kMDMEnrollment;
-          }
-        }
-      }
-    }
-
-    return MacDeviceManagementStateOld::kNoEnrollment;
-  }
-}
-
-MacDeviceManagementStateNew IsDeviceRegisteredWithManagementNew() {
-  if (@available(macOS 10.13.4, *)) {
-    std::vector<std::string> profiles_argv{"/usr/bin/profiles", "status",
-                                           "-type", "enrollment"};
-
-    std::string profiles_stdout;
-    if (!GetAppOutput(profiles_argv, &profiles_stdout)) {
-      LOG(WARNING) << "Could not get profiles output.";
-      return MacDeviceManagementStateNew::kFailureAPIUnavailable;
-    }
-
-    std::vector<StringPiece> lines = SplitStringPiece(
-        profiles_stdout, "\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
-
-    bool enrolled_via_dep = false;
-    bool mdm_enrollment_not_approved = false;
-    bool mdm_enrollment_user_approved = false;
-
-    for (const auto& line : lines) {
-      std::vector<StringPiece> halves =
-          SplitStringPiece(line, ":", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
-      if (halves.size() != 2)
-        return MacDeviceManagementStateNew::kFailureUnableToParseResult;
-      StringPiece property = halves[0];
-      StringPiece state = halves[1];
-
-      if (property == "Enrolled via DEP") {
-        if (state == "Yes")
-          enrolled_via_dep = true;
-        else if (state != "No")
-          return MacDeviceManagementStateNew::kFailureUnableToParseResult;
-      } else if (property == "MDM enrollment") {
-        if (state == "Yes")
-          mdm_enrollment_not_approved = true;
-        else if (state == "Yes (User Approved)")
-          mdm_enrollment_user_approved = true;
-        else if (state != "No")
-          return MacDeviceManagementStateNew::kFailureUnableToParseResult;
-      } else {
-        // Ignore any other output lines, for future extensibility.
-      }
-    }
-
-    if (!enrolled_via_dep && !mdm_enrollment_not_approved &&
-        !mdm_enrollment_user_approved) {
-      return MacDeviceManagementStateNew::kNoEnrollment;
-    }
-
-    if (!enrolled_via_dep && mdm_enrollment_not_approved &&
-        !mdm_enrollment_user_approved) {
-      return MacDeviceManagementStateNew::kLimitedMDMEnrollment;
-    }
-
-    if (!enrolled_via_dep && !mdm_enrollment_not_approved &&
-        mdm_enrollment_user_approved) {
-      return MacDeviceManagementStateNew::kFullMDMEnrollment;
-    }
-
-    if (enrolled_via_dep && !mdm_enrollment_not_approved &&
-        mdm_enrollment_user_approved) {
-      return MacDeviceManagementStateNew::kDEPMDMEnrollment;
-    }
-
-    return MacDeviceManagementStateNew::kFailureUnableToParseResult;
-  } else {
-    return MacDeviceManagementStateNew::kFailureAPIUnavailable;
-  }
-}
-
-DeviceUserDomainJoinState AreDeviceAndUserJoinedToDomain() {
-  DeviceUserDomainJoinState state{false, false};
-
   @autoreleasepool {
     ODSession* session = [ODSession defaultSession];
     if (session == nil) {
       DLOG(WARNING) << "ODSession default session is nil.";
-      return state;
+      return false;
     }
 
     NSError* error = nil;
@@ -170,20 +27,20 @@
     if (!all_node_names) {
       DLOG(WARNING) << "ODSession failed to give node names: "
                     << error.localizedDescription.UTF8String;
-      return state;
+      return false;
     }
 
     NSUInteger num_nodes = all_node_names.count;
     if (num_nodes < 3) {
       DLOG(WARNING) << "ODSession returned too few node names: "
                     << all_node_names.description.UTF8String;
-      return state;
+      return false;
     }
 
     if (num_nodes > 3) {
       // Non-enterprise machines have:"/Search", "/Search/Contacts",
       // "/Local/Default". Everything else would be enterprise management.
-      state.device_joined = true;
+      return true;
     }
 
     ODNode* node = [ODNode nodeWithSession:session
@@ -192,7 +49,7 @@
     if (node == nil) {
       DLOG(WARNING) << "ODSession cannot obtain the authentication node: "
                     << error.localizedDescription.UTF8String;
-      return state;
+      return false;
     }
 
     // Now check the currently logged on user.
@@ -206,34 +63,33 @@
                                       error:&error];
     if (query == nil) {
       DLOG(WARNING) << "ODSession cannot create user query: "
-                    << mac::NSToCFCast(error);
-      return state;
+                    << base::mac::NSToCFCast(error);
+      return false;
     }
 
     NSArray* results = [query resultsAllowingPartial:NO error:&error];
     if (!results) {
       DLOG(WARNING) << "ODSession cannot obtain current user node: "
                     << error.localizedDescription.UTF8String;
-      return state;
+      return false;
     }
-
     if (results.count != 1) {
       DLOG(WARNING) << @"ODSession unexpected number of user nodes: "
                     << results.count;
     }
-
     for (id element in results) {
-      ODRecord* record = mac::ObjCCastStrict<ODRecord>(element);
+      ODRecord* record = base::mac::ObjCCastStrict<ODRecord>(element);
       NSArray* attributes =
           [record valuesForAttribute:kODAttributeTypeMetaRecordName error:nil];
       for (id attribute in attributes) {
-        NSString* attribute_value = mac::ObjCCastStrict<NSString>(attribute);
+        NSString* attribute_value =
+            base::mac::ObjCCastStrict<NSString>(attribute);
         // Example: "uid=johnsmith,ou=People,dc=chromium,dc=org
         NSRange domain_controller =
             [attribute_value rangeOfString:@"(^|,)\\s*dc="
                                    options:NSRegularExpressionSearch];
         if (domain_controller.length > 0) {
-          state.user_joined = true;
+          return true;
         }
       }
 
@@ -242,20 +98,20 @@
           [record valuesForAttribute:kODAttributeTypeAltSecurityIdentities
                                error:nil];
       for (id attribute in attributes) {
-        NSString* attribute_value = mac::ObjCCastStrict<NSString>(attribute);
+        NSString* attribute_value =
+            base::mac::ObjCCastStrict<NSString>(attribute);
         NSRange icloud =
             [attribute_value rangeOfString:@"CN=com.apple.idms.appleid.prd"
                                    options:NSCaseInsensitiveSearch];
         if (!icloud.length) {
           // Any alternative identity that is not iCloud is likely enterprise
           // management.
-          state.user_joined = true;
+          return true;
         }
       }
     }
   }
-
-  return state;
+  return false;
 }
 
 }  // namespace base
diff --git a/base/enterprise_util_mac_unittest.cc b/base/enterprise_util_mac_unittest.cc
deleted file mode 100644
index cde19f7..0000000
--- a/base/enterprise_util_mac_unittest.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/enterprise_util.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(EnterpriseUtilMacTest, IsDeviceRegisteredWithManagementOldSmokeTest) {
-  MacDeviceManagementStateOld state = IsDeviceRegisteredWithManagementOld();
-
-  EXPECT_NE(MacDeviceManagementStateOld::kFailureAPIUnavailable, state);
-  EXPECT_NE(MacDeviceManagementStateOld::kFailureUnableToParseResult, state);
-}
-
-TEST(EnterpriseUtilMacTest, IsDeviceRegisteredWithManagementNewSmokeTest) {
-  MacDeviceManagementStateNew state = IsDeviceRegisteredWithManagementNew();
-
-  EXPECT_NE(MacDeviceManagementStateNew::kFailureAPIUnavailable, state);
-  EXPECT_NE(MacDeviceManagementStateNew::kFailureUnableToParseResult, state);
-}
-
-}  // namespace base
diff --git a/base/task/thread_pool/task_tracker.cc b/base/task/thread_pool/task_tracker.cc
index ea1a9c86..d8d5bdf 100644
--- a/base/task/thread_pool/task_tracker.cc
+++ b/base/task/thread_pool/task_tracker.cc
@@ -593,7 +593,7 @@
     // Set up TaskRunnerHandle as expected for the scope of the task.
     Optional<SequencedTaskRunnerHandle> sequenced_task_runner_handle;
     Optional<ThreadTaskRunnerHandle> single_thread_task_runner_handle;
-    Optional<EphemeralTaskExecutor> ephemiral_task_executor;
+    Optional<EphemeralTaskExecutor> ephemeral_task_executor;
     switch (task_source->execution_mode()) {
       case TaskSourceExecutionMode::kJob:
       case TaskSourceExecutionMode::kParallel:
@@ -602,7 +602,7 @@
         DCHECK(task_source->task_runner());
         sequenced_task_runner_handle.emplace(
             static_cast<SequencedTaskRunner*>(task_source->task_runner()));
-        ephemiral_task_executor.emplace(
+        ephemeral_task_executor.emplace(
             static_cast<SequencedTaskRunner*>(task_source->task_runner()),
             nullptr, &traits);
         break;
@@ -610,7 +610,7 @@
         DCHECK(task_source->task_runner());
         single_thread_task_runner_handle.emplace(
             static_cast<SingleThreadTaskRunner*>(task_source->task_runner()));
-        ephemiral_task_executor.emplace(
+        ephemeral_task_executor.emplace(
             static_cast<SequencedTaskRunner*>(task_source->task_runner()),
             static_cast<SingleThreadTaskRunner*>(task_source->task_runner()),
             &traits);
diff --git a/base/trace_event/etw_manifest/BUILD.gn b/base/trace_event/etw_manifest/BUILD.gn
index 19c4ecf..dab9e6f 100644
--- a/base/trace_event/etw_manifest/BUILD.gn
+++ b/base/trace_event/etw_manifest/BUILD.gn
@@ -12,9 +12,7 @@
     "//chrome:main_dll",
   ]
 
-  sources = [
-    "chrome_events_win.man",
-  ]
+  sources = [ "chrome_events_win.man" ]
 
   user_mode_logging = true
 
diff --git a/base/win/.clang-tidy b/base/win/.clang-tidy
index baec539..7a75762 100644
--- a/base/win/.clang-tidy
+++ b/base/win/.clang-tidy
@@ -17,6 +17,7 @@
          modernize-use-nullptr,
          modernize-use-override,
          modernize-use-transparent-functors,
+         modernize-use-using,
          readability-redundant-member-init'
 HeaderFilterRegex: 'base/win/*'
 CheckOptions:
diff --git a/base/win/event_trace_consumer_unittest.cc b/base/win/event_trace_consumer_unittest.cc
index 64aac10..8f50635 100644
--- a/base/win/event_trace_consumer_unittest.cc
+++ b/base/win/event_trace_consumer_unittest.cc
@@ -29,7 +29,7 @@
 
 namespace {
 
-typedef std::list<EVENT_TRACE> EventQueue;
+using EventQueue = std::list<EVENT_TRACE>;
 
 class TestConsumer : public EtwTraceConsumerBase<TestConsumer> {
  public:
diff --git a/base/win/event_trace_provider.h b/base/win/event_trace_provider.h
index ff8f1c8..426be19 100644
--- a/base/win/event_trace_provider.h
+++ b/base/win/event_trace_provider.h
@@ -23,11 +23,11 @@
 namespace base {
 namespace win {
 
-typedef GUID EtwEventClass;
-typedef UCHAR EtwEventType;
-typedef UCHAR EtwEventLevel;
-typedef USHORT EtwEventVersion;
-typedef ULONG EtwEventFlags;
+using EtwEventClass = GUID;
+using EtwEventType = UCHAR;
+using EtwEventLevel = UCHAR;
+using EtwEventVersion = USHORT;
+using EtwEventFlags = ULONG;
 
 // Base class is a POD for correctness.
 template <size_t N>
@@ -40,7 +40,7 @@
 template <size_t N>
 class EtwMofEvent : public EtwMofEventBase<N> {
  public:
-  typedef EtwMofEventBase<N> Super;
+  using Super = EtwMofEventBase<N>;
 
   // Clang and the C++ standard don't allow unqualified lookup into dependent
   // bases, hence these using decls to explicitly pull the names out.
diff --git a/base/win/i18n.cc b/base/win/i18n.cc
index ca80f938..786ad0a 100644
--- a/base/win/i18n.cc
+++ b/base/win/i18n.cc
@@ -12,7 +12,7 @@
 
 namespace {
 
-typedef decltype(::GetSystemPreferredUILanguages)* GetPreferredUILanguages_Fn;
+using GetPreferredUILanguages_Fn = decltype(::GetSystemPreferredUILanguages)*;
 
 bool GetPreferredUILanguageList(GetPreferredUILanguages_Fn function,
                                 ULONG flags,
diff --git a/base/win/pe_image.h b/base/win/pe_image.h
index 2761597..5f6d003b 100644
--- a/base/win/pe_image.h
+++ b/base/win/pe_image.h
@@ -32,65 +32,54 @@
   // Callback to enumerate sections.
   // cookie is the value passed to the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumSectionsFunction)(const PEImage& image,
-                                       PIMAGE_SECTION_HEADER header,
-                                       PVOID section_start,
-                                       DWORD section_size,
-                                       PVOID cookie);
+  using EnumSectionsFunction =
+      bool (*)(const PEImage&, PIMAGE_SECTION_HEADER, PVOID, DWORD, PVOID);
 
   // Callback to enumerate exports.
   // function is the actual address of the symbol. If forward is not null, it
   // contains the dll and symbol to forward this export to. cookie is the value
   // passed to the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumExportsFunction)(const PEImage& image,
-                                      DWORD ordinal,
-                                      DWORD hint,
-                                      LPCSTR name,
-                                      PVOID function,
-                                      LPCSTR forward,
-                                      PVOID cookie);
+  using EnumExportsFunction =
+      bool (*)(const PEImage&, DWORD, DWORD, LPCSTR, PVOID, LPCSTR, PVOID);
 
   // Callback to enumerate import blocks.
   // name_table and iat point to the imports name table and address table for
   // this block. cookie is the value passed to the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumImportChunksFunction)(const PEImage& image,
-                                           LPCSTR module,
-                                           PIMAGE_THUNK_DATA name_table,
-                                           PIMAGE_THUNK_DATA iat,
-                                           PVOID cookie);
+  using EnumImportChunksFunction = bool (*)(const PEImage&,
+                                            LPCSTR,
+                                            PIMAGE_THUNK_DATA,
+                                            PIMAGE_THUNK_DATA,
+                                            PVOID);
 
   // Callback to enumerate imports.
   // module is the dll that exports this symbol. cookie is the value passed to
   // the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumImportsFunction)(const PEImage& image,
-                                      LPCSTR module,
-                                      DWORD ordinal,
-                                      LPCSTR name,
-                                      DWORD hint,
-                                      PIMAGE_THUNK_DATA iat,
-                                      PVOID cookie);
+  using EnumImportsFunction = bool (*)(const PEImage&,
+                                       LPCSTR,
+                                       DWORD,
+                                       LPCSTR,
+                                       DWORD,
+                                       PIMAGE_THUNK_DATA,
+                                       PVOID);
 
   // Callback to enumerate delayed import blocks.
   // module is the dll that exports this block of symbols. cookie is the value
   // passed to the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumDelayImportChunksFunction)(const PEImage& image,
-                                                PImgDelayDescr delay_descriptor,
-                                                LPCSTR module,
-                                                PIMAGE_THUNK_DATA name_table,
-                                                PIMAGE_THUNK_DATA iat,
-                                                PVOID cookie);
+  using EnumDelayImportChunksFunction = bool (*)(const PEImage&,
+                                                 PImgDelayDescr,
+                                                 LPCSTR,
+                                                 PIMAGE_THUNK_DATA,
+                                                 PIMAGE_THUNK_DATA,
+                                                 PVOID);
 
   // Callback to enumerate relocations.
   // cookie is the value passed to the enumerate method.
   // Returns true to continue the enumeration.
-  typedef bool (*EnumRelocsFunction)(const PEImage& image,
-                                     WORD type,
-                                     PVOID address,
-                                     PVOID cookie);
+  using EnumRelocsFunction = bool (*)(const PEImage&, WORD, PVOID, PVOID);
 
   explicit PEImage(HMODULE module) : module_(module) {}
   explicit PEImage(const void* module) {
diff --git a/base/win/scoped_handle.h b/base/win/scoped_handle.h
index 8720889..9055e3e 100644
--- a/base/win/scoped_handle.h
+++ b/base/win/scoped_handle.h
@@ -38,7 +38,7 @@
 template <class Traits, class Verifier>
 class GenericScopedHandle {
  public:
-  typedef typename Traits::Handle Handle;
+  using Handle = typename Traits::Handle;
 
   GenericScopedHandle() : handle_(Traits::NullHandle()) {}
 
@@ -113,7 +113,7 @@
 // The traits class for Win32 handles that can be closed via CloseHandle() API.
 class HandleTraits {
  public:
-  typedef HANDLE Handle;
+  using Handle = HANDLE;
 
   // Closes the handle.
   static bool BASE_EXPORT CloseHandle(HANDLE handle);
@@ -133,7 +133,7 @@
 // Do-nothing verifier.
 class DummyVerifierTraits {
  public:
-  typedef HANDLE Handle;
+  using Handle = HANDLE;
 
   static void StartTracking(HANDLE handle,
                             const void* owner,
@@ -151,7 +151,7 @@
 // Performs actual run-time tracking.
 class BASE_EXPORT VerifierTraits {
  public:
-  typedef HANDLE Handle;
+  using Handle = HANDLE;
 
   static void StartTracking(HANDLE handle,
                             const void* owner,
@@ -166,7 +166,7 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(VerifierTraits);
 };
 
-typedef GenericScopedHandle<HandleTraits, VerifierTraits> ScopedHandle;
+using ScopedHandle = GenericScopedHandle<HandleTraits, VerifierTraits>;
 
 // This function may be called by the embedder to disable the use of
 // VerifierTraits at runtime. It has no effect if DummyVerifierTraits is used
diff --git a/base/win/scoped_handle_unittest.cc b/base/win/scoped_handle_unittest.cc
index d9ffbc86..8f7bfc5 100644
--- a/base/win/scoped_handle_unittest.cc
+++ b/base/win/scoped_handle_unittest.cc
@@ -52,7 +52,7 @@
 TEST(ScopedHandleTest, ActiveVerifierTrackedHasBeenClosed) {
   HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
   ASSERT_NE(HANDLE(nullptr), handle);
-  typedef NTSTATUS(WINAPI * NtCloseFunc)(HANDLE);
+  using NtCloseFunc = decltype(&::NtClose);
   NtCloseFunc ntclose = reinterpret_cast<NtCloseFunc>(
       GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtClose"));
   ASSERT_NE(nullptr, ntclose);
diff --git a/base/win/scoped_handle_verifier.cc b/base/win/scoped_handle_verifier.cc
index 916d413e..21471e1 100644
--- a/base/win/scoped_handle_verifier.cc
+++ b/base/win/scoped_handle_verifier.cc
@@ -27,12 +27,12 @@
 namespace {
 
 base::win::internal::ScopedHandleVerifier* g_active_verifier = nullptr;
-typedef void* (*GetHandleVerifierFn)();
-typedef std::unordered_map<HANDLE,
-                           base::win::internal::ScopedHandleVerifierInfo,
-                           base::win::internal::HandleHash>
-    HandleMap;
-typedef base::internal::LockImpl NativeLock;
+using GetHandleVerifierFn = void* (*)();
+using HandleMap =
+    std::unordered_map<HANDLE,
+                       base::win::internal::ScopedHandleVerifierInfo,
+                       base::win::internal::HandleHash>;
+using NativeLock = base::internal::LockImpl;
 
 NativeLock* GetLock() {
   static auto* native_lock = new NativeLock();
diff --git a/base/win/win_util.cc b/base/win/win_util.cc
index bca2c75..450c4ea3 100644
--- a/base/win/win_util.cc
+++ b/base/win/win_util.cc
@@ -289,7 +289,7 @@
   // 3. If step 1 and 2 fail then we check attached keyboards and return true
   //    if we find ACPI\* or HID\VID* keyboards.
 
-  typedef BOOL(WINAPI * GetAutoRotationState)(PAR_STATE state);
+  using GetAutoRotationState = decltype(&::GetAutoRotationState);
   static const auto get_rotation_state = reinterpret_cast<GetAutoRotationState>(
       GetUser32FunctionPointer("GetAutoRotationState"));
   if (get_rotation_state) {
@@ -550,7 +550,7 @@
   // a convertible or a detachable.
   // See
   // https://msdn.microsoft.com/en-us/library/windows/desktop/dn629263(v=vs.85).aspx
-  typedef decltype(GetAutoRotationState)* GetAutoRotationStateType;
+  using GetAutoRotationStateType = decltype(GetAutoRotationState)*;
   static const auto get_auto_rotation_state_func =
       reinterpret_cast<GetAutoRotationStateType>(
           GetUser32FunctionPointer("GetAutoRotationState"));
@@ -601,8 +601,8 @@
     if (GetVersion() < Version::WIN8)
       return true;
 
-    typedef decltype(
-        GetProcessMitigationPolicy)* GetProcessMitigationPolicyType;
+    using GetProcessMitigationPolicyType =
+        decltype(GetProcessMitigationPolicy)*;
     GetProcessMitigationPolicyType get_process_mitigation_policy_func =
         reinterpret_cast<GetProcessMitigationPolicyType>(GetProcAddress(
             GetModuleHandle(L"kernel32.dll"), "GetProcessMitigationPolicy"));
diff --git a/base/win/win_util.h b/base/win/win_util.h
index c0848b6..82c84e1 100644
--- a/base/win/win_util.h
+++ b/base/win/win_util.h
@@ -35,7 +35,7 @@
 
 struct IPropertyStore;
 struct _tagpropertykey;
-typedef _tagpropertykey PROPERTYKEY;
+using PROPERTYKEY = _tagpropertykey;
 
 namespace base {
 
diff --git a/base/win/windows_version.h b/base/win/windows_version.h
index cd36483..f7a25e7 100644
--- a/base/win/windows_version.h
+++ b/base/win/windows_version.h
@@ -14,7 +14,7 @@
 #include "base/macros.h"
 #include "base/version.h"
 
-typedef void* HANDLE;
+using HANDLE = void*;
 struct _OSVERSIONINFOEXW;
 struct _SYSTEM_INFO;
 
diff --git a/base/win/wrapped_window_proc.h b/base/win/wrapped_window_proc.h
index 0742019a0..ff2d4aa 100644
--- a/base/win/wrapped_window_proc.h
+++ b/base/win/wrapped_window_proc.h
@@ -23,7 +23,7 @@
 // expected behavior for this function is to not return, instead of returning
 // EXCEPTION_EXECUTE_HANDLER or similar, given that in general we are not
 // prepared to handle exceptions.
-typedef int(__cdecl* WinProcExceptionFilter)(EXCEPTION_POINTERS* info);
+using WinProcExceptionFilter = int __cdecl (*)(EXCEPTION_POINTERS* info);
 
 // Sets the filter to deal with exceptions inside a WindowProc. Returns the old
 // exception filter, if any.
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index c460db7..2e084b0 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -238,7 +238,11 @@
         if has_crazy_linker and not has_monochrome:
           basename = 'crazy.' + basename
 
-    apk_path = 'lib/%s/%s' % (android_abi, basename)
+    lib_android_abi = android_abi
+    if path.startswith('android_clang_arm64_hwasan/'):
+      lib_android_abi = 'arm64-v8a-hwasan'
+
+    apk_path = 'lib/%s/%s' % (lib_android_abi, basename)
     zipalign.AddToZipHermetic(
         out_apk,
         apk_path,
diff --git a/build/android/gyp/test/BUILD.gn b/build/android/gyp/test/BUILD.gn
index 6ac0810..301a220d 100644
--- a/build/android/gyp/test/BUILD.gn
+++ b/build/android/gyp/test/BUILD.gn
@@ -1,17 +1,11 @@
 import("//build/config/android/rules.gni")
 
 java_library("hello_world_java") {
-  sources = [
-    "java/org/chromium/helloworld/HelloWorldPrinter.java",
-  ]
+  sources = [ "java/org/chromium/helloworld/HelloWorldPrinter.java" ]
 }
 
 java_binary("hello_world") {
-  deps = [
-    ":hello_world_java",
-  ]
-  sources = [
-    "java/org/chromium/helloworld/HelloWorldMain.java",
-  ]
+  deps = [ ":hello_world_java" ]
+  sources = [ "java/org/chromium/helloworld/HelloWorldMain.java" ]
   main_class = "org.chromium.helloworld.HelloWorldMain"
 }
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py
index 76b33fc..ee41a6d2 100755
--- a/build/android/gyp/write_build_config.py
+++ b/build/android/gyp/write_build_config.py
@@ -789,7 +789,8 @@
   """Returns a java literal array with the "base" library names:
   e.g. libfoo.so -> foo
   """
-  return ('{%s}' % ','.join(['"%s"' % s[3:-3] for s in library_paths]))
+  names = ['"%s"' % os.path.basename(s)[3:-3] for s in library_paths]
+  return ('{%s}' % ','.join(sorted(set(names))))
 
 
 def _CreateJavaLocaleListFromAssets(assets, locale_paks):
diff --git a/build/config/android/abi.gni b/build/config/android/abi.gni
index 3029320..ed7c2ff 100644
--- a/build/config/android/abi.gni
+++ b/build/config/android/abi.gni
@@ -26,6 +26,9 @@
   # Only effective if use_order_profiling = true. When this is true the call
   # graph based instrumentation is used.
   use_call_graph = false
+
+  # Build additional browser splits with HWASAN instrumentation enabled.
+  build_hwasan_splits = false
 }
 
 assert(!devtools_instrumentation_dumping || use_order_profiling,
diff --git a/build/config/android/extract_unwind_tables.gni b/build/config/android/extract_unwind_tables.gni
index b56ebcfb..a732d66b 100644
--- a/build/config/android/extract_unwind_tables.gni
+++ b/build/config/android/extract_unwind_tables.gni
@@ -21,12 +21,8 @@
     }
 
     script = "//build/android/gyp/extract_unwind_tables.py"
-    outputs = [
-      _asset_path,
-    ]
-    inputs = [
-      "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension",
-    ]
+    outputs = [ _asset_path ]
+    inputs = [ "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension" ]
 
     args = [
       "--input_path",
@@ -45,12 +41,8 @@
     if (defined(invoker.testonly)) {
       testonly = invoker.testonly
     }
-    sources = [
-      _asset_path,
-    ]
+    sources = [ _asset_path ]
     disable_compression = true
-    deps = [
-      ":$_unwind_action",
-    ]
+    deps = [ ":$_unwind_action" ]
   }
 }
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index cbd235d..047364b 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -116,15 +116,11 @@
     _parent_invoker = invoker.invoker
     _target_label =
         get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain")
-    sources = [
-      _target_label,
-    ]
+    sources = [ _target_label ]
     if (sources != []) {
       set_sources_assignment_filter(_java_target_blacklist)
       sources = []
-      sources = [
-        _target_label,
-      ]
+      sources = [ _target_label ]
       if (sources != []) {
         assert(false, "Invalid java target name: $_target_label")
       }
@@ -148,24 +144,18 @@
     script = "//build/android/gyp/write_build_config.py"
     depfile = "$target_gen_dir/$target_name.d"
     inputs = []
-    outputs = [
-      invoker.build_config,
-    ]
+    outputs = [ invoker.build_config ]
 
     _deps_configs = []
     if (defined(invoker.possible_config_deps)) {
       foreach(_possible_dep, invoker.possible_config_deps) {
         set_sources_assignment_filter(_java_target_whitelist)
         _target_label = get_label_info(_possible_dep, "label_no_toolchain")
-        sources = [
-          _target_label,
-        ]
+        sources = [ _target_label ]
         if (sources == []) {
           set_sources_assignment_filter(_java_target_blacklist)
           sources = []
-          sources = [
-            _target_label,
-          ]
+          sources = [ _target_label ]
           if (sources != []) {
             # Put the bug number in the target name so that false-positives
             # have a hint in the error message about non-existent dependencies.
@@ -581,13 +571,9 @@
     _install_artifacts_json =
         "${target_gen_dir}/${target_name}.install_artifacts"
     generated_file("${target_name}__install_artifacts") {
-      deps = [
-        invoker.apk_under_test,
-      ]
+      deps = [ invoker.apk_under_test ]
       output_conversion = "json"
-      outputs = [
-        _install_artifacts_json,
-      ]
+      outputs = [ _install_artifacts_json ]
       data_keys = [ "install_artifacts" ]
       walk_keys = [ "install_artifacts_barrier" ]
       rebase = root_build_dir
@@ -974,9 +960,7 @@
       pool = "//build/toolchain:link_pool($default_toolchain)"
 
       _output_path = invoker.output_path
-      inputs = [
-        invoker.build_config,
-      ]
+      inputs = [ invoker.build_config ]
       if (defined(invoker.inputs)) {
         inputs += invoker.inputs
       }
@@ -1092,13 +1076,9 @@
       _script_name = invoker.script_name
 
       script = "//build/android/gyp/create_java_binary_script.py"
-      inputs = [
-        _build_config,
-      ]
+      inputs = [ _build_config ]
       _java_script = "$root_build_dir/bin/$_script_name"
-      outputs = [
-        _java_script,
-      ]
+      outputs = [ _java_script ]
       _rebased_build_config = rebase_path(_build_config, root_build_dir)
       args = [
         "--output",
@@ -1278,9 +1258,7 @@
                      _shrinked_android,
                    ] + _input_class_jars
 
-          outputs = [
-            _main_dex_list_path,
-          ]
+          outputs = [ _main_dex_list_path ]
 
           args = [
             "--depfile",
@@ -1340,9 +1318,7 @@
         script = "//build/android/gyp/dex.py"
         depfile = "$target_gen_dir/$target_name.d"
         inputs = []
-        outputs = [
-          invoker.output,
-        ]
+        outputs = [ invoker.output ]
 
         args = [
           "--depfile",
@@ -1584,9 +1560,7 @@
           _java_bytecode_rewriter_input_jar,
           _build_config,
         ]
-        outputs = [
-          _java_bytecode_rewriter_output_jar,
-        ]
+        outputs = [ _java_bytecode_rewriter_output_jar ]
         args = [
           "--script",
           rebase_path(_bytecode_rewriter_script, root_build_dir),
@@ -1644,9 +1618,7 @@
           _desugar_input_jar,
           _desugar_jar,
         ]
-        outputs = [
-          _desugar_output_jar,
-        ]
+        outputs = [ _desugar_output_jar ]
         args = [
           "--desugar-jar",
           rebase_path(_desugar_jar, root_build_dir),
@@ -1684,9 +1656,7 @@
           _build_config,
           _filter_input_jar,
         ]
-        outputs = [
-          _filter_output_jar,
-        ]
+        outputs = [ _filter_output_jar ]
         args = [
           "--input",
           rebase_path(_filter_input_jar, root_build_dir),
@@ -1744,12 +1714,8 @@
         deps += invoker.deps
       }
       dest = _output_jar_path
-      sources = [
-        _previous_output_jar,
-      ]
-      outputs = [
-        _output_jar_path,
-      ]
+      sources = [ _previous_output_jar ]
+      outputs = [ _output_jar_path ]
     }
 
     group(target_name) {
@@ -1758,9 +1724,7 @@
                                "data_deps",
                                "visibility",
                              ])
-      public_deps = [
-        ":$_output_jar_target",
-      ]
+      public_deps = [ ":$_output_jar_target" ]
     }
   }
 
@@ -1779,9 +1743,7 @@
         invoker.input_manifest,
       ]
 
-      outputs = [
-        invoker.output_manifest,
-      ]
+      outputs = [ invoker.output_manifest ]
       _rebased_build_config = rebase_path(invoker.build_config, root_build_dir)
 
       args = [
@@ -2120,9 +2082,7 @@
       ]
 
       inputs += [ invoker.android_manifest ]
-      outputs = [
-        _intermediate_srcjar_path,
-      ]
+      outputs = [ _intermediate_srcjar_path ]
       args += [
         "--android-manifest",
         rebase_path(invoker.android_manifest, root_build_dir),
@@ -2416,9 +2376,7 @@
           _output_apk,
           _final_srcjar_path,
         ]
-        public_deps = [
-          ":${_compile_resources_target_name}",
-        ]
+        public_deps = [ ":${_compile_resources_target_name}" ]
       }
     }
   }
@@ -2539,9 +2497,7 @@
       depfile = "$target_gen_dir/$target_name.d"
       _apksigner = "$android_sdk_build_tools/lib/apksigner.jar"
       _zipalign = "$android_sdk_build_tools/zipalign"
-      data_deps = [
-        "//tools/android/md5sum",
-      ]  # Used when deploying APKs
+      data_deps = [ "//tools/android/md5sum" ]
 
       inputs = [
         invoker.keystore_path,
@@ -2550,12 +2506,8 @@
         _zipalign,
       ]
 
-      outputs = [
-        invoker.output_apk_path,
-      ]
-      data = [
-        invoker.output_apk_path,
-      ]
+      outputs = [ invoker.output_apk_path ]
+      data = [ invoker.output_apk_path ]
 
       _rebased_compiled_resources_path =
           rebase_path(invoker.packaged_resources_path, root_build_dir)
@@ -2742,9 +2694,7 @@
         deps += invoker.deps
       }
 
-      outputs = [
-        invoker.javac_jar_path,
-      ]
+      outputs = [ invoker.javac_jar_path ]
       if (!invoker.enable_errorprone) {
         outputs += [ invoker.javac_jar_path + ".info" ]
       }
@@ -2844,9 +2794,7 @@
                                "visibility",
                              ])
       script = "//build/android/gyp/ijar.py"
-      deps = [
-        _ijar_target,
-      ]
+      deps = [ _ijar_target ]
       if (defined(invoker.deps)) {
         deps += invoker.deps
       }
@@ -2857,9 +2805,7 @@
       if (defined(invoker.inputs)) {
         inputs += invoker.inputs
       }
-      outputs = [
-        invoker.output_jar,
-      ]
+      outputs = [ invoker.output_jar ]
       args = [
         rebase_path(_ijar_executable, root_build_dir),
         rebase_path(invoker.input_jar, root_build_dir),
@@ -3124,9 +3070,7 @@
     } else {
       # Default based on whether target is in third_party.
       set_sources_assignment_filter([ "*\bthird_party\b*" ])
-      sources = [
-        get_label_info(":$_main_target_name", "dir"),
-      ]
+      sources = [ get_label_info(":$_main_target_name", "dir") ]
       _chromium_code = sources != []
       if (!_chromium_code && !_is_prebuilt && _java_files != []) {
         # Unless third_party code has an org.chromium file in it.
@@ -3409,13 +3353,9 @@
         # Use copy_ex rather than copy to ensure that we copy symlink targets
         # rather than the symlink itself.
         copy_ex(_copy_system_library_target_name) {
-          sources = [
-            _unprocessed_jar_path,
-          ]
+          sources = [ _unprocessed_jar_path ]
           dest = _final_jar_path
-          outputs = [
-            _final_jar_path,
-          ]
+          outputs = [ _final_jar_path ]
         }
         _accumulated_public_deps += [ ":$_copy_system_library_target_name" ]
       } else {
@@ -3452,9 +3392,7 @@
             # change just one class at a time.
             disable_incremental = _is_prebuilt
             output = _dex_path
-            deps = [
-              ":$_process_prebuilt_target_name",
-            ]
+            deps = [ ":$_process_prebuilt_target_name" ]
 
             # Should never need multidex when compiling individual libraries.
             # Disabling multidex saves on having to create a main_dex_list.
@@ -3604,9 +3542,7 @@
       invoker.build_config,
       invoker.native_libraries_config,
     ]
-    outputs = [
-      invoker.module_zip_path,
-    ]
+    outputs = [ invoker.module_zip_path ]
     args = [
       "--depfile",
       rebase_path(depfile, root_build_dir),
@@ -3676,9 +3612,7 @@
     forward_variables_from(invoker, [ "deps" ])
     script = "//build/android/gyp/dexsplitter.py"
     _stamp = "${target_gen_dir}/${target_name}.stamp"
-    outputs = [
-      _stamp,
-    ]
+    outputs = [ _stamp ]
 
     depfile = "${target_gen_dir}/${target_name}.d"
     args = [
@@ -3736,9 +3670,7 @@
       "--output",
       rebase_path(invoker.output, root_build_dir),
     ]
-    outputs = [
-      invoker.output,
-    ]
+    outputs = [ invoker.output ]
     deps = []
     if (defined(invoker.deps)) {
       deps += invoker.deps
diff --git a/build/config/android/linker_version_script.gni b/build/config/android/linker_version_script.gni
index c7cc4fb..12a123d4 100644
--- a/build/config/android/linker_version_script.gni
+++ b/build/config/android/linker_version_script.gni
@@ -17,9 +17,7 @@
 template("generate_linker_version_script") {
   action_with_pydeps(target_name) {
     script = "//build/android/gyp/generate_linker_version_script.py"
-    outputs = [
-      invoker.linker_script,
-    ]
+    outputs = [ invoker.linker_script ]
     inputs = []
     args = [ "--output=" + rebase_path(invoker.linker_script, root_build_dir) ]
 
diff --git a/build/config/android/test/proto/BUILD.gn b/build/config/android/test/proto/BUILD.gn
index f2222cb..a28111a 100644
--- a/build/config/android/test/proto/BUILD.gn
+++ b/build/config/android/test/proto/BUILD.gn
@@ -55,16 +55,12 @@
 
 proto_java_library("absolute_dep_proto_java") {
   proto_path = "//"
-  sources = [
-    "absolute_dep/absolute_dep.proto",
-  ]
+  sources = [ "absolute_dep/absolute_dep.proto" ]
 }
 
 proto_java_library("relative_dep_proto_java") {
   proto_path = "relative_dep/"
-  sources = [
-    "relative_dep/relative_dep.proto",
-  ]
+  sources = [ "relative_dep/relative_dep.proto" ]
 }
 
 proto_library("absolute_root_proto") {
@@ -98,14 +94,10 @@
 
 proto_library("absolute_dep_proto") {
   proto_in_dir = "//"
-  sources = [
-    "absolute_dep/absolute_dep.proto",
-  ]
+  sources = [ "absolute_dep/absolute_dep.proto" ]
 }
 
 proto_library("relative_dep_proto") {
   proto_in_dir = "relative_dep/"
-  sources = [
-    "relative_dep/relative_dep.proto",
-  ]
+  sources = [ "relative_dep/relative_dep.proto" ]
 }
diff --git a/build/config/ios/asset_catalog.gni b/build/config/ios/asset_catalog.gni
index 68979b07..ed9254c 100644
--- a/build/config/ios/asset_catalog.gni
+++ b/build/config/ios/asset_catalog.gni
@@ -48,9 +48,7 @@
 
   if (current_toolchain != default_toolchain) {
     group(target_name) {
-      public_deps = [
-        ":$target_name($default_toolchain)",
-      ]
+      public_deps = [ ":$target_name($default_toolchain)" ]
     }
   } else {
     _copy_target_name = target_name + "__copy"
@@ -108,12 +106,8 @@
                              ])
 
       sources = _outputs
-      outputs = [
-        "{{bundle_resources_dir}}/{{source_file_part}}",
-      ]
-      public_deps = [
-        ":$_copy_target_name",
-      ]
+      outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
+      public_deps = [ ":$_copy_target_name" ]
     }
   }
 }
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index 63bd157..62c5597 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -66,9 +66,7 @@
     # http://crbug.com/762840. Fix for bots running out of memory.
     pool = "//build/toolchain:link_pool($default_toolchain)"
 
-    outputs = [
-      "$target_out_dir/$_output_name",
-    ]
+    outputs = [ "$target_out_dir/$_output_name" ]
 
     deps = []
     _index = 0
@@ -448,9 +446,7 @@
       _info_plist,
     ]
     if (defined(invoker.info_plist_target)) {
-      deps = [
-        invoker.info_plist_target,
-      ]
+      deps = [ invoker.info_plist_target ]
     }
     forward_variables_from(invoker,
                            [
@@ -690,9 +686,7 @@
                                "visibility",
                                "testonly",
                              ])
-      public_deps = [
-        ":$_arch_executable_target",
-      ]
+      public_deps = [ ":$_arch_executable_target" ]
     }
   } else {
     lipo_binary(_lipo_executable_target) {
@@ -745,9 +739,7 @@
         _info_plist_path = _gen_info_plist_outputs[0]
 
         script = "//build/config/ios/codesign.py"
-        deps = [
-          ":$_generate_info_plist",
-        ]
+        deps = [ ":$_generate_info_plist" ]
         if (defined(invoker.entitlements_target)) {
           deps += [ invoker.entitlements_target ]
         }
@@ -755,9 +747,7 @@
           _entitlements_path,
           _info_plist_path,
         ]
-        outputs = [
-          _generate_entitlements_output,
-        ]
+        outputs = [ _generate_entitlements_output ]
 
         args = [
                  "generate-entitlements",
@@ -798,21 +788,15 @@
         ]
         args = [ "--plist" ] + rebase_path(sources, root_build_dir) +
                [ "--output" ] + rebase_path(outputs, root_build_dir)
-        deps = [
-          ":$_generate_info_plist",
-        ]
+        deps = [ ":$_generate_info_plist" ]
       }
 
       _bundle_data_pkg_info = target_name + "_bundle_data_pkg_info"
       bundle_data(_bundle_data_pkg_info) {
         forward_variables_from(invoker, [ "testonly" ])
         sources = get_target_outputs(":$_create_pkg_info")
-        outputs = [
-          "{{bundle_resources_dir}}/PkgInfo",
-        ]
-        public_deps = [
-          ":$_create_pkg_info",
-        ]
+        outputs = [ "{{bundle_resources_dir}}/PkgInfo" ]
+        public_deps = [ ":$_create_pkg_info" ]
       }
     }
 
@@ -880,12 +864,8 @@
           public_deps += [ ":${_variant.target_name}" ]
         }
 
-        sources = [
-          "${_default_variant.bundle_gen_dir}/$_bundle_short_name",
-        ]
-        outputs = [
-          "$root_out_dir/$_bundle_short_name",
-        ]
+        sources = [ "${_default_variant.bundle_gen_dir}/$_bundle_short_name" ]
+        outputs = [ "$root_out_dir/$_bundle_short_name" ]
 
         args = rebase_path(sources, root_out_dir) +
                rebase_path(outputs, root_out_dir)
@@ -1025,9 +1005,7 @@
   }
 
   compile_ib_files(_compile_ib_file) {
-    sources = [
-      invoker.source,
-    ]
+    sources = [ invoker.source ]
     output_extension = _output_extension
     visibility = [ ":$_target_name" ]
     ibtool_flags = [
@@ -1051,9 +1029,7 @@
 
     sources = get_target_outputs(":$_compile_ib_file")
 
-    outputs = [
-      "{{bundle_resources_dir}}/{{source_file_part}}",
-    ]
+    outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
   }
 }
 
@@ -1103,9 +1079,7 @@
 
     sources = get_target_outputs(":$_convert_target")
 
-    outputs = [
-      invoker.output,
-    ]
+    outputs = [ invoker.output ]
   }
 }
 
@@ -1353,9 +1327,7 @@
                                "visibility",
                                "testonly",
                              ])
-      public_deps = [
-        ":$_arch_shared_library_target",
-      ]
+      public_deps = [ ":$_arch_shared_library_target" ]
     }
 
     group(_link_target_name) {
@@ -1365,9 +1337,7 @@
                                "visibility",
                                "testonly",
                              ])
-      public_deps = [
-        ":$_link_target_name($default_toolchain)",
-      ]
+      public_deps = [ ":$_link_target_name($default_toolchain)" ]
 
       if (_has_public_headers) {
         if (!defined(public_configs)) {
@@ -1399,9 +1369,7 @@
                                  "testonly",
                                ])
         script = "//build/config/ios/write_framework_hmap.py"
-        outputs = [
-          _header_map_filename,
-        ]
+        outputs = [ _header_map_filename ]
 
         # The header map generation only wants the list of headers, not all of
         # sources, so filter any non-header source files from "sources". It is
@@ -1424,9 +1392,7 @@
       action(_create_module_map_target) {
         visibility = [ ":$_framework_headers_target" ]
         script = "//build/config/ios/write_framework_modulemap.py"
-        outputs = [
-          "$_framework_root/Modules/module.modulemap",
-        ]
+        outputs = [ "$_framework_root/Modules/module.modulemap" ]
         args = [ rebase_path("$_framework_root", root_build_dir) ]
       }
 
@@ -1439,9 +1405,7 @@
                                ])
         visibility = [ ":$_framework_headers_target" ]
         sources = _public_headers
-        outputs = [
-          "$_framework_root/Headers/{{source_file_part}}",
-        ]
+        outputs = [ "$_framework_root/Headers/{{source_file_part}}" ]
 
         # Do not use forward_variables_from for "public_deps" as
         # we do not want to forward those dependencies.
@@ -1459,9 +1423,7 @@
           ":$_compile_headers_map_target",
           ":$_create_module_map_target",
         ]
-        public_deps = [
-          ":$_copy_public_headers_target",
-        ]
+        public_deps = [ ":$_copy_public_headers_target" ]
       }
     }
 
@@ -1495,12 +1457,8 @@
       visibility = [ ":${_target_name}_signed_bundle" ]
       forward_variables_from(invoker, [ "testonly" ])
       sources = get_target_outputs(":$_info_plist_target")
-      outputs = [
-        "{{bundle_contents_dir}}/Info.plist",
-      ]
-      public_deps = [
-        ":$_info_plist_target",
-      ]
+      outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
+      public_deps = [ ":$_info_plist_target" ]
     }
 
     create_signed_bundle(_target_name + "_signed_bundle") {
@@ -1582,15 +1540,10 @@
                                "testonly",
                                "visibility",
                              ])
-      public_deps = [
-        ":$_target_name",
-      ]
-      sources = [
-        "$root_out_dir/$_output_name.framework",
-      ]
-      outputs = [
-        "{{bundle_resources_dir}}/Frameworks/$_output_name.framework",
-      ]
+      public_deps = [ ":$_target_name" ]
+      sources = [ "$root_out_dir/$_output_name.framework" ]
+      outputs =
+          [ "{{bundle_resources_dir}}/Frameworks/$_output_name.framework" ]
     }
   }
 }
@@ -1671,9 +1624,7 @@
       visibility += [ ":$_target_name" ]
     }
 
-    deps = [
-      ":$_arch_loadable_module_source",
-    ]
+    deps = [ ":$_arch_loadable_module_source" ]
     configs += [ "//build/config/ios:xctest_config" ]
 
     output_dir = "$target_out_dir/$current_cpu"
@@ -1690,9 +1641,7 @@
       forward_variables_from(invoker, [ "visibility" ])
       testonly = true
 
-      public_deps = [
-        ":$_arch_loadable_module_target",
-      ]
+      public_deps = [ ":$_arch_loadable_module_target" ]
     }
 
     # Force the use of invoker.xctest_bundle_principal_class if it is
@@ -1728,14 +1677,10 @@
       testonly = true
       visibility = [ ":$_target_name" ]
 
-      public_deps = [
-        ":$_info_plist_target",
-      ]
+      public_deps = [ ":$_info_plist_target" ]
 
       sources = get_target_outputs(":$_info_plist_target")
-      outputs = [
-        "{{bundle_contents_dir}}/Info.plist",
-      ]
+      outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
     }
 
     lipo_binary(_lipo_loadable_module_target) {
@@ -1791,9 +1736,7 @@
         }
       }
 
-      deps = [
-        ":$_info_plist_bundle",
-      ]
+      deps = [ ":$_info_plist_bundle" ]
     }
 
     bundle_data(_xctest_bundle) {
@@ -1802,15 +1745,9 @@
       testonly = true
       visibility = [ ":$host_target" ]
 
-      public_deps = [
-        ":$_target_name",
-      ]
-      sources = [
-        "$root_out_dir/$_output_name.xctest",
-      ]
-      outputs = [
-        "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest",
-      ]
+      public_deps = [ ":$_target_name" ]
+      sources = [ "$root_out_dir/$_output_name.xctest" ]
+      outputs = [ "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest" ]
     }
   }
 }
@@ -1844,9 +1781,7 @@
     _xctest_module_target_name = _xctest_target + "shell_source"
     _xctest_module_target = ":$_xctest_module_target_name"
     source_set(_xctest_module_target_name) {
-      sources = [
-        "//build/config/ios/xctest_shell.mm",
-      ]
+      sources = [ "//build/config/ios/xctest_shell.mm" ]
 
       configs += [ "//build/config/ios:xctest_config" ]
     }
@@ -1858,9 +1793,7 @@
     host_target = _host_target
     xcode_test_application_name = _host_output
 
-    deps = [
-      _xctest_module_target,
-    ]
+    deps = [ _xctest_module_target ]
   }
 
   ios_app_bundle(_host_target) {
@@ -1960,9 +1893,7 @@
     ]
 
     _output_name = "$target_gen_dir/${_target_name}_merged.plist"
-    outputs = [
-      _output_name,
-    ]
+    outputs = [ _output_name ]
     args = [
              "merge",
              "-f=xml1",
@@ -1982,14 +1913,10 @@
     testonly = true
     visibility = [ ":$_target_name" ]
 
-    public_deps = [
-      ":$_info_plist_target",
-    ]
+    public_deps = [ ":$_info_plist_target" ]
 
     sources = get_target_outputs(":$_info_plist_target")
-    outputs = [
-      "{{bundle_contents_dir}}/Info.plist",
-    ]
+    outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
   }
 
   _pkginfo_bundle = _target_name + "_pkginfo_bundle"
@@ -1997,13 +1924,9 @@
     testonly = true
     visibility = [ ":$_target_name" ]
 
-    sources = [
-      "$_xctrunner_path/PkgInfo",
-    ]
+    sources = [ "$_xctrunner_path/PkgInfo" ]
 
-    outputs = [
-      "{{bundle_contents_dir}}/PkgInfo",
-    ]
+    outputs = [ "{{bundle_contents_dir}}/PkgInfo" ]
   }
 
   _xctest_bundle = invoker.xctest_bundle
@@ -2064,9 +1987,7 @@
   group(_xcuitest_target) {
     testonly = true
 
-    deps = [
-      ":$_xcuitest_runner_target",
-    ]
+    deps = [ ":$_xcuitest_runner_target" ]
   }
 
   _xcuitest_module_output = _xcuitest_target
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index 7a58bc33..f7bc1ce 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -253,7 +253,11 @@
 
   if (using_sanitizer) {
     assert(is_clang, "sanitizers only supported with clang")
-    assert(!is_official_build, "sanitizers not supported in official builds")
+
+    # Allow non-default toolchains to enable sanitizers in toolchain_args even
+    # in official builds.
+    assert(current_toolchain != default_toolchain || !is_official_build,
+           "sanitizers not supported in official builds")
 
     cflags += [
       # Column info in debug data confuses Visual Studio's debugger, so don't
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni
index bb58aa9..b79d65d 100644
--- a/build/config/sanitizers/sanitizers.gni
+++ b/build/config/sanitizers/sanitizers.gni
@@ -113,8 +113,8 @@
   archive_seed_corpus = true
 }
 
-# Disable sanitizers for non-default toolchains.
-if (current_toolchain != default_toolchain) {
+# Disable sanitizers for non-target toolchains.
+if (!is_a_target_toolchain) {
   is_asan = false
   is_cfi = false
   is_hwasan = false
diff --git a/build/toolchain/android/BUILD.gn b/build/toolchain/android/BUILD.gn
index 0ba5b2c1..ceca1a4 100644
--- a/build/toolchain/android/BUILD.gn
+++ b/build/toolchain/android/BUILD.gn
@@ -99,6 +99,15 @@
   }
 }
 
+android_clang_toolchain("android_clang_arm64_hwasan") {
+  binary_prefix = "aarch64-linux-android"
+  toolchain_args = {
+    current_cpu = "arm64"
+    is_hwasan = true
+    android64_ndk_api_level = 29
+  }
+}
+
 android_clang_toolchain("android_clang_mips64el") {
   binary_prefix = "mips64el-linux-android"
   toolchain_args = {
diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc
index 512c476..b85219a3 100644
--- a/cc/paint/image_transfer_cache_entry.cc
+++ b/cc/paint/image_transfer_cache_entry.cc
@@ -259,7 +259,7 @@
   // We don't need to populate the SerializeOptions here since the writer is
   // only used for serializing primitives.
   PaintOp::SerializeOptions options(nullptr, nullptr, nullptr, nullptr, nullptr,
-                                    nullptr, false, false, 0, 0, SkMatrix::I());
+                                    nullptr, false, false, 0, SkMatrix::I());
   PaintOpWriter writer(data.data(), data.size(), options);
   writer.Write(static_cast<uint32_t>(IsYuv() ? 1 : 0));
 
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 69d3c09..b7a6c128 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -341,7 +341,6 @@
     bool can_use_lcd_text,
     bool context_supports_distance_field_text,
     int max_texture_size,
-    size_t max_texture_bytes,
     const SkMatrix& original_ctm)
     : image_provider(image_provider),
       transfer_cache(transfer_cache),
@@ -353,7 +352,6 @@
       context_supports_distance_field_text(
           context_supports_distance_field_text),
       max_texture_size(max_texture_size),
-      max_texture_bytes(max_texture_bytes),
       original_ctm(original_ctm) {}
 
 PaintOp::SerializeOptions::SerializeOptions(const SerializeOptions&) = default;
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 7943996..12b1cf4 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -155,7 +155,6 @@
                      bool can_use_lcd_text,
                      bool context_supports_distance_field_text,
                      int max_texture_size,
-                     size_t max_texture_bytes,
                      const SkMatrix& original_ctm);
     SerializeOptions(const SerializeOptions&);
     SerializeOptions& operator=(const SerializeOptions&);
@@ -171,7 +170,6 @@
     bool can_use_lcd_text = false;
     bool context_supports_distance_field_text = true;
     int max_texture_size = 0;
-    size_t max_texture_bytes = 0.f;
     SkMatrix original_ctm = SkMatrix::I();
 
     // Optional.
diff --git a/cc/paint/paint_op_buffer_serializer.cc b/cc/paint/paint_op_buffer_serializer.cc
index 64a0d00..7601f97 100644
--- a/cc/paint/paint_op_buffer_serializer.cc
+++ b/cc/paint/paint_op_buffer_serializer.cc
@@ -61,8 +61,7 @@
     sk_sp<SkColorSpace> color_space,
     bool can_use_lcd_text,
     bool context_supports_distance_field_text,
-    int max_texture_size,
-    size_t max_texture_bytes)
+    int max_texture_size)
     : serialize_cb_(std::move(serialize_cb)),
       image_provider_(image_provider),
       transfer_cache_(transfer_cache),
@@ -73,7 +72,6 @@
       context_supports_distance_field_text_(
           context_supports_distance_field_text),
       max_texture_size_(max_texture_size),
-      max_texture_bytes_(max_texture_bytes),
       text_blob_canvas_(kMaxExtent,
                         kMaxExtent,
                         ComputeSurfaceProps(can_use_lcd_text),
@@ -417,7 +415,7 @@
       image_provider_, transfer_cache_, paint_cache_, &text_blob_canvas_,
       strike_server_, color_space_, can_use_lcd_text_,
       context_supports_distance_field_text_, max_texture_size_,
-      max_texture_bytes_, text_blob_canvas_.getTotalMatrix());
+      text_blob_canvas_.getTotalMatrix());
 }
 
 SimpleBufferSerializer::SimpleBufferSerializer(
@@ -430,8 +428,7 @@
     sk_sp<SkColorSpace> color_space,
     bool can_use_lcd_text,
     bool context_supports_distance_field_text,
-    int max_texture_size,
-    size_t max_texture_bytes)
+    int max_texture_size)
     : PaintOpBufferSerializer(
           base::BindRepeating(&SimpleBufferSerializer::SerializeToMemory,
                               base::Unretained(this)),
@@ -442,8 +439,7 @@
           std::move(color_space),
           can_use_lcd_text,
           context_supports_distance_field_text,
-          max_texture_size,
-          max_texture_bytes),
+          max_texture_size),
       memory_(memory),
       total_(size) {}
 
diff --git a/cc/paint/paint_op_buffer_serializer.h b/cc/paint/paint_op_buffer_serializer.h
index e144bc1..88eb914a 100644
--- a/cc/paint/paint_op_buffer_serializer.h
+++ b/cc/paint/paint_op_buffer_serializer.h
@@ -28,8 +28,7 @@
                           sk_sp<SkColorSpace> color_space,
                           bool can_use_lcd_text,
                           bool context_supports_distance_field_text,
-                          int max_texture_size,
-                          size_t max_texture_bytes);
+                          int max_texture_size);
   virtual ~PaintOpBufferSerializer();
 
   struct Preamble {
@@ -114,7 +113,6 @@
   bool can_use_lcd_text_;
   bool context_supports_distance_field_text_;
   int max_texture_size_;
-  size_t max_texture_bytes_;
 
   SkTextBlobCacheDiffCanvas text_blob_canvas_;
   bool valid_ = true;
@@ -132,8 +130,7 @@
                          sk_sp<SkColorSpace> color_space,
                          bool can_use_lcd_text,
                          bool context_supports_distance_field_text,
-                         int max_texture_size,
-                         size_t max_texture_bytes);
+                         int max_texture_size);
   ~SimpleBufferSerializer() override;
 
   size_t written() const { return written_; }
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index c000f33..d7f1e5d 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1988,8 +1988,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer, nullptr, preamble);
   ASSERT_NE(serializer.written(), 0u);
 
@@ -2068,8 +2067,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer, nullptr, preamble);
   ASSERT_NE(serializer.written(), 0u);
 
@@ -2171,8 +2169,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   PaintOpBufferSerializer::Preamble preamble;
   serializer.Serialize(&buffer, nullptr, preamble);
   ASSERT_NE(serializer.written(), 0u);
@@ -2248,8 +2245,7 @@
         options_provider.client_paint_cache(), options_provider.strike_server(),
         options_provider.color_space(), options_provider.can_use_lcd_text(),
         options_provider.context_supports_distance_field_text(),
-        options_provider.max_texture_size(),
-        options_provider.max_texture_bytes());
+        options_provider.max_texture_size());
     PaintOpBufferSerializer::Preamble preamble;
     preamble.playback_rect = test_case.clip_rect;
     preamble.full_raster_rect = gfx::Rect(0, 0, test_case.clip_rect.right(),
@@ -2314,8 +2310,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer, nullptr, preamble);
   ASSERT_NE(serializer.written(), 0u);
 
@@ -3119,8 +3114,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer);
   ASSERT_NE(serializer.written(), 0u);
 
@@ -3266,8 +3260,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer);
   ASSERT_TRUE(serializer.valid());
   ASSERT_GT(serializer.written(), 0u);
@@ -3385,8 +3378,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(buffer.get());
 
   ASSERT_EQ(options_provider.decoded_images().size(), 1u);
@@ -3421,8 +3413,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(buffer.get());
 
   ASSERT_EQ(options_provider.decoded_images().size(), 1u);
@@ -3460,8 +3451,7 @@
         options_provider.client_paint_cache(), options_provider.strike_server(),
         options_provider.color_space(), options_provider.can_use_lcd_text(),
         options_provider.context_supports_distance_field_text(),
-        options_provider.max_texture_size(),
-        options_provider.max_texture_bytes());
+        options_provider.max_texture_size());
     serializer.Serialize(buffer.get());
     memory_written = serializer.written();
   }
@@ -3486,8 +3476,7 @@
         options_provider.client_paint_cache(), options_provider.strike_server(),
         options_provider.color_space(), options_provider.can_use_lcd_text(),
         options_provider.context_supports_distance_field_text(),
-        options_provider.max_texture_size(),
-        options_provider.max_texture_bytes());
+        options_provider.max_texture_size());
     serializer.Serialize(buffer.get());
     memory_scaled_written = serializer.written();
   }
@@ -3579,8 +3568,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   options_provider.context_supports_distance_field_text();
   serializer.Serialize(buffer.get());
 
@@ -3632,8 +3620,7 @@
       options_provider.client_paint_cache(), options_provider.strike_server(),
       options_provider.color_space(), options_provider.can_use_lcd_text(),
       options_provider.context_supports_distance_field_text(),
-      options_provider.max_texture_size(),
-      options_provider.max_texture_bytes());
+      options_provider.max_texture_size());
   serializer.Serialize(&buffer);
   ASSERT_TRUE(serializer.valid());
   ASSERT_GT(serializer.written(), 0u);
diff --git a/cc/paint/paint_op_perftest.cc b/cc/paint/paint_op_perftest.cc
index e3cd6cb..4dd80d1c 100644
--- a/cc/paint/paint_op_perftest.cc
+++ b/cc/paint/paint_op_perftest.cc
@@ -56,8 +56,7 @@
           test_options_provider.color_space(),
           test_options_provider.can_use_lcd_text(),
           test_options_provider.context_supports_distance_field_text(),
-          test_options_provider.max_texture_size(),
-          test_options_provider.max_texture_bytes());
+          test_options_provider.max_texture_size());
       serializer.Serialize(&buffer, nullptr, preamble);
       bytes_written = serializer.written();
 
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index 1d4c732..077f5fb 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -820,8 +820,7 @@
       memory_, remaining_bytes_, options_.image_provider,
       options_.transfer_cache, options_.paint_cache, options_.strike_server,
       options_.color_space, can_use_lcd_text,
-      options_.context_supports_distance_field_text, options_.max_texture_size,
-      options_.max_texture_bytes);
+      options_.context_supports_distance_field_text, options_.max_texture_size);
   serializer.Serialize(record, playback_rect, post_scale,
                        post_matrix_for_analysis);
 
diff --git a/cc/test/test_options_provider.cc b/cc/test/test_options_provider.cc
index ed1e9fb..7dd9010c 100644
--- a/cc/test/test_options_provider.cc
+++ b/cc/test/test_options_provider.cc
@@ -44,7 +44,6 @@
                          can_use_lcd_text_,
                          context_supports_distance_field_text_,
                          max_texture_size_,
-                         max_texture_bytes_,
                          SkMatrix::I()),
       deserialize_options_(this,
                            &service_paint_cache_,
diff --git a/cc/test/test_options_provider.h b/cc/test/test_options_provider.h
index 15881ea..3bb2b6b 100644
--- a/cc/test/test_options_provider.h
+++ b/cc/test/test_options_provider.h
@@ -48,7 +48,6 @@
     return context_supports_distance_field_text_;
   }
   int max_texture_size() const { return max_texture_size_; }
-  size_t max_texture_bytes() const { return max_texture_bytes_; }
 
   const std::vector<DrawImage>& decoded_images() const {
     return decoded_images_;
@@ -74,7 +73,6 @@
   bool can_use_lcd_text_ = true;
   bool context_supports_distance_field_text_ = true;
   int max_texture_size_ = 1024;
-  size_t max_texture_bytes_ = 4 * 1024 * 1024;
 
   ServicePaintCache service_paint_cache_;
   ClientPaintCache client_paint_cache_;
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 24b15abc..aea795f 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1072,13 +1072,9 @@
   DCHECK(IsUsingLayerLists());
   viewport_property_ids_ = ids;
   // Outer viewport properties exist only if inner viewport property exists.
-  // TODO(bokan): Temporarily make this a CHECK to debug crbug.com/1037759.
-  if (ids.inner_scroll == ScrollTree::kInvalidNodeId) {
-    CHECK_EQ(ids.outer_scroll, ScrollTree::kInvalidNodeId);
-    CHECK_EQ(ids.outer_clip, ClipTree::kInvalidNodeId);
-  } else {
-    CHECK_NE(ids.outer_scroll, ScrollTree::kInvalidNodeId);
-  }
+  DCHECK(ids.inner_scroll != ScrollTree::kInvalidNodeId ||
+         (ids.outer_scroll == ScrollTree::kInvalidNodeId &&
+          ids.outer_clip == ClipTree::kInvalidNodeId));
 }
 
 Layer* LayerTreeHost::InnerViewportScrollLayerForTesting() const {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index c878612..018d904 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -259,13 +259,9 @@
     if (is_viewport_scrollbar) {
       gfx::SizeF viewport_bounds(bounds_size);
       if (scroll_node->scrolls_inner_viewport) {
-        // TODO(bokan): Temporarily make these CHECKs to debug
-        // crbug.com/1037759.
-        CHECK_EQ(scroll_node, InnerViewportScrollNode());
+        DCHECK_EQ(scroll_node, InnerViewportScrollNode());
         auto* outer_scroll_node = OuterViewportScrollNode();
-        CHECK_NE(viewport_property_ids_.outer_scroll,
-                 ScrollTree::kInvalidNodeId);
-        CHECK(outer_scroll_node);
+        DCHECK(outer_scroll_node);
 
         // Add offset and bounds contribution of outer viewport.
         current_offset +=
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 8035baf..ac4ab383 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1536,9 +1536,8 @@
   }
 
   java_cpp_enum("cookie_controls_mode_javagen") {
-    sources = [
-      "../components/content_settings/core/browser/cookie_settings.h",
-    ]
+    sources =
+        [ "../components/content_settings/core/browser/cookie_settings.h" ]
   }
 
   java_cpp_enum("credit_card_javagen") {
diff --git a/chrome/VERSION b/chrome/VERSION
index 8f9c508..967ab92 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=81
 MINOR=0
-BUILD=4030
+BUILD=4031
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 111c59e..1825dbe2 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -757,12 +757,11 @@
   "java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java",
   "java/src/org/chromium/chrome/browser/gesturenav/CompositorNavigationGlow.java",
   "java/src/org/chromium/chrome/browser/gesturenav/GestureNavMetrics.java",
+  "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java",
   "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java",
-  "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java",
   "java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java",
   "java/src/org/chromium/chrome/browser/gesturenav/NavigationBubble.java",
   "java/src/org/chromium/chrome/browser/gesturenav/NavigationGlow.java",
-  "java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java",
   "java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java",
   "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java",
   "java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java",
@@ -1122,6 +1121,7 @@
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerFactory.java",
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java",
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java",
+  "java/src/org/chromium/chrome/browser/omaha/notification/UpdateUtils.java",
   "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java",
   "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java",
   "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 0d3abf1..a6aaccad 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -332,6 +332,7 @@
         defined(invoker.use_trichrome_library) && invoker.use_trichrome_library
     is_monochrome = !is_trichrome
 
+    shared_libraries = []
     loadable_modules = []
     secondary_abi_loadable_modules = []
 
@@ -444,6 +445,18 @@
     use_chromium_linker = is_trichrome && chromium_linker_supported
     use_modern_linker = use_chromium_linker
 
+    if (build_hwasan_splits && android_64bit_target_cpu &&
+        invoker.is_64_bit_browser) {
+      _hwasan_toolchain = "//build/toolchain/android:android_clang_arm64_hwasan"
+      shared_libraries +=
+          [ "//chrome/android:libmonochrome_64($_hwasan_toolchain)" ]
+
+      if (use_chromium_linker) {
+        shared_libraries +=
+            [ "//base/android/linker:chromium_android_linker($_hwasan_toolchain)" ]
+      }
+    }
+
     # Resources config for blocklisting resource names from obfuscation
     resources_config_path = "//android_webview/aapt2.config"
 
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
index e28b6875..d4c41b98 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -96,7 +96,7 @@
                     (SectionHeaderView) inflater.inflate(R.layout.ss_feed_header, null, false);
         }
         FeedSurfaceCoordinator feedSurfaceCoordinator = new FeedSurfaceCoordinator(mActivity, null,
-                null, null, sectionHeaderView, exploreSurfaceActionHandler, isInNightMode, this);
+                null, sectionHeaderView, exploreSurfaceActionHandler, isInNightMode, this);
         feedSurfaceCoordinator.getView().setId(R.id.start_surface_explore_view);
         return feedSurfaceCoordinator;
         // TODO(crbug.com/982018): Customize surface background for incognito and dark mode.
diff --git a/chrome/android/features/test_dummy/public/BUILD.gn b/chrome/android/features/test_dummy/public/BUILD.gn
index bb42ea9..2018bea5 100644
--- a/chrome/android/features/test_dummy/public/BUILD.gn
+++ b/chrome/android/features/test_dummy/public/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/features/test_dummy/TestDummy.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/chrome/features/test_dummy/TestDummy.java" ]
 }
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn
index ec02c9e..8500ffe 100644
--- a/chrome/android/features/vr/BUILD.gn
+++ b/chrome/android/features/vr/BUILD.gn
@@ -21,9 +21,7 @@
 android_resources("java_resources") {
   resource_dirs = [ "java/res" ]
 
-  deps = [
-    ":java_strings_grd",
-  ]
+  deps = [ ":java_strings_grd" ]
 
   custom_package = "org.chromium.chrome.vr"
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 3341c86..dbd407bc 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -90,7 +90,6 @@
         SectionHeaderView sectionHeaderView = (SectionHeaderView) inflater.inflate(
                 R.layout.new_tab_page_snippets_expandable_header, null, false);
         mCoordinator = new FeedSurfaceCoordinator(((TabImpl) mTab).getActivity(),
-                host.createHistoryNavigationDelegate(),
                 new SnapScrollHelper(mNewTabPageManager, mNewTabPageLayout), mNewTabPageLayout,
                 sectionHeaderView, actionApi,
                 ((TabImpl) mTab).getActivity().getNightModeStateProvider().isInNightMode(), this);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index ccdc5ce..e01904d 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -15,6 +15,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.widget.FrameLayout;
 import android.widget.ScrollView;
 
 import androidx.annotation.Nullable;
@@ -35,8 +36,6 @@
 import org.chromium.chrome.browser.feed.library.api.host.stream.StreamConfiguration;
 import org.chromium.chrome.browser.feed.library.api.host.stream.TooltipApi;
 import org.chromium.chrome.browser.feed.tooltip.BasicTooltipApi;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.ntp.NewTabPageLayout;
 import org.chromium.chrome.browser.ntp.SnapScrollHelper;
@@ -67,7 +66,7 @@
     private final FeedSurfaceMediator mMediator;
 
     private UiConfig mUiConfig;
-    private HistoryNavigationLayout mRootView;
+    private FrameLayout mRootView;
     private ContextMenuManager mContextMenuManager;
 
     // Used when Feed is enabled.
@@ -223,7 +222,7 @@
     /**
      * Provides the additional capabilities needed for the container view.
      */
-    private class RootView extends HistoryNavigationLayout {
+    private class RootView extends FrameLayout {
         /**
          * @param context The context of the application.
          */
@@ -265,7 +264,6 @@
      * Constructs a new FeedSurfaceCoordinator.
      *
      * @param activity The containing {@link ChromeActivity}.
-     * @param historyNavigationDelegate The {@link HistoryNavigationDelegate} for the root view.
      * @param snapScrollHelper The {@link SnapScrollHelper} for the New Tab Page.
      * @param ntpHeader The extra header on top of the feeds for the New Tab Page.
      * @param sectionHeaderView The {@link SectionHeaderView} for the feed.
@@ -274,7 +272,6 @@
      * @param delegate The constructing {@link FeedSurfaceDelegate}.
      */
     public FeedSurfaceCoordinator(ChromeActivity activity,
-            @Nullable HistoryNavigationDelegate historyNavigationDelegate,
             @Nullable SnapScrollHelper snapScrollHelper, @Nullable View ntpHeader,
             @Nullable SectionHeaderView sectionHeaderView, ActionApi actionApi,
             boolean showDarkBackground, FeedSurfaceDelegate delegate) {
@@ -292,9 +289,6 @@
 
         mRootView = new RootView(mActivity);
         mRootView.setPadding(0, resources.getDimensionPixelOffset(R.dimen.tab_strip_height), 0, 0);
-        if (historyNavigationDelegate != null) {
-            mRootView.setNavigationDelegate(historyNavigationDelegate);
-        }
         mUiConfig = new UiConfig(mRootView);
 
         // Mediator should be created before any Stream changes.
diff --git a/chrome/android/java/res/layout/explore_sites_page_layout.xml b/chrome/android/java/res/layout/explore_sites_page_layout.xml
index ef47196..8a2ac2b4 100644
--- a/chrome/android/java/res/layout/explore_sites_page_layout.xml
+++ b/chrome/android/java/res/layout/explore_sites_page_layout.xml
@@ -3,7 +3,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/history_navigation"
@@ -15,4 +15,4 @@
         android:scrollbars="vertical"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"/>
-</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout>
+</FrameLayout>
diff --git a/chrome/android/java/res/layout/recent_tabs_page.xml b/chrome/android/java/res/layout/recent_tabs_page.xml
index 8f96843..35913c4 100644
--- a/chrome/android/java/res/layout/recent_tabs_page.xml
+++ b/chrome/android/java/res/layout/recent_tabs_page.xml
@@ -4,7 +4,7 @@
      found in the LICENSE file. -->
 
 <!-- This single-child FrameLayout is needed for its top padding. -->
-<org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/history_navigation"
     android:layout_width="match_parent"
@@ -33,4 +33,4 @@
             android:scrollbarStyle="outsideOverlay" />
 
     </org.chromium.chrome.browser.ntp.NativePageRootFrameLayout>
-</org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout>
+</FrameLayout>
diff --git a/chrome/android/java/res/layout/selectable_list_layout.xml b/chrome/android/java/res/layout/selectable_list_layout.xml
index 2d9b64fc..8f356ea 100644
--- a/chrome/android/java/res/layout/selectable_list_layout.xml
+++ b/chrome/android/java/res/layout/selectable_list_layout.xml
@@ -21,7 +21,7 @@
         android:layout_height="@dimen/toolbar_height_no_shadow"
         android:background="@color/default_primary_color" />
 
-    <org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout
+    <FrameLayout
         android:id="@+id/list_content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -64,7 +64,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center" />
-    </org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout>
+    </FrameLayout>
 
     <org.chromium.components.browser_ui.widget.FadingShadowView
         android:id="@+id/shadow"
diff --git a/chrome/android/java/res_download/layout/download_manager_card_header.xml b/chrome/android/java/res_download/layout/download_manager_card_header.xml
index c72c8a7..5faa757 100644
--- a/chrome/android/java/res_download/layout/download_manager_card_header.xml
+++ b/chrome/android/java/res_download/layout/download_manager_card_header.xml
@@ -6,6 +6,7 @@
 
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@drawable/group_card_item_border"
@@ -17,8 +18,8 @@
         android:id="@+id/favicon"
         android:layout_width="16dp"
         android:layout_height="16dp"
-        android:src="@drawable/ic_globe_24dp"
-        android:importantForAccessibility="no"/>
+        android:importantForAccessibility="no"
+        app:srcCompat="@drawable/ic_globe_24dp"/>
 
     <TextView
         android:id="@+id/domain"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 4a98d9e1..7ab8c83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2165,14 +2165,15 @@
     }
 
     private void showFullHistoryOnNavigationSheet(Tab tab) {
-        // TODO(jinsukkim): Make NavigationSheet a per-activity object using RootUiCoordinator.
+        // Another instance of NavigationSheet(for gesture navigation) may be running.
         if (NavigationSheet.isInstanceShowing(getBottomSheetController())) {
             mNavigationSheet = null;
             return;
         }
         mNavigationSheet = NavigationSheet.create(
                 getWindow().getDecorView().findViewById(android.R.id.content), this,
-                this::getBottomSheetController, new TabbedSheetDelegate(tab));
+                this::getBottomSheetController);
+        mNavigationSheet.setDelegate(new TabbedSheetDelegate(tab));
         if (!mNavigationSheet.startAndExpand(/* forward=*/false, /* animate=*/true)) {
             mNavigationSheet = null;
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
index 97309eb7..fb77b68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -6,8 +6,6 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.view.View;
-import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 
@@ -18,9 +16,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
-import org.chromium.chrome.browser.gesturenav.NavigationGlowFactory;
 import org.chromium.chrome.browser.gesturenav.NavigationHandler;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -35,8 +30,8 @@
  * An overscroll handler implemented in terms a modified version of the Android
  * compat library's SwipeRefreshLayout effect.
  */
-public class SwipeRefreshHandler extends TabWebContentsUserData
-        implements OverscrollRefreshHandler, OnAttachStateChangeListener {
+public class SwipeRefreshHandler
+        extends TabWebContentsUserData implements OverscrollRefreshHandler {
     private static final Class<SwipeRefreshHandler> USER_DATA_KEY = SwipeRefreshHandler.class;
 
     // Synthetic delay between the {@link #didStopRefreshing()} signal and the
@@ -73,15 +68,11 @@
     // Accessibility utterance used to indicate refresh activation.
     private String mAccessibilityRefreshString;
 
-    // Overscroll Navigation delegate providing info/object constructor.
-    private HistoryNavigationDelegate mNavigationDelegate =
-            HistoryNavigationDelegateFactory.DEFAULT;
-
-    // Handles overscroll history navigation.
+    // Handles overscroll history navigation. Gesture events from native layer are forwarded
+    // to this object. Remains null while navigation feature is disabled due to feature flag,
+    // system settings (Q and forward), etc.
     private NavigationHandler mNavigationHandler;
 
-    private NavigationHandler.ActionDelegate mActionDelegate;
-
     public static SwipeRefreshHandler from(Tab tab) {
         SwipeRefreshHandler handler = get(tab);
         if (handler == null) {
@@ -117,7 +108,6 @@
             }
         };
         mTab.addObserver(mTabObserver);
-        mNavigationDelegate = HistoryNavigationDelegateFactory.create(tab);
     }
 
     private void initSwipeRefreshLayout(final Context context) {
@@ -156,9 +146,6 @@
     public void initWebContents(WebContents webContents) {
         webContents.setOverscrollRefreshHandler(this);
         mContainerView = mTab.getContentView();
-        mContainerView.addOnAttachStateChangeListener(this);
-        mNavigationDelegate.setWindowInsetsChangeObserver(
-                mContainerView, () -> updateNavigationHandler());
         setEnabled(true);
     }
 
@@ -166,26 +153,12 @@
     @Override
     public void cleanupWebContents(WebContents webContents) {
         if (mSwipeRefreshLayout != null) detachSwipeRefreshLayoutIfNecessary();
-        mContainerView.removeOnAttachStateChangeListener(this);
-        mNavigationDelegate.setWindowInsetsChangeObserver(mContainerView, null);
         mContainerView = null;
-        if (mNavigationHandler != null) {
-            mNavigationHandler.destroy();
-            mNavigationHandler = null;
-            mActionDelegate = null;
-        }
+        mNavigationHandler = null;
         setEnabled(false);
     }
 
     @Override
-    public void onViewAttachedToWindow(View v) {
-        updateNavigationHandler();
-    }
-
-    @Override
-    public void onViewDetachedFromWindow(View v) {}
-
-    @Override
     public void destroyInternal() {
         if (mSwipeRefreshLayout != null) {
             mSwipeRefreshLayout.setOnRefreshListener(null);
@@ -215,36 +188,22 @@
             return mSwipeRefreshLayout.start();
         } else if (type == OverscrollAction.HISTORY_NAVIGATION) {
             if (mNavigationHandler != null) {
-                boolean navigable = mActionDelegate.canNavigate(navigateForward);
-                boolean showGlow = navigateForward && !mTab.canGoForward();
                 mNavigationHandler.onDown(); // Simulates the initial onDown event.
-                if (navigable) {
-                    mNavigationHandler.showArrowWidget(navigateForward);
-                } else if (showGlow) {
-                    mNavigationHandler.showGlow(startX, startY);
-                }
-                return navigable || showGlow;
+                boolean navigable = mNavigationHandler.navigate(navigateForward, startX, startY);
+                boolean showGlow = navigateForward && !mTab.canGoForward();
+                return showGlow || navigable;
             }
         }
         mSwipeType = OverscrollAction.NONE;
         return false;
     }
 
-    private void updateNavigationHandler() {
-        if (mNavigationDelegate.isNavigationEnabled(mContainerView)) {
-            if (mNavigationHandler == null) {
-                mActionDelegate = mNavigationDelegate.createActionDelegate();
-                mNavigationHandler = new NavigationHandler(mContainerView, mTab.getContext(),
-                        mNavigationDelegate,
-                        NavigationGlowFactory.forRenderedPage(
-                                mContainerView, mTab.getWebContents()));
-            }
-        } else {
-            if (mNavigationHandler != null) {
-                mNavigationHandler.destroy();
-                mNavigationHandler = null;
-            }
-        }
+    /**
+     * Sets {@link NavigationHandler} object.
+     * @param layout {@link NavigationHandler} object.
+     */
+    public void setNavigationHandler(NavigationHandler navigationHandler) {
+        mNavigationHandler = navigationHandler;
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
index 24321e4..31ae7ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
 import org.chromium.chrome.browser.favicon.LargeIconBridge;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -358,14 +357,6 @@
     }
 
     /**
-     * Sets the delegate object needed for history navigation logic.
-     * @param delegate {@link HistoryNavigationDelegate} object.
-     */
-    public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
-        mSelectableListLayout.setHistoryNavigationDelegate(delegate);
-    }
-
-    /**
      * @return Current URL representing the UI state of bookmark manager. If no state has been shown
      *         yet in this session, on phone return last used state stored in preference; on tablet
      *         return the url previously set by {@link #updateForUrl(String)}.
@@ -630,4 +621,4 @@
     public static void preventLoadingForTesting(boolean preventLoading) {
         sPreventLoadingForTesting = preventLoading;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
index d97936a..24143cfb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
@@ -29,7 +29,6 @@
 
         mManager = new BookmarkManager(activity, false, activity.getSnackbarManager());
         mManager.setBasicNativePage(this);
-        mManager.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
         mTitle = host.getContext().getResources().getString(R.string.bookmarks);
 
         initWithView(mManager.getView());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index f7208296..fffb32b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -32,6 +32,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.ObserverList;
 import org.chromium.base.SysUtils;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.compat.ApiHelperForN;
@@ -87,6 +88,27 @@
                    CompositorViewResizer.Observer {
     private static final long SYSTEM_UI_VIEWPORT_UPDATE_DELAY_MS = 500;
 
+    /**
+     * Observer interface for any object that needs to process touch events.
+     */
+    public interface TouchEventObserver {
+        /**
+         * Determine if touch events should be forwarded to the observing object.
+         * Should return {@link true} if the object decided to consume the events.
+         * @param e {@link MotionEvent} object to process.
+         * @return {@code true} if the observer will process touch events going forward.
+         */
+        boolean shouldInterceptTouchEvent(MotionEvent e);
+
+        /**
+         * Handle touch events.
+         * @param e {@link MotionEvent} object to process.
+         */
+        void handleTouchEvent(MotionEvent e);
+    }
+
+    private ObserverList<TouchEventObserver> mTouchEventObservers = new ObserverList<>();
+
     private EventOffsetHandler mEventOffsetHandler;
     private boolean mIsKeyboardShowing;
 
@@ -558,10 +580,28 @@
         return mInvalidator;
     }
 
+    /**
+     * Add observer that needs to listen and process touch events.
+     * @param o {@link TouchEventObserver} object.
+     */
+    public void addTouchEventObserver(TouchEventObserver o) {
+        mTouchEventObservers.addObserver(o);
+    }
+
+    /**
+     * Remove observer that needs to listen and process touch events.
+     * @param o {@link TouchEventObserver} object.
+     */
+    public void removeTouchEventObserver(TouchEventObserver o) {
+        mTouchEventObservers.removeObserver(o);
+    }
+
     @Override
     public boolean onInterceptTouchEvent(MotionEvent e) {
         super.onInterceptTouchEvent(e);
-
+        for (TouchEventObserver o : mTouchEventObservers) {
+            if (o.shouldInterceptTouchEvent(e)) return true;
+        }
         if (mLayoutManager == null) return false;
 
         mEventOffsetHandler.onInterceptTouchEvent(e);
@@ -605,6 +645,7 @@
     @Override
     public boolean dispatchTouchEvent(MotionEvent e) {
         updateLastActiveTouchEvent(e);
+        for (TouchEventObserver o : mTouchEventObservers) o.handleTouchEvent(e);
         return super.dispatchTouchEvent(e);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
index 465dba8..ee5860d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
@@ -47,7 +47,6 @@
                 activity.getModalDialogManager());
 
         mDownloadCoordinator.addObserver(this);
-        mDownloadCoordinator.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
         mTitle = activity.getString(R.string.menu_downloads);
 
         // #destroy() unregisters the ActivityStateListener to avoid checking for externally removed
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java
index 3f3f6ad..48471c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinator.java
@@ -6,8 +6,6 @@
 
 import android.view.View;
 
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-
 /**
  * A coordinator that represents the main download manager UI page. This visually shows a list of
  * downloaded items and allows the user to interact with those items.
@@ -42,10 +40,4 @@
 
     /** Stops notifying {@code observer} of url state changes. */
     void removeObserver(Observer observer);
-
-    /**
-     * Sets the {@link HistoryNavigationDelegate} object that takes care of history navigation.
-     * @param delegate The delegate instance the history navigation logic needs.
-     */
-    void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
index 2ec4e08..215aec0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -7,6 +7,7 @@
 import android.app.Activity;
 import android.view.Gravity;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -20,8 +21,6 @@
 import org.chromium.chrome.browser.download.home.snackbars.DeleteUndoCoordinator;
 import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.download.DownloadSettings;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
@@ -44,11 +43,10 @@
 
     private final ToolbarCoordinator mToolbarCoordinator;
     private final SelectionDelegate<ListItem> mSelectionDelegate;
-    private SelectionDelegate.SelectionObserver<ListItem> mNavigationCanceller;
 
     private final Activity mActivity;
 
-    private HistoryNavigationLayout mMainView;
+    private ViewGroup mMainView;
 
     private boolean mMuteFilterChanges;
 
@@ -75,7 +73,7 @@
      * TODO(crbug.com/880468) : Investigate if it is better to do in XML.
      */
     private void initializeView() {
-        mMainView = new HistoryNavigationLayout(mActivity);
+        mMainView = new FrameLayout(mActivity);
         mMainView.setBackgroundColor(ApiCompatibilityUtils.getColor(
                 mActivity.getResources(), R.color.modern_primary_color));
 
@@ -85,10 +83,6 @@
                 mActivity.getResources().getDimensionPixelOffset(R.dimen.toolbar_height_no_shadow),
                 0, 0);
         mMainView.addView(mListCoordinator.getView(), listParams);
-        mNavigationCanceller = (selectedItems) -> {
-            if (!selectedItems.isEmpty()) mMainView.release();
-        };
-        mSelectionDelegate.addObserver(mNavigationCanceller);
 
         FrameLayout.LayoutParams toolbarParams = new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
@@ -118,7 +112,6 @@
         mDeleteCoordinator.destroy();
         mListCoordinator.destroy();
         mToolbarCoordinator.destroy();
-        mSelectionDelegate.removeObserver(mNavigationCanceller);
     }
 
     @Override
@@ -150,11 +143,6 @@
         mObservers.removeObserver(observer);
     }
 
-    @Override
-    public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
-        mMainView.setNavigationDelegate(delegate);
-    }
-
     // ToolbarActionDelegate implementation.
     @Override
     public void close() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/CardPaginator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/CardPaginator.java
index 388e0357..f5f0169 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/CardPaginator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/mutator/CardPaginator.java
@@ -24,9 +24,7 @@
      * @param dateAndDomain The date and domain for the items in the card.
      */
     public void loadMore(Pair<Date, String> dateAndDomain) {
-        assert mPageCountForCard.containsKey(dateAndDomain);
-        int currentPages = mPageCountForCard.get(dateAndDomain);
-        mPageCountForCard.put(dateAndDomain, currentPages + 1);
+        mPageCountForCard.put(dateAndDomain, getCurrentPageCount(dateAndDomain) + 1);
     }
 
     /**
@@ -44,9 +42,7 @@
      * @return The number of items being shown on the card.
      */
     public int getItemCountForCard(Pair<Date, String> dateAndDomain) {
-        return mPageCountForCard.containsKey(dateAndDomain)
-                ? mPageCountForCard.get(dateAndDomain) * ITEM_COUNT_PER_PAGE
-                : 0;
+        return getCurrentPageCount(dateAndDomain) * ITEM_COUNT_PER_PAGE;
     }
 
     /**
@@ -63,4 +59,10 @@
     public void reset() {
         mPageCountForCard.clear();
     }
+
+    /** @return The number of pages currently being displayed. Default is 1.*/
+    private int getCurrentPageCount(Pair<Date, String> dateAndDomain) {
+        return mPageCountForCard.containsKey(dateAndDomain) ? mPageCountForCard.get(dateAndDomain)
+                                                            : 1;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
index 65cf49a..fd840ae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
@@ -11,6 +11,7 @@
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Base64;
+import android.view.ViewGroup;
 
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
@@ -22,7 +23,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.favicon.RoundedIconGenerator;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.native_page.NativePageHost;
@@ -96,7 +96,7 @@
     private Tab mTab;
     private TabObserver mTabObserver;
     private Profile mProfile;
-    private HistoryNavigationLayout mView;
+    private ViewGroup mView;
     private RecyclerView mRecyclerView;
     private StableScrollLayoutManager mLayoutManager;
     private String mTitle;
@@ -177,7 +177,7 @@
         mTab = tab;
 
         mTitle = activity.getString(R.string.explore_sites_title);
-        mView = (HistoryNavigationLayout) activity.getLayoutInflater().inflate(
+        mView = (ViewGroup) activity.getLayoutInflater().inflate(
                 R.layout.explore_sites_page_layout, null);
         mProfile = ((TabImpl) mTab).getProfile();
 
@@ -246,7 +246,6 @@
         CategoryCardAdapter adapterDelegate = new CategoryCardAdapter(
                 mModel, mLayoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile);
 
-        mView.setNavigationDelegate(host.createHistoryNavigationDelegate());
         mRecyclerView = mView.findViewById(R.id.explore_sites_category_recycler);
 
         CategoryCardViewHolderFactory factory = createCategoryCardViewHolderFactory();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java
index f394d00..7155059 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/AndroidUiNavigationGlow.java
@@ -20,7 +20,7 @@
      * Amount of time we wait before {@link GlowView} gets detached from parent view
      * after the glow effect is completed.
      */
-    private final static int REMOVE_RUNNABLE_DELAY_MS = 500;
+    private static final int REMOVE_RUNNABLE_DELAY_MS = 500;
 
     private final Runnable mRemoveGlowViewRunnable;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java
new file mode 100644
index 0000000..cc8b622
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationCoordinator.java
@@ -0,0 +1,191 @@
+// 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.gesturenav;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.View;
+
+import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.InsetObserverView;
+import org.chromium.chrome.browser.SwipeRefreshHandler;
+import org.chromium.chrome.browser.compositor.CompositorViewHolder;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabImpl;
+import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
+import org.chromium.content_public.browser.WebContents;
+
+/**
+ * Coordinator object for gesture navigation.
+ */
+public class HistoryNavigationCoordinator
+        implements InsetObserverView.WindowInsetObserver, Destroyable {
+    private CompositorViewHolder mCompositorViewHolder;
+    private HistoryNavigationLayout mNavigationLayout;
+    private InsetObserverView mInsetObserverView;
+    private ActivityTabTabObserver mActivityTabObserver;
+    private ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
+    private Tab mTab;
+
+    /**
+     * Initializes the navigation layout and internal objects.
+     * @param compositorViewHolder Parent view for navigation layout.
+     * @param tabProvider Activity tab provider.
+     * @param insetObserverView View that provides information about the inset and inset
+     *        capabilities of the device.
+     */
+    public void init(ActivityLifecycleDispatcher lifecycleDispatcher,
+            CompositorViewHolder compositorViewHolder, ActivityTabProvider tabProvider,
+            InsetObserverView insetObserverView) {
+        mNavigationLayout = new HistoryNavigationLayout(compositorViewHolder.getContext());
+        mCompositorViewHolder = compositorViewHolder;
+        mActivityLifecycleDispatcher = lifecycleDispatcher;
+        lifecycleDispatcher.register(this);
+
+        compositorViewHolder.addView(mNavigationLayout);
+        compositorViewHolder.addTouchEventObserver(mNavigationLayout);
+        mActivityTabObserver = new ActivityTabProvider.ActivityTabTabObserver(tabProvider) {
+            @Override
+            protected void onObservingDifferentTab(Tab tab) {
+                if (mTab == tab) return;
+                onTabSwitched(tab);
+            }
+
+            @Override
+            public void onContentChanged(Tab tab) {
+                initNavigationHandler(
+                        tab, createDelegate(tab), tab.getWebContents(), tab.isNativePage());
+            }
+        };
+
+        // We wouldn't hear about the first tab until the content changed or we switched tabs
+        // if tabProvider.get() != null. Do here what we do when tab switching happens.
+        if (tabProvider.get() != null) onTabSwitched(tabProvider.get());
+
+        mNavigationLayout.setVisibility(View.INVISIBLE);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+            mInsetObserverView = insetObserverView;
+            insetObserverView.addObserver(this);
+        }
+    }
+
+    /**
+     * Creates {@link HistoryNavigationDelegate} for native/rendered pages on Tab.
+     */
+    private static HistoryNavigationDelegate createDelegate(Tab tab) {
+        if (!isFeatureFlagEnabled() || ((TabImpl) tab).getActivity() == null) {
+            return HistoryNavigationDelegate.DEFAULT;
+        }
+
+        return new HistoryNavigationDelegate() {
+            // TODO(jinsukkim): Avoid getting activity from tab.
+            private final Supplier<BottomSheetController> mController = () -> {
+                ChromeActivity activity = ((TabImpl) tab).getActivity();
+                return activity == null || activity.isActivityFinishingOrDestroyed()
+                        ? null
+                        : activity.getBottomSheetController();
+            };
+
+            @Override
+            public NavigationHandler.ActionDelegate createActionDelegate() {
+                return new TabbedActionDelegate(tab);
+            }
+
+            @Override
+            public NavigationSheet.Delegate createSheetDelegate() {
+                return new TabbedSheetDelegate(tab);
+            }
+
+            @Override
+            public Supplier<BottomSheetController> getBottomSheetController() {
+                return mController;
+            }
+        };
+    }
+
+    private static boolean isFeatureFlagEnabled() {
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.OVERSCROLL_HISTORY_NAVIGATION);
+    }
+
+    @Override
+    public void onInsetChanged(int left, int top, int right, int bottom) {
+        // Resets navigation handler when the feature becomes disabled.
+        if (!isNavigationEnabled(mCompositorViewHolder)) {
+            initNavigationHandler(mTab, HistoryNavigationDelegate.DEFAULT, null, false);
+        }
+    }
+
+    private void onTabSwitched(Tab tab) {
+        WebContents webContents = tab != null ? tab.getWebContents() : null;
+        HistoryNavigationDelegate delegate =
+                webContents != null && isNavigationEnabled(mCompositorViewHolder)
+                ? createDelegate(tab)
+                : HistoryNavigationDelegate.DEFAULT;
+
+        // Also resets NavigationHandler when there's no tab (going into TabSwitcher).
+        if (tab == null || webContents != null) {
+            initNavigationHandler(
+                    tab, delegate, webContents, tab != null ? tab.isNativePage() : false);
+        }
+    }
+
+    /**
+     * @param view {@link View} object to obtain the navigation setting from.
+     * @return {@code true} if overscroll navigation is allowed to run on this page.
+     */
+    private static boolean isNavigationEnabled(View view) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true;
+        Insets insets = view.getRootWindowInsets().getSystemGestureInsets();
+        return insets.left == 0 && insets.right == 0;
+    }
+
+    private void initNavigationHandler(Tab tab, HistoryNavigationDelegate delegate,
+            WebContents webContents, boolean isNativePage) {
+        assert mNavigationLayout != null;
+        mNavigationLayout.initNavigationHandler(delegate, webContents, isNativePage);
+        if (mTab != tab) {
+            if (mTab != null) SwipeRefreshHandler.from(mTab).setNavigationHandler(null);
+            if (tab != null) {
+                SwipeRefreshHandler.from(tab).setNavigationHandler(
+                        mNavigationLayout.getNavigationHandler());
+            }
+            mTab = tab;
+        }
+    }
+
+    @Override
+    public void onSafeAreaChanged(Rect area) {}
+
+    @Override
+    public void destroy() {
+        if (mActivityTabObserver != null) {
+            mActivityTabObserver.destroy();
+            mActivityTabObserver = null;
+        }
+        if (mInsetObserverView != null) {
+            mInsetObserverView.removeObserver(this);
+            mInsetObserverView = null;
+        }
+        if (mCompositorViewHolder != null && mNavigationLayout != null) {
+            mCompositorViewHolder.removeTouchEventObserver(mNavigationLayout);
+            mCompositorViewHolder = null;
+        }
+        if (mNavigationLayout != null) {
+            mNavigationLayout.destroy();
+            mNavigationLayout = null;
+        }
+        if (mActivityLifecycleDispatcher != null) {
+            mActivityLifecycleDispatcher.unregister(this);
+            mActivityLifecycleDispatcher = null;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java
index e82d1c2..f6e3370 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegate.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.gesturenav;
 
-import android.view.View;
-
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
 
@@ -24,21 +22,28 @@
     NavigationSheet.Delegate createSheetDelegate();
 
     /**
-     * @param view {@link View} object to obtain the navigation setting from.
-     * @return {@code true} if overscroll navigation is allowed to run on this page.
-     */
-    boolean isNavigationEnabled(View view);
-
-    /**
      * @return {@link BottomSheetController} object.
      */
     Supplier<BottomSheetController> getBottomSheetController();
 
     /**
-     * Observe window insets change to update navigation configutation dynamically.
-     * @param view {@link View} to observe the insets change on.
-     * @param runnable {@link Runnable} to execute when insets change is detected.
-     *        Pass {@code null} to reset the observation.
+     * Default {@link HistoryNavigationDelegate} that does not support navigation.
      */
-    void setWindowInsetsChangeObserver(View view, Runnable runnable);
+    public static final HistoryNavigationDelegate DEFAULT = new HistoryNavigationDelegate() {
+        @Override
+        public NavigationHandler.ActionDelegate createActionDelegate() {
+            return null;
+        }
+
+        @Override
+        public NavigationSheet.Delegate createSheetDelegate() {
+            return null;
+        }
+
+        @Override
+        public Supplier<BottomSheetController> getBottomSheetController() {
+            assert false : "Should never be called";
+            return null;
+        }
+    };
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java
deleted file mode 100644
index 4a46aaa..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationDelegateFactory.java
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.gesturenav;
-
-import android.graphics.Insets;
-import android.os.Build;
-import android.view.View;
-import android.view.WindowInsets;
-
-import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
-
-/**
- * Factory class for {@link HistoryNavigationDelegate}.
- */
-public class HistoryNavigationDelegateFactory {
-    /**
-     * Default {@link HistoryNavigationDelegate} that does not support navigation. Mainly
-     * used for SnackbarActivity-based UI on the phone to disable the feature.
-     */
-    public static final HistoryNavigationDelegate DEFAULT = new HistoryNavigationDelegate() {
-        @Override
-        public NavigationHandler.ActionDelegate createActionDelegate() {
-            return null;
-        }
-
-        @Override
-        public NavigationSheet.Delegate createSheetDelegate() {
-            return null;
-        }
-
-        @Override
-        public Supplier<BottomSheetController> getBottomSheetController() {
-            assert false : "Should never be called";
-            return null;
-        }
-
-        @Override
-        public boolean isNavigationEnabled(View view) {
-            return false;
-        }
-
-        @Override
-        public void setWindowInsetsChangeObserver(View view, Runnable runnable) {}
-    };
-
-    private HistoryNavigationDelegateFactory() {}
-
-    /**
-     * Creates {@link HistoryNavigationDelegate} for native/rendered pages on Tab.
-     */
-    public static HistoryNavigationDelegate create(Tab tab) {
-        if (!isFeatureFlagEnabled() || ((TabImpl) tab).getActivity() == null) return DEFAULT;
-
-        return new HistoryNavigationDelegate() {
-            // TODO(jinsukkim): Avoid getting activity from tab.
-            private final Supplier<BottomSheetController> mController = () -> {
-                ChromeActivity activity = ((TabImpl) tab).getActivity();
-                return activity == null || activity.isActivityFinishingOrDestroyed()
-                        ? null
-                        : activity.getBottomSheetController();
-            };
-            private Runnable mInsetsChangeRunnable;
-
-            @Override
-            public NavigationHandler.ActionDelegate createActionDelegate() {
-                return new TabbedActionDelegate(tab);
-            }
-
-            @Override
-            public NavigationSheet.Delegate createSheetDelegate() {
-                return new TabbedSheetDelegate(tab);
-            }
-
-            @Override
-            public Supplier<BottomSheetController> getBottomSheetController() {
-                return mController;
-            }
-
-            @Override
-            public boolean isNavigationEnabled(View view) {
-                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true;
-                Insets insets = view.getRootWindowInsets().getSystemGestureInsets();
-                return insets.left == 0 && insets.right == 0;
-            }
-
-            @Override
-            public void setWindowInsetsChangeObserver(View view, Runnable runnable) {
-                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return;
-                mInsetsChangeRunnable = runnable;
-                view.setOnApplyWindowInsetsListener(
-                        runnable != null ? this::onApplyWindowInsets : null);
-            }
-
-            private WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
-                assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
-                mInsetsChangeRunnable.run();
-                return insets;
-            }
-        };
-    }
-
-    private static boolean isFeatureFlagEnabled() {
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.OVERSCROLL_HISTORY_NAVIGATION);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
index d95b3195..906f9e01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
@@ -5,88 +5,123 @@
 package org.chromium.chrome.browser.gesturenav;
 
 import android.content.Context;
-import android.util.AttributeSet;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import org.chromium.chrome.browser.compositor.CompositorViewHolder.TouchEventObserver;
+import org.chromium.content_public.browser.WebContents;
+
 /**
- * FrameLayout that supports side-wise slide gesture for history navigation. Inheriting
- * class may need to override {@link #wasLastSideSwipeGestureConsumed()} if
- * {@link #onTouchEvent} cannot be relied upon to know whether the side-swipe related
- * event was handled. Namely {@link android.support.v7.widget.RecyclerView}) always
- * claims to handle touch events.
- * TODO(jinsukkim): Write a test verifying UI logic.
+ * FrameLayout that supports side-wise slide gesture for history navigation.
  */
-public class HistoryNavigationLayout extends FrameLayout {
+public class HistoryNavigationLayout
+        extends FrameLayout implements TouchEventObserver, ViewGroup.OnHierarchyChangeListener {
     private GestureDetector mDetector;
     private NavigationHandler mNavigationHandler;
-    private HistoryNavigationDelegate mDelegate = HistoryNavigationDelegateFactory.DEFAULT;
+    private HistoryNavigationDelegate mDelegate;
+    private WebContents mWebContents;
+    private boolean mIsNativePage;
+    private NavigationGlow mJavaGlowEffect;
+    private NavigationGlow mCompositorGlowEffect;
 
     public HistoryNavigationLayout(Context context) {
-        this(context, null);
-    }
-
-    public HistoryNavigationLayout(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * Initializes navigation logic and internal objects if navigation is enabled.
-     * @param delegate {@link HistoryNavigationDelegate} providing info and a factory method.
-     */
-    public void setNavigationDelegate(HistoryNavigationDelegate delegate) {
-        mDelegate = delegate;
-
-        // Navigation is potentially enabled only when the delegate is set.
-        delegate.setWindowInsetsChangeObserver(this, () -> updateNavigationHandler());
+        super(context);
+        setOnHierarchyChangeListener(this);
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        updateNavigationHandler();
+    public void onChildViewAdded(View parent, View child) {
+        if (getVisibility() != View.VISIBLE) setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    public void onChildViewRemoved(View parent, View child) {
+        // TODO(jinsukkim): Replace INVISIBLE with GONE to avoid performing layout/measurements.
+        if (getChildCount() == 0) setVisibility(View.INVISIBLE);
     }
 
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        // TODO(jinsukkim): There are callsites enabling HistoryNavigationLayout but
-        //         failing to call |setNavigationDelegate| (or |setTab| before renaming).
-        //         Find when it can happen.
         if (mNavigationHandler != null) mNavigationHandler.reset();
     }
 
     @Override
-    public boolean dispatchTouchEvent(MotionEvent e) {
-        if (mNavigationHandler != null) {
-            mDetector.onTouchEvent(e);
-            mNavigationHandler.onTouchEvent(e.getAction());
-        }
-        return super.dispatchTouchEvent(e);
-    }
-
-    private void updateNavigationHandler() {
-        if (mDelegate.isNavigationEnabled(this)) {
-            if (mNavigationHandler == null) {
-                mDetector = new GestureDetector(getContext(), new SideNavGestureListener());
-                mNavigationHandler = new NavigationHandler(
-                        this, getContext(), mDelegate, NavigationGlowFactory.forJavaLayer(this));
-            }
-        } else {
-            mDetector = null;
-            if (mNavigationHandler != null) {
-                mNavigationHandler.destroy();
-                mNavigationHandler = null;
-            }
-        }
+    public boolean shouldInterceptTouchEvent(MotionEvent e) {
+        // Forward gesture events only for native pages. Rendered pages receive events
+        // from SwipeRefreshHandler.
+        if (!mIsNativePage) return false;
+        return mNavigationHandler != null && mNavigationHandler.isActive();
     }
 
     @Override
-    public boolean onInterceptTouchEvent(MotionEvent e) {
-        // Do not propagate touch events down to children if navigation UI was triggered.
-        if (mDetector != null && mNavigationHandler.isActive()) return true;
-        return super.onInterceptTouchEvent(e);
+    public void handleTouchEvent(MotionEvent e) {
+        if (mNavigationHandler != null && mIsNativePage) {
+            mDetector.onTouchEvent(e);
+            mNavigationHandler.onTouchEvent(e.getAction());
+        }
+    }
+
+    /**
+     * Initialize {@link NavigationHandler} object.
+     * @param delegate {@link HistoryNavigationDelegate} providing info and a factory method.
+     * @param webContents A new WebContents object.
+     * @param isNativePage {@code true} if the content is a native page.
+     */
+    public void initNavigationHandler(
+            HistoryNavigationDelegate delegate, WebContents webContents, boolean isNativePage) {
+        if (mNavigationHandler == null) {
+            mDetector = new GestureDetector(getContext(), new SideNavGestureListener());
+            mNavigationHandler = new NavigationHandler(this, getContext(), this::getGlowEffect);
+        }
+        if (mDelegate != delegate) {
+            mNavigationHandler.setDelegate(delegate);
+            mDelegate = delegate;
+        }
+
+        if (isNativePage == mIsNativePage && mWebContents == webContents) return;
+        if (mWebContents != webContents) resetCompositorGlow();
+        mWebContents = webContents;
+        mIsNativePage = isNativePage;
+    }
+
+    /**
+     * Create {@link NavigationGlow} object lazily.
+     */
+    private NavigationGlow getGlowEffect() {
+        if (mIsNativePage) {
+            if (mJavaGlowEffect == null) mJavaGlowEffect = new AndroidUiNavigationGlow(this);
+            return mJavaGlowEffect;
+        } else {
+            if (mCompositorGlowEffect == null) {
+                mCompositorGlowEffect = new CompositorNavigationGlow(this, mWebContents);
+            }
+            return mCompositorGlowEffect;
+        }
+    }
+
+    /**
+     * Reset CompositorGlowEffect for new a WebContents. Destroy the current one
+     * (for its native object) so it can be created again lazily.
+     */
+    private void resetCompositorGlow() {
+        if (mCompositorGlowEffect != null) {
+            mCompositorGlowEffect.destroy();
+            mCompositorGlowEffect = null;
+        }
+    }
+
+    /** @return Current {@link HistoryNavigationDelegate} object. */
+    public HistoryNavigationDelegate getDelegate() {
+        return mDelegate;
+    }
+
+    /** @return Current {@link NavigationHandler} object. */
+    public NavigationHandler getNavigationHandler() {
+        return mNavigationHandler;
     }
 
     private class SideNavGestureListener extends GestureDetector.SimpleOnGestureListener {
@@ -97,8 +132,7 @@
 
         @Override
         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-            // |onScroll| needs handling only after the state moves away from |NONE|. This helps
-            // invoke |wasLastSideSwipeGestureConsumed| which may be expensive less often.
+            // |onScroll| needs handling only after the state moved away from |NONE|.
             if (mNavigationHandler.isStopped()) return true;
 
             return mNavigationHandler.onScroll(
@@ -112,4 +146,16 @@
     public void release() {
         if (mNavigationHandler != null) mNavigationHandler.release(false);
     }
+
+    /**
+     * Performs cleanup upon destruction.
+     */
+    void destroy() {
+        resetCompositorGlow();
+        mDelegate = HistoryNavigationDelegate.DEFAULT;
+        if (mNavigationHandler != null) {
+            mNavigationHandler.setDelegate(mDelegate);
+            mNavigationHandler = null;
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java
deleted file mode 100644
index 08f9c85b..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationGlowFactory.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.gesturenav;
-
-import android.view.ViewGroup;
-
-import org.chromium.base.supplier.Supplier;
-import org.chromium.content_public.browser.WebContents;
-
-/**
- * Factory class that provides {@link NavigationGlow} according to the actual surface
- * the glow effect is rendered on.
- */
-public class NavigationGlowFactory {
-    /**
-     * @pararm parentView Parent view where the glow view gets attached to.
-     * @pararm webContents WebContents whose native view's cc layer will be used
-     *        for rendering glow effect.
-     * @return Supplier for {@link NavigationGlow} object for rendered pages.
-     */
-    public static Supplier<NavigationGlow> forRenderedPage(
-            ViewGroup parentView, WebContents webContents) {
-        return () -> new CompositorNavigationGlow(parentView, webContents);
-    }
-
-    /**
-     * @pararm parentView Parent view where the glow view gets attached to.
-     * @return Supplier for {@link NavigationGlow} object for pages where glow effect can be
-     *         rendered on the parent android view.
-     */
-    public static Supplier<NavigationGlow> forJavaLayer(ViewGroup parentView) {
-        return () -> new AndroidUiNavigationGlow(parentView);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
index b25b24ba..cdc58a95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationHandler.java
@@ -46,12 +46,11 @@
 
     private final ViewGroup mParentView;
     private final Context mContext;
-    private final Supplier<NavigationGlow> mGlowEffectSupplier;
 
-    private final HistoryNavigationDelegate mDelegate;
-    private final ActionDelegate mActionDelegate;
+    private HistoryNavigationDelegate mDelegate;
+    private ActionDelegate mActionDelegate;
 
-    private NavigationGlow mGlowEffect;
+    private Supplier<NavigationGlow> mGlowEffectSupplier;
 
     private @GestureState int mState = GestureState.NONE;
 
@@ -95,13 +94,11 @@
         boolean willBackExitApp();
     }
 
-    public NavigationHandler(ViewGroup parentView, Context context,
-            HistoryNavigationDelegate delegate, Supplier<NavigationGlow> glowEffectSupplier) {
+    public NavigationHandler(
+            ViewGroup parentView, Context context, Supplier<NavigationGlow> glowEffect) {
         mParentView = parentView;
         mContext = context;
-        mDelegate = delegate;
-        mActionDelegate = delegate.createActionDelegate();
-        mGlowEffectSupplier = glowEffectSupplier;
+        mGlowEffectSupplier = glowEffect;
         mEdgeWidthPx = EDGE_WIDTH_DP * parentView.getResources().getDisplayMetrics().density;
     }
 
@@ -114,7 +111,6 @@
             cancelStopNavigatingRunnable();
             mSideSlideLayout.post(getStopNavigatingRunnable());
         });
-
         mSideSlideLayout.setOnResetListener(() -> {
             if (mDetachLayoutRunnable != null) return;
             mDetachLayoutRunnable = () -> {
@@ -124,10 +120,21 @@
             mSideSlideLayout.post(mDetachLayoutRunnable);
         });
 
-        mNavigationSheet = NavigationSheet.isEnabled()
-                ? NavigationSheet.create(mParentView, mContext,
-                        mDelegate.getBottomSheetController(), mDelegate.createSheetDelegate())
-                : NavigationSheet.DUMMY;
+        mNavigationSheet = NavigationSheet.isEnabled() ? NavigationSheet.create(
+                                   mParentView, mContext, mDelegate.getBottomSheetController())
+                                                       : NavigationSheet.DUMMY;
+        mNavigationSheet.setDelegate(mDelegate.createSheetDelegate());
+    }
+
+    /**
+     * Sets {@link HistoryNavigationDelegate} object.
+     * Also creates new delegates, for horizontal gesture and bottom sheet processing.
+     * @param {@link HistoryNavigationDelegate} object.
+     */
+    void setDelegate(HistoryNavigationDelegate delegate) {
+        mDelegate = delegate;
+        mActionDelegate = delegate.createActionDelegate();
+        if (mNavigationSheet != null) mNavigationSheet.setDelegate(delegate.createSheetDelegate());
     }
 
     /**
@@ -138,8 +145,8 @@
             if (mState == GestureState.DRAGGED && mSideSlideLayout != null) {
                 mSideSlideLayout.release(mNavigationSheet.isHidden());
                 mNavigationSheet.release();
-            } else if (mState == GestureState.GLOW && mGlowEffect != null) {
-                mGlowEffect.release();
+            } else if (mState == GestureState.GLOW && mGlowEffectSupplier != null) {
+                mGlowEffectSupplier.get().release();
             }
         }
     }
@@ -167,15 +174,7 @@
 
         if (mState == GestureState.STARTED) {
             if (shouldTriggerUi(startX, distanceX, distanceY)) {
-                boolean forward = distanceX > 0;
-                if (mActionDelegate.canNavigate(forward)) {
-                    showArrowWidget(forward);
-                } else {
-                    // |forward| should be true if we get here, since navigating back
-                    // is always possible.
-                    assert forward;
-                    showGlow(endX, endY);
-                }
+                navigate(distanceX > 0, endX, endY);
             }
             if (!isActive()) mState = GestureState.NONE;
         }
@@ -189,10 +188,28 @@
     }
 
     /**
+     * Shows UI in response to gesture events.
+     * @param forward Direction of the swipe gesture. {@code true} if forward; else back.
+     * @param x The X position of the event.
+     * @param y The Y position of the event.
+     * @return {@code true} if the navigation can be triggered.
+     */
+    public boolean navigate(boolean forward, float x, float y) {
+        assert mActionDelegate != null;
+        boolean navigable = mActionDelegate.canNavigate(forward);
+        if (navigable) {
+            showArrowWidget(forward);
+        } else {
+            showGlow(x, y);
+        }
+        return navigable;
+    }
+
+    /**
      * Start showing arrow widget for navigation back/forward.
      * @param forward {@code true} if navigating forward.
      */
-    public void showArrowWidget(boolean forward) {
+    private void showArrowWidget(boolean forward) {
         if (mState != GestureState.STARTED) reset();
         if (mSideSlideLayout == null) createLayout();
         mSideSlideLayout.setEnabled(true);
@@ -211,10 +228,9 @@
      * @param startX X coordinate of the touch event at the beginning.
      * @param startY Y coordinate of the touch event at the beginning.
      */
-    public void showGlow(float startX, float startY) {
+    private void showGlow(float startX, float startY) {
         if (mState != GestureState.STARTED) reset();
-        if (mGlowEffect == null) mGlowEffect = mGlowEffectSupplier.get();
-        mGlowEffect.prepare(startX, startY);
+        mGlowEffectSupplier.get().prepare(startX, startY);
         mState = GestureState.GLOW;
     }
 
@@ -252,8 +268,8 @@
                 mSideSlideLayout.hideArrow();
                 mState = GestureState.NONE;
             }
-        } else if (mState == GestureState.GLOW && mGlowEffect != null) {
-            mGlowEffect.onScroll(-delta);
+        } else if (mState == GestureState.GLOW) {
+            mGlowEffectSupplier.get().onScroll(-delta);
         }
     }
 
@@ -283,8 +299,8 @@
             cancelStopNavigatingRunnable();
             mSideSlideLayout.release(allowNav && mNavigationSheet.isHidden());
             mNavigationSheet.release();
-        } else if (mState == GestureState.GLOW && mGlowEffect != null) {
-            mGlowEffect.release();
+        } else if (mState == GestureState.GLOW) {
+            mGlowEffectSupplier.get().release();
         }
     }
 
@@ -295,19 +311,12 @@
         if (mState == GestureState.DRAGGED && mSideSlideLayout != null) {
             cancelStopNavigatingRunnable();
             mSideSlideLayout.reset();
-        } else if (mState == GestureState.GLOW && mGlowEffect != null) {
-            mGlowEffect.reset();
+        } else if (mState == GestureState.GLOW) {
+            mGlowEffectSupplier.get().reset();
         }
         mState = GestureState.NONE;
     }
 
-    /**
-     * Performs cleanup upon destruction.
-     */
-    public void destroy() {
-        if (mGlowEffect != null) mGlowEffect.destroy();
-    }
-
     private void cancelStopNavigatingRunnable() {
         if (mStopNavigatingRunnable != null) {
             mSideSlideLayout.removeCallbacks(mStopNavigatingRunnable);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java
index b4c25a5f..e664413 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheet.java
@@ -40,13 +40,11 @@
      * @param rootView Root view whose dimension is used for the sheet.
      * @param context {@link Context} used to retrieve resources.
      * @param bottomSheetController {@link BottomSheetController} object.
-     * @param delegate Delegate used by navigation sheet to perform actions.
      * @return NavigationSheet object.
      */
-    public static NavigationSheet create(View rootView, Context context,
-            Supplier<BottomSheetController> bottomSheetController,
-            NavigationSheet.Delegate delegate) {
-        return new NavigationSheetCoordinator(rootView, context, bottomSheetController, delegate);
+    public static NavigationSheet create(
+            View rootView, Context context, Supplier<BottomSheetController> bottomSheetController) {
+        return new NavigationSheetCoordinator(rootView, context, bottomSheetController);
     }
 
     /**
@@ -73,6 +71,9 @@
      */
     static final NavigationSheet DUMMY = new NavigationSheet() {
         @Override
+        public void setDelegate(Delegate delegate) {}
+
+        @Override
         public void start(boolean forward, boolean showCloseIndicator) {}
 
         @Override
@@ -101,6 +102,12 @@
     };
 
     /**
+     * Set a new {@link Delegate} object whenever the dependency is updated.
+     * @param delegate Delegate used by navigation sheet to perform actions.
+     */
+    void setDelegate(Delegate delegate);
+
+    /**
      * Get the navigation sheet ready as the gesture starts.
      * @param forward {@code true} if we're navigating forward.
      * @param showCloseIndicator {@code true} if we should show 'close chrome' indicator
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
index 606cf80..a875e200 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/NavigationSheetCoordinator.java
@@ -60,7 +60,6 @@
     private final View mToolbarView;
     private final LayoutInflater mLayoutInflater;
     private final Supplier<BottomSheetController> mBottomSheetController;
-    private final NavigationSheet.Delegate mDelegate;
     private final NavigationSheetMediator mMediator;
     private final BottomSheetObserver mSheetObserver = new EmptyBottomSheetObserver() {
         @Override
@@ -80,6 +79,8 @@
     private final int mContentPadding;
     private final View mParentView;
 
+    private NavigationSheet.Delegate mDelegate;
+
     private static class NavigationItemViewBinder {
         public static void bind(PropertyModel model, View view, PropertyKey propertyKey) {
             if (ItemProperties.ICON == propertyKey) {
@@ -113,11 +114,10 @@
     /**
      * Construct a new NavigationSheet.
      */
-    NavigationSheetCoordinator(View parent, Context context,
-            Supplier<BottomSheetController> bottomSheetController, Delegate delegate) {
+    NavigationSheetCoordinator(
+            View parent, Context context, Supplier<BottomSheetController> bottomSheetController) {
         mParentView = parent;
         mBottomSheetController = bottomSheetController;
-        mDelegate = delegate;
         mLayoutInflater = LayoutInflater.from(context);
         mToolbarView = mLayoutInflater.inflate(R.layout.navigation_sheet_toolbar, null);
         mMediator = new NavigationSheetMediator(context, mModelList, (position, index) -> {
@@ -184,6 +184,11 @@
     // NavigationSheet
 
     @Override
+    public void setDelegate(NavigationSheet.Delegate delegate) {
+        mDelegate = delegate;
+    }
+
+    @Override
     public void start(boolean forward, boolean showCloseIndicator) {
         if (mBottomSheetController.get() == null) return;
         mForward = forward;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
index 9066876..9178bad6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
@@ -53,7 +53,7 @@
 
     private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
 
-    private static final int SCALE_DOWN_DURATION_MS = 400;
+    private static final int SCALE_DOWN_DURATION_MS = 600;
     private static final int ANIMATE_TO_START_DURATION_MS = 500;
 
     // Minimum number of pull updates necessary to trigger a side nav.
@@ -115,11 +115,7 @@
         public void onAnimationEnd(Animation animation) {
             mArrowView.setFaded(false, false);
             mArrowView.setVisibility(View.INVISIBLE);
-            if (mNavigating) {
-                if (mListener != null) mListener.onNavigate(mIsForward);
-            } else {
-                reset();
-            }
+            if (!mNavigating) reset();
             hideCloseIndicator();
         }
     };
@@ -195,6 +191,9 @@
     }
 
     private void startHidingAnimation(AnimationListener listener) {
+        // Start animation and navigation simultaneously.
+        if (mNavigating && mListener != null) mListener.onNavigate(mIsForward);
+
         // ScaleAnimation needs to be created again if the arrow widget width changes over time
         // (due to turning on/off close indicator) to set the right x pivot point.
         if (mHidingAnimation == null || mAnimationViewWidth != mArrowViewWidth) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index 5c9d7a8..49feb0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -31,7 +31,6 @@
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.favicon.LargeIconBridge;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
 import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver;
@@ -297,14 +296,6 @@
     }
 
     /**
-     * Sets the delegate object needed for history navigation logic.
-     * @param delegate {@link HistoryNavigationDelegate} object.
-     */
-    public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
-        mSelectableListLayout.setHistoryNavigationDelegate(delegate);
-    }
-
-    /**
      * Called when the user presses the back key. This is only going to be called
      * when the history UI is shown in a separate activity rather inside a tab.
      * @return True if manager handles this event, false if it decides to ignore.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
index 5f3405c..fe091ace 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
@@ -33,7 +33,6 @@
         mHistoryManager = new HistoryManager(activity, false, activity.getSnackbarManager(),
                 activity.getCurrentTabModel().isIncognito());
         mTitle = host.getContext().getResources().getString(R.string.menu_history);
-        mHistoryManager.setHistoryNavigationDelegate(host.createHistoryNavigationDelegate());
 
         initWithView(mHistoryManager.getView());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index b5d363b..3b01e24 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -20,8 +20,6 @@
 import org.chromium.chrome.browser.feed.FeedNewTabPage;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
 import org.chromium.chrome.browser.history.HistoryPage;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
@@ -248,11 +246,6 @@
         }
 
         @Override
-        public HistoryNavigationDelegate createHistoryNavigationDelegate() {
-            return HistoryNavigationDelegateFactory.create(mTab);
-        }
-
-        @Override
         public DestroyableObservableSupplier<Rect> createDefaultMarginSupplier() {
             return new BrowserControlsMarginSupplier(mFullscreenManager);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageHost.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageHost.java
index d5412e3..d8cea68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageHost.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageHost.java
@@ -8,7 +8,6 @@
 import android.graphics.Rect;
 
 import org.chromium.base.supplier.DestroyableObservableSupplier;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 /**
@@ -39,12 +38,6 @@
     boolean isVisible();
 
     /**
-     * Creates a delegate object needed for history navigation logic.
-     * @return {@link HistoryNavigationDelegate} implementation.
-     */
-    HistoryNavigationDelegate createHistoryNavigationDelegate();
-
-    /**
      * Creates a default margin supplier. Once created, the NativePage is responsible for calling
      * {@link DestroyableObservableSupplier#destroy()} to clean-up the supplier once it is no longer
      * needed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
index 7b161d6..787856e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
@@ -84,7 +84,6 @@
         mIncognitoNewTabPageView =
                 (IncognitoNewTabPageView) inflater.inflate(R.layout.new_tab_page_incognito, null);
         mIncognitoNewTabPageView.initialize(mIncognitoNewTabPageManager);
-        mIncognitoNewTabPageView.setNavigationDelegate(host.createHistoryNavigationDelegate());
 
         TextView newTabIncognitoHeader =
                 mIncognitoNewTabPageView.findViewById(R.id.new_tab_incognito_title);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java
index 8174bf39..3d62728 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageView.java
@@ -8,16 +8,16 @@
 import android.graphics.Canvas;
 import android.util.AttributeSet;
 import android.view.View;
+import android.widget.FrameLayout;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.ui.base.ViewUtils;
 
 /**
  * The New Tab Page for use in the incognito profile.
  */
-public class IncognitoNewTabPageView extends HistoryNavigationLayout {
+public class IncognitoNewTabPageView extends FrameLayout {
     private IncognitoNewTabPageManager mManager;
     private boolean mFirstShow = true;
     private NewTabPageScrollView mScrollView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 88b99fb..c4e74e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -12,6 +12,7 @@
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
+import android.widget.FrameLayout;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -20,8 +21,6 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegateFactory;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
@@ -40,7 +39,7 @@
  * The native new tab page, represented by some basic data such as title and url, and an Android
  * View that displays the page.
  */
-public class NewTabPageView extends HistoryNavigationLayout {
+public class NewTabPageView extends FrameLayout {
     private static final String TAG = "NewTabPageView";
 
     private NewTabPageRecyclerView mRecyclerView;
@@ -131,7 +130,6 @@
                 mRecyclerView::setTouchEnabled, closeContextMenuCallback,
                 NewTabPage.CONTEXT_MENU_USER_ACTION_PREFIX);
         mTab.getWindowAndroid().addContextMenuCloseListener(mContextMenuManager);
-        setNavigationDelegate(HistoryNavigationDelegateFactory.create(mTab));
 
         OverviewModeBehavior overviewModeBehavior =
                 ((TabImpl) tab).getActivity() instanceof ChromeTabbedActivity
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
index 730c9361..6ee740a7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
@@ -14,6 +14,7 @@
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ExpandableListView;
 
 import org.chromium.base.ActivityState;
@@ -23,7 +24,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.NativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
 import org.chromium.chrome.browser.util.UrlConstants;
@@ -45,7 +45,7 @@
     private final ChromeFullscreenManager mFullscreenManager;
     private final ExpandableListView mListView;
     private final String mTitle;
-    private final HistoryNavigationLayout mView;
+    private final ViewGroup mView;
 
     private RecentTabsManager mRecentTabsManager;
     private RecentTabsRowAdapter mAdapter;
@@ -91,7 +91,7 @@
         mTitle = resources.getString(R.string.recent_tabs);
         mRecentTabsManager.setUpdatedCallback(this);
         LayoutInflater inflater = LayoutInflater.from(activity);
-        mView = (HistoryNavigationLayout) inflater.inflate(R.layout.recent_tabs_page, null);
+        mView = (ViewGroup) inflater.inflate(R.layout.recent_tabs_page, null);
         mListView = (ExpandableListView) mView.findViewById(R.id.odp_listview);
         mAdapter = new RecentTabsRowAdapter(activity, recentTabsManager);
         mListView.setAdapter(mAdapter);
@@ -114,7 +114,6 @@
             mFullscreenManager = null;
         }
 
-        mView.setNavigationDelegate(mPageHost.createHistoryNavigationDelegate());
         onUpdated();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java
index 633ea74..adb3bf1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java
@@ -26,8 +26,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.init.BrowserParts;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.init.EmptyBrowserParts;
@@ -44,8 +42,6 @@
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 import org.chromium.chrome.browser.omaha.OmahaBase;
 import org.chromium.chrome.browser.omaha.UpdateStatusProvider;
-import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateInteractionSource;
-import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateState;
 import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateStatus;
 
 import java.lang.annotation.Retention;
@@ -199,7 +195,9 @@
                             "GoogleUpdate.Notification.LaunchEvent", LaunchEvent.START,
                             LaunchEvent.NUM_ENTRIES);
                     try {
-                        handleUpdateIntent(context, intent);
+                        int state = intent.getIntExtra(UPDATE_NOTIFICATION_STATE_EXTRA,
+                                UpdateStatusProvider.UpdateState.NONE);
+                        UpdateUtils.onUpdateAvailable(context, state);
                     } catch (IllegalArgumentException e) {
                         // If it takes too long to load native library, we may fail to start
                         // activity.
@@ -215,33 +213,5 @@
             ChromeBrowserInitializer.getInstance().handlePreNativeStartup(parts);
             ChromeBrowserInitializer.getInstance().handlePostNativeStartup(true, parts);
         }
-
-        private void handleUpdateIntent(Context context, Intent intent) {
-            @UpdateState
-            int state = intent.getIntExtra(UPDATE_NOTIFICATION_STATE_EXTRA, UpdateState.NONE);
-            switch (state) {
-                case INLINE_UPDATE_AVAILABLE:
-                    Intent launchInlineUpdateIntent =
-                            new Intent(Intent.ACTION_VIEW)
-                                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-                                    .setClass(context, ChromeLauncherActivity.class)
-                                    .putExtra(INLINE_UPDATE_NOTIFICATION_RECEIVED_EXTRA, true);
-                    IntentHandler.startActivityForTrustedIntent(launchInlineUpdateIntent);
-                    break;
-                case UPDATE_AVAILABLE:
-                    Callback<UpdateStatus> intentLauncher = new Callback<UpdateStatus>() {
-                        @Override
-                        public void onResult(UpdateStatus result) {
-                            UpdateStatusProvider.getInstance().startIntentUpdate(context,
-                                    UpdateInteractionSource.FROM_NOTIFICATION, true /* newTask */);
-                            UpdateStatusProvider.getInstance().removeObserver(this);
-                        }
-                    };
-                    UpdateStatusProvider.getInstance().addObserver(intentLauncher);
-                    break;
-                default:
-                    break;
-            }
-        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateUtils.java
new file mode 100644
index 0000000..3015227
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/notification/UpdateUtils.java
@@ -0,0 +1,59 @@
+// 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.omaha.notification;
+
+import static org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateState.INLINE_UPDATE_AVAILABLE;
+import static org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateState.UPDATE_AVAILABLE;
+
+import android.content.Context;
+import android.content.Intent;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.document.ChromeLauncherActivity;
+import org.chromium.chrome.browser.omaha.UpdateStatusProvider;
+import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateState;
+
+/**
+ * Util functions for update notification implementation.
+ */
+public class UpdateUtils {
+    private static final String INLINE_UPDATE_NOTIFICATION_RECEIVED_EXTRA =
+            "org.chromium.chrome.browser.omaha.inline_update_notification_received_extra";
+
+    /**
+     * Addresses different states for update notification.
+     * @param context A {@link Context} Context passing into receiver.
+     * @param state A {@link UpdateState} state of update notification.
+     */
+    public static void onUpdateAvailable(Context context, @UpdateState int state) {
+        switch (state) {
+            case INLINE_UPDATE_AVAILABLE:
+                Intent launchInlineUpdateIntent =
+                        new Intent(Intent.ACTION_VIEW)
+                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                                .setClass(context, ChromeLauncherActivity.class)
+                                .putExtra(INLINE_UPDATE_NOTIFICATION_RECEIVED_EXTRA, true);
+                IntentHandler.startActivityForTrustedIntent(launchInlineUpdateIntent);
+                break;
+            case UPDATE_AVAILABLE:
+                Callback<UpdateStatusProvider.UpdateStatus> intentLauncher =
+                        new Callback<UpdateStatusProvider.UpdateStatus>() {
+                            @Override
+                            public void onResult(UpdateStatusProvider.UpdateStatus result) {
+                                UpdateStatusProvider.getInstance().startIntentUpdate(context,
+                                        UpdateStatusProvider.UpdateInteractionSource
+                                                .FROM_NOTIFICATION,
+                                        true /* newTask */);
+                                UpdateStatusProvider.getInstance().removeObserver(this);
+                            }
+                        };
+                UpdateStatusProvider.getInstance().addObserver(intentLauncher);
+                break;
+            default:
+                break;
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index 2bfa905..59f8822 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.FeatureUtilities;
+import org.chromium.chrome.browser.gesturenav.HistoryNavigationCoordinator;
 import org.chromium.chrome.browser.language.LanguageAskPrompt;
 import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
 import org.chromium.chrome.browser.locale.LocaleManager;
@@ -48,6 +49,7 @@
     private StatusIndicatorCoordinator mStatusIndicatorCoordinator;
     private StatusIndicatorCoordinator.StatusIndicatorObserver mStatusIndicatorObserver;
     private @Nullable ToolbarButtonInProductHelpController mToolbarButtonInProductHelpController;
+    private HistoryNavigationCoordinator mHistoryNavigationCoordinator;
     private boolean mIntentWithEffect;
 
     /**
@@ -95,6 +97,10 @@
         if (mImmersiveModeManager != null) {
             getToolbarManager().setImmersiveModeManager(mImmersiveModeManager);
         }
+        mHistoryNavigationCoordinator = new HistoryNavigationCoordinator();
+        mHistoryNavigationCoordinator.init(mActivity.getLifecycleDispatcher(),
+                mActivity.getCompositorViewHolder(), mActivity.getActivityTabProvider(),
+                mActivity.getInsetObserverView());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index faca1c8..8bb8fd6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -24,9 +24,6 @@
  * UI-less Chrome.
  */
 public class WebApkActivity extends WebappActivity {
-    /** Manages whether to check update for the WebAPK, and starts update check if needed. */
-    private WebApkUpdateManager mUpdateManager;
-
     /** The start time that the activity becomes focused in milliseconds since boot. */
     private long mStartTime;
 
@@ -90,8 +87,7 @@
         WebApkUma.recordShellApkVersion(info.shellApkVersion(), info.distributor());
         storage.incrementLaunchCount();
 
-        mUpdateManager = new WebApkUpdateManager(storage);
-        mUpdateManager.updateIfNeeded(getActivityTab(), info);
+        getComponent().resolveWebApkUpdateManager().updateIfNeeded(storage, info);
     }
 
     @Override
@@ -129,10 +125,6 @@
 
     @Override
     protected void onDestroyInternal() {
-        if (mUpdateManager != null) {
-            mUpdateManager.destroy();
-        }
-
         // The common case is to be connected to just one WebAPK's services. For the sake of
         // simplicity disconnect from the services of all WebAPKs.
         ChromeWebApkHost.disconnectFromAllServices(true /* waitForPendingWork */);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
index 8c735a2..dee2583b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -17,8 +17,12 @@
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.UrlUtilities;
@@ -29,16 +33,21 @@
 
 import java.util.Map;
 
+import javax.inject.Inject;
+
 /**
  * WebApkUpdateManager manages when to check for updates to the WebAPK's Web Manifest, and sends
  * an update request to the WebAPK Server when an update is needed.
  */
-public class WebApkUpdateManager implements WebApkUpdateDataFetcher.Observer {
+@ActivityScope
+public class WebApkUpdateManager implements WebApkUpdateDataFetcher.Observer, Destroyable {
     private static final String TAG = "WebApkUpdateManager";
 
     // Maximum wait time for WebAPK update to be scheduled.
     private static final long UPDATE_TIMEOUT_MILLISECONDS = DateUtils.SECOND_IN_MILLIS * 30;
 
+    private final ChromeActivity mActivity;
+
     /** Whether updates are enabled. Some tests disable updates. */
     private static boolean sUpdatesEnabled = true;
 
@@ -46,7 +55,7 @@
     private WebApkInfo mInfo;
 
     /** The WebappDataStorage with cached data about prior update requests. */
-    private final WebappDataStorage mStorage;
+    private WebappDataStorage mStorage;
 
     private WebApkUpdateDataFetcher mFetcher;
 
@@ -59,20 +68,24 @@
         public void onResultFromNative(@WebApkInstallResult int result, boolean relaxUpdates);
     }
 
-    public WebApkUpdateManager(WebappDataStorage storage) {
-        mStorage = storage;
+    @Inject
+    public WebApkUpdateManager(
+            ChromeActivity activity, ActivityLifecycleDispatcher lifecycleDispatcher) {
+        mActivity = activity;
+        lifecycleDispatcher.register(this);
     }
 
     /**
      * Checks whether the WebAPK's Web Manifest has changed. Requests an updated WebAPK if the Web
      * Manifest has changed. Skips the check if the check was done recently.
-     * @param tab  The tab of the WebAPK.
-     * @param info The WebApkInfo of the WebAPK.
      */
-    public void updateIfNeeded(Tab tab, WebApkInfo info) {
+    public void updateIfNeeded(WebappDataStorage storage, WebApkInfo info) {
+        mStorage = storage;
         mInfo = info;
 
-        if (!shouldCheckIfWebManifestUpdated(mInfo)) return;
+        Tab tab = mActivity.getActivityTab();
+
+        if (tab == null || !shouldCheckIfWebManifestUpdated(mInfo)) return;
 
         mFetcher = buildFetcher();
         mFetcher.start(tab, mInfo, this);
@@ -85,6 +98,7 @@
         }, UPDATE_TIMEOUT_MILLISECONDS);
     }
 
+    @Override
     public void destroy() {
         destroyFetcher();
         if (mUpdateFailureHandler != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
index eb3db77..8e0ca539 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkVersionManager.java
@@ -6,7 +6,6 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.os.Build;
 
 import org.chromium.base.CommandLine;
@@ -15,6 +14,8 @@
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.webapk.lib.client.DexOptimizer;
 import org.chromium.webapk.lib.client.WebApkVersion;
 import org.chromium.webapk.lib.common.WebApkCommonUtils;
@@ -25,18 +26,6 @@
  * Updates installed WebAPKs after a Chrome update.
  */
 public class WebApkVersionManager {
-    /**
-     * Name of the shared preference for the version number of the dynamically loaded dex.
-     */
-    private static final String EXTRACTED_DEX_VERSION_PREF =
-            "org.chromium.chrome.browser.webapps.extracted_dex_version";
-
-    /**
-     * Name of the shared preference for the Android OS version at the time that the dex was last
-     * extracted from Chrome's assets and optimized.
-     */
-    private static final String LAST_SDK_VERSION_PREF =
-            "org.chromium.chrome.browser.webapps.last_sdk_version";
 
     /**
      * Tries to extract the WebAPK runtime dex from the Chrome APK if it has not tried already.
@@ -47,9 +36,10 @@
     public static void updateWebApksIfNeeded() {
         assert !ThreadUtils.runningOnUiThread();
 
-        SharedPreferences preferences = ContextUtils.getAppSharedPreferences();
-        int extractedDexVersion = preferences.getInt(EXTRACTED_DEX_VERSION_PREF, -1);
-        int lastSdkVersion = preferences.getInt(LAST_SDK_VERSION_PREF, -1);
+        SharedPreferencesManager preferences = SharedPreferencesManager.getInstance();
+        int extractedDexVersion =
+                preferences.readInt(ChromePreferenceKeys.WEBAPK_EXTRACTED_DEX_VERSION, -1);
+        int lastSdkVersion = preferences.readInt(ChromePreferenceKeys.WEBAPK_LAST_SDK_VERSION, -1);
         if (!CommandLine.getInstance().hasSwitch(
                     ChromeSwitches.ALWAYS_EXTRACT_WEBAPK_RUNTIME_DEX_ON_STARTUP)
                 && extractedDexVersion == WebApkVersion.CURRENT_RUNTIME_DEX_VERSION
@@ -57,10 +47,9 @@
             return;
         }
 
-        SharedPreferences.Editor editor = preferences.edit();
-        editor.putInt(EXTRACTED_DEX_VERSION_PREF, WebApkVersion.CURRENT_RUNTIME_DEX_VERSION);
-        editor.putInt(LAST_SDK_VERSION_PREF, Build.VERSION.SDK_INT);
-        editor.apply();
+        preferences.writeInt(ChromePreferenceKeys.WEBAPK_EXTRACTED_DEX_VERSION,
+                WebApkVersion.CURRENT_RUNTIME_DEX_VERSION);
+        preferences.writeInt(ChromePreferenceKeys.WEBAPK_LAST_SDK_VERSION, Build.VERSION.SDK_INT);
 
         Context context = ContextUtils.getApplicationContext();
         File dexDir = context.getDir("dex", Context.MODE_PRIVATE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
index 7ecabee..880ef28 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/dependency_injection/WebappActivityComponent.java
@@ -8,6 +8,7 @@
 import org.chromium.chrome.browser.customtabs.dependency_injection.BaseCustomTabActivityComponent;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
+import org.chromium.chrome.browser.webapps.WebApkUpdateManager;
 import org.chromium.chrome.browser.webapps.WebappActivityTabController;
 
 import dagger.Subcomponent;
@@ -21,4 +22,5 @@
 public interface WebappActivityComponent extends BaseCustomTabActivityComponent {
     TrustedWebActivityBrowserControlsVisibilityManager resolveBrowserControlsVisibilityManager();
     WebappActivityTabController resolveTabController();
+    WebApkUpdateManager resolveWebApkUpdateManager();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
index d84b410..2bae900 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
@@ -26,8 +26,6 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationDelegate;
-import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
 import org.chromium.components.browser_ui.widget.FadingShadow;
 import org.chromium.components.browser_ui.widget.FadingShadowView;
@@ -286,18 +284,6 @@
     @Override
     public void onSelectionStateChange(List<E> selectedItems) {
         setToolbarShadowVisibility();
-        if (!selectedItems.isEmpty()) {
-            ((HistoryNavigationLayout) findViewById(R.id.list_content)).release();
-        }
-    }
-
-    /**
-     * Sets the delegate object needed for history navigation logic.
-     * @param delegate {@link HistoryNavigationDelegate} object.
-     */
-    public void setHistoryNavigationDelegate(HistoryNavigationDelegate delegate) {
-        HistoryNavigationLayout layout = (HistoryNavigationLayout) findViewById(R.id.list_content);
-        layout.setNavigationDelegate(delegate);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationSheetTest.java
index a60a6e1..e7139ec 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationSheetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationSheetTest.java
@@ -195,8 +195,8 @@
             Tab tab = mActivityTestRule.getActivity().getActivityTabProvider().get();
             NavigationSheet navigationSheet =
                     NavigationSheet.create(tab.getContentView(), mActivityTestRule.getActivity(),
-                            mActivityTestRule.getActivity()::getBottomSheetController,
-                            new TestSheetDelegate(controller));
+                            mActivityTestRule.getActivity()::getBottomSheetController);
+            navigationSheet.setDelegate(new TestSheetDelegate(controller));
             navigationSheet.startAndExpand(false, false);
             return navigationSheet;
         });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
index 32b4343..7347db7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -18,9 +18,11 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
@@ -69,6 +71,7 @@
     private static final long WEBAPK_THEME_COLOR = 2147483648L;
     private static final long WEBAPK_BACKGROUND_COLOR = 2147483648L;
 
+    private ChromeActivity mActivity;
     private Tab mTab;
 
     /**
@@ -79,8 +82,9 @@
         private CallbackHelper mWaiter;
         private boolean mNeedsUpdate;
 
-        public TestWebApkUpdateManager(CallbackHelper waiter, WebappDataStorage storage) {
-            super(storage);
+        public TestWebApkUpdateManager(CallbackHelper waiter, ChromeActivity activity,
+                ActivityLifecycleDispatcher lifecycleDispatcher) {
+            super(activity, lifecycleDispatcher);
             mWaiter = waiter;
         }
 
@@ -141,7 +145,8 @@
     public void setUp() throws Exception {
         mActivityTestRule.startMainActivityOnBlankPage();
         RecordHistogram.setDisabledForTests(true);
-        mTab = mActivityTestRule.getActivity().getActivityTab();
+        mActivity = mActivityTestRule.getActivity();
+        mTab = mActivity.getActivityTab();
 
         TestFetchStorageCallback callback = new TestFetchStorageCallback();
         WebappRegistry.getInstance().register(WEBAPK_ID, callback);
@@ -156,10 +161,12 @@
      /** Checks whether a WebAPK update is needed. */
     private boolean checkUpdateNeeded(final CreationData creationData) throws Exception {
         CallbackHelper waiter = new CallbackHelper();
-        WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(WEBAPK_ID);
-        final TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(waiter, storage);
+        final TestWebApkUpdateManager updateManager =
+                new TestWebApkUpdateManager(waiter, mActivity, mActivity.getLifecycleDispatcher());
 
         TestThreadUtils.runOnUiThreadBlocking(() -> {
+            WebappDataStorage storage =
+                    WebappRegistry.getInstance().getWebappDataStorage(WEBAPK_ID);
             WebApkInfo info = WebApkInfo.create(
                     "", creationData.scope, null, null, null, creationData.name,
                     creationData.shortName, creationData.displayMode, creationData.orientation, 0,
@@ -172,7 +179,7 @@
                     1 /* webApkVersionCode */
 
             );
-            updateManager.updateIfNeeded(mTab, info);
+            updateManager.updateIfNeeded(storage, info);
         });
         waiter.waitForCallback(0);
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index f102706..856ddef 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -39,8 +39,10 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.background_task_scheduler.ChromeBackgroundTaskFactory;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.test.ShadowUrlUtilities;
 import org.chromium.content_public.common.ScreenOrientationValues;
@@ -150,8 +152,20 @@
         private String mUpdateName;
         private boolean mDestroyedFetcher;
 
-        public TestWebApkUpdateManager(WebappDataStorage storage) {
-            super(storage);
+        public TestWebApkUpdateManager() {
+            this(buildMockActivity(), Mockito.mock(ActivityLifecycleDispatcher.class));
+        }
+
+        private static ChromeActivity buildMockActivity() {
+            Tab mockTab = Mockito.mock(Tab.class);
+            ChromeActivity mockActivity = Mockito.mock(ChromeActivity.class);
+            Mockito.when(mockActivity.getActivityTab()).thenReturn(mockTab);
+            return mockActivity;
+        }
+
+        private TestWebApkUpdateManager(
+                ChromeActivity activity, ActivityLifecycleDispatcher activityLifecycleDispatcher) {
+            super(activity, activityLifecycleDispatcher);
         }
 
         /**
@@ -254,7 +268,7 @@
                 });
     }
 
-    private WebappDataStorage getStorage(String packageName) {
+    private static WebappDataStorage getStorage(String packageName) {
         return WebappRegistry.getInstance().getWebappDataStorage(
                 WebappRegistry.webApkIdForPackage(packageName));
     }
@@ -391,10 +405,6 @@
         return Bitmap.createBitmap(colors, 1, 1, Bitmap.Config.ALPHA_8);
     }
 
-    private static void updateIfNeeded(WebApkUpdateManager updateManager) {
-        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
-    }
-
     private static void updateIfNeeded(String packageName, WebApkUpdateManager updateManager) {
         // Use the intent version of {@link WebApkInfo#create()} in order to test default values
         // set by the intent version of {@link WebApkInfo#create()}.
@@ -403,7 +413,7 @@
         intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, packageName);
         WebApkInfo info = WebApkInfo.create(intent);
 
-        updateManager.updateIfNeeded(null, info);
+        updateManager.updateIfNeeded(getStorage(packageName), info);
     }
 
     private static void onGotUnchangedWebManifestData(WebApkUpdateManager updateManager) {
@@ -473,9 +483,8 @@
                 WEBAPK_PACKAGE_NAME, androidManifestData, REQUEST_UPDATE_FOR_SHELL_APK_VERSION);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         updateManager.onGotManifestData(infoFromManifestData(fetchedManifestData),
                 fetchedManifestData.primaryIconUrl, fetchedManifestData.badgeIconUrl);
@@ -514,9 +523,8 @@
     public void testCheckOnNextLaunchIfClosePriorToFirstPageLoad() {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
         {
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
+            TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+            updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
             assertTrue(updateManager.updateCheckStarted());
         }
 
@@ -524,18 +532,16 @@
 
         {
             // Relaunching the WebAPK should do an is-update-needed check.
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
+            TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+            updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
             assertTrue(updateManager.updateCheckStarted());
             onGotUnchangedWebManifestData(updateManager);
         }
 
         {
             // Relaunching the WebAPK should not do an is-update-needed-check.
-            TestWebApkUpdateManager updateManager =
-                    new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-            updateIfNeeded(updateManager);
+            TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+            updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
             assertFalse(updateManager.updateCheckStarted());
         }
     }
@@ -551,9 +557,8 @@
         long initialTime = mClockRule.currentTimeMillis();
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotUnchangedWebManifestData(updateManager);
         assertFalse(updateManager.updateRequested());
@@ -575,9 +580,8 @@
         storage.updateDidLastWebApkUpdateRequestSucceed(false);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotUnchangedWebManifestData(updateManager);
         assertFalse(updateManager.updateRequested());
@@ -595,9 +599,8 @@
     public void testMarkUpdateAsFailedIfClosePriorToUpdateCompleting() {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotDifferentData(updateManager);
         assertTrue(updateManager.updateRequested());
@@ -620,8 +623,8 @@
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
 
         onGotDifferentData(updateManager);
         assertTrue(updateManager.updateRequested());
@@ -645,8 +648,8 @@
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
 
         onGotDifferentData(updateManager);
         assertTrue(updateManager.updateRequested());
@@ -675,9 +678,8 @@
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION - 1);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
 
         ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
@@ -701,9 +703,8 @@
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION - 1);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
 
         updateManager.destroy();
@@ -722,9 +723,8 @@
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION - 1);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
 
         onGotManifestData(updateManager, defaultManifestData());
@@ -746,9 +746,8 @@
     public void testStartUrlRedirectsToPageWithUpdatedWebManifest() {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
 
         // start_url does not have a Web Manifest. {@link #onGotManifestData} is called as a result
@@ -782,9 +781,8 @@
     public void testStartUrlRedirectsToPageWithUnchangedWebManifest() {
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME));
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
 
         // Update manager times out.
         updateManager.onGotManifestData(null, null, null);
@@ -813,8 +811,7 @@
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION);
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL);
 
-        TestWebApkUpdateManager updateManager =
-                new TestWebApkUpdateManager(getStorage(UNBOUND_WEBAPK_PACKAGE_NAME));
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
         updateIfNeeded(UNBOUND_WEBAPK_PACKAGE_NAME, updateManager);
         assertFalse(updateManager.updateCheckStarted());
         assertFalse(updateManager.updateRequested());
@@ -1149,24 +1146,24 @@
         registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(),
                 REQUEST_UPDATE_FOR_SHELL_APK_VERSION - 1);
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
 
         // There have not been any update requests for the current ShellAPK version. A WebAPK update
         // should be requested immediately.
-        updateIfNeeded(updateManager);
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotManifestData(updateManager, defaultManifestData());
         assertTrue(updateManager.updateRequested());
         tryCompletingUpdate(updateManager, storage, WebApkInstallResult.FAILURE);
 
         mClockRule.advance(1);
-        updateIfNeeded(updateManager);
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertFalse(updateManager.updateCheckStarted());
 
         // A previous update request was made for the current ShellAPK version. A WebAPK update
         // should be requested after the regular delay.
         mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL - 1);
-        updateIfNeeded(updateManager);
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotManifestData(updateManager, defaultManifestData());
         assertTrue(updateManager.updateRequested());
@@ -1180,8 +1177,8 @@
     public void testForcedUpdateSuccess() {
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
         storage.setShouldForceUpdate(true);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotDifferentData(updateManager);
         assertTrue(updateManager.updateRequested());
@@ -1197,8 +1194,8 @@
     public void testForcedUpdateNotNeeded() {
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
         storage.setShouldForceUpdate(true);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotManifestData(updateManager, defaultManifestData());
         assertFalse(updateManager.updateRequested());
@@ -1212,8 +1209,8 @@
     public void testForcedUpdateFailure() {
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
         storage.setShouldForceUpdate(true);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotDifferentData(updateManager);
         assertTrue(updateManager.updateRequested());
@@ -1228,8 +1225,8 @@
     public void testForcedUpdateManifestNotRetrieved() {
         WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME);
         storage.setShouldForceUpdate(true);
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
-        updateIfNeeded(updateManager);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
+        updateIfNeeded(WEBAPK_PACKAGE_NAME, updateManager);
         assertTrue(updateManager.updateCheckStarted());
         onGotManifestData(updateManager, null);
         assertFalse(updateManager.updateRequested());
@@ -1250,7 +1247,7 @@
         storage.setShouldForceUpdate(true);
         assertFalse(storage.shouldForceUpdate());
 
-        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage);
+        TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager();
         updateIfNeeded(UNBOUND_WEBAPK_PACKAGE_NAME, updateManager);
         assertFalse(updateManager.updateCheckStarted());
         assertFalse(updateManager.updateRequested());
diff --git a/chrome/android/modules/chrome_feature_module_tmpl.gni b/chrome/android/modules/chrome_feature_module_tmpl.gni
index fbff253..c1523124 100644
--- a/chrome/android/modules/chrome_feature_module_tmpl.gni
+++ b/chrome/android/modules/chrome_feature_module_tmpl.gni
@@ -54,6 +54,12 @@
     _shared_libraries += [
       "//chrome/android:${_base_target_name}_${_module_desc.name}${_toolchain}",
     ]
+
+    if (android_64bit_target_cpu && _is_monochrome_or_trichrome &&
+        invoker.is_64_bit_browser && build_hwasan_splits) {
+      _hwasan_toolchain = "//build/toolchain/android:android_clang_arm64_hwasan"
+      _shared_libraries += [ "//chrome/android:${_base_target_name}_${_module_desc.name}($_hwasan_toolchain)" ]
+    }
   } else {
     not_needed([ "_is_monochrome_or_trichrome" ])
   }
diff --git a/chrome/android/modules/extra_icu/internal/BUILD.gn b/chrome/android/modules/extra_icu/internal/BUILD.gn
index da8ed097..2d3e2e1 100644
--- a/chrome/android/modules/extra_icu/internal/BUILD.gn
+++ b/chrome/android/modules/extra_icu/internal/BUILD.gn
@@ -5,9 +5,8 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java" ]
   deps = [
     "//base:base_java",
     "//chrome/android/modules/extra_icu/public:java",
diff --git a/chrome/android/modules/image_editor/public/BUILD.gn b/chrome/android/modules/image_editor/public/BUILD.gn
index a1dba9b..df0367b2 100644
--- a/chrome/android/modules/image_editor/public/BUILD.gn
+++ b/chrome/android/modules/image_editor/public/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/modules/image_editor/ImageEditorProvider.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/modules/image_editor/ImageEditorProvider.java" ]
 
   deps = [
     "//chrome/browser/image_editor/public:java",
diff --git a/chrome/android/modules/stack_unwinder/provider/BUILD.gn b/chrome/android/modules/stack_unwinder/provider/BUILD.gn
index 45dde3f..06a0c2a 100644
--- a/chrome/android/modules/stack_unwinder/provider/BUILD.gn
+++ b/chrome/android/modules/stack_unwinder/provider/BUILD.gn
@@ -11,7 +11,5 @@
     "//chrome/android/features/stack_unwinder/public:java",
     "//chrome/android/modules/stack_unwinder/public:java",
   ]
-  sources = [
-    "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderModuleProvider.java" ]
 }
diff --git a/chrome/android/modules/test_dummy/internal/BUILD.gn b/chrome/android/modules/test_dummy/internal/BUILD.gn
index 92361888..e9989ec 100644
--- a/chrome/android/modules/test_dummy/internal/BUILD.gn
+++ b/chrome/android/modules/test_dummy/internal/BUILD.gn
@@ -6,9 +6,7 @@
 import("//chrome/android/modules/buildflags.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/modules/test_dummy/TestDummyProviderImpl.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyProviderImpl.java" ]
   deps = [
     "//base:base_java",
     "//chrome/android/features/test_dummy/internal:java",
@@ -22,15 +20,11 @@
 # component target must be named according to the feature, so that the component
 # build's .cr.co library is named properly (ie. libtest_dummy.cr.so).
 group("native") {
-  deps = [
-    ":test_dummy",
-  ]
+  deps = [ ":test_dummy" ]
 }
 
 component("test_dummy") {
-  sources = [
-    "entrypoints.cc",
-  ]
+  sources = [ "entrypoints.cc" ]
   deps = [
     ":jni_registration",
     "//base",
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index f87bc1d..25d52b3a 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -17,9 +17,7 @@
 
 # This target is for dependency tracking for the command ID header.
 source_set("command_ids") {
-  sources = [
-    "chrome_command_ids.h",
-  ]
+  sources = [ "chrome_command_ids.h" ]
 }
 
 # TODO: put back in chrome/browser if necessary. http://crbug.com/771801.
@@ -30,9 +28,7 @@
       "shutdown_signal_handlers_posix.h",
     ]
   }
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 # On Windows, links chrome_dll.rc. On other platforms, does nothing so you can
@@ -40,13 +36,9 @@
 source_set("chrome_dll_resources") {
   # This source is added unconditionally for include checking on non-Windows
   # platforms.
-  sources = [
-    "chrome_dll_resource.h",
-  ]
+  sources = [ "chrome_dll_resource.h" ]
 
-  deps = [
-    ":command_ids",
-  ]
+  deps = [ ":command_ids" ]
 
   if (is_win) {
     sources += [
@@ -88,9 +80,7 @@
     grit_output_dir = "$root_gen_dir/chrome/java/res"
     generated_files =
         rebase_path(android_generated_java_resources, "java/res", ".")
-    deps = [
-      ":generated_resources",
-    ]
+    deps = [ ":generated_resources" ]
   }
 }
 
@@ -271,7 +261,5 @@
 }
 
 source_set("chrome_service_manifests") {
-  public_deps = [
-    ":chrome_content_browser_overlay_manifest",
-  ]
+  public_deps = [ ":chrome_content_browser_overlay_manifest" ]
 }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index f2670c8..01a2246 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -395,6 +395,12 @@
 #define IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS 52411
 #define IDC_CONTENT_CONTEXT_ACCESSIBILITY_LABELS_TOGGLE_ONCE 52412
 
+#if defined(OS_CHROMEOS)
+// Quick Answers context menu items.
+#define IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER 52413
+#define IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY 52414
+#endif
+
 // NOTE: The last valid command value is 57343 (0xDFFF)
 // See http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index bcb4717..680bc03 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -793,6 +793,20 @@
   <message name="IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE" desc="The label on the button that closes dialog while accepting the selected settings.">
     Accept and continue
   </message>
+
+  <message name="IDS_LOGIN_OS_SYNC_CONSENT_TITLE" desc="OS sync consent screen dialog title/header">
+    Sync for a personalized experience across devices
+  </message>
+  <message name="IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME" desc="Label for the toggle button that enables OS sync">
+    Sync my <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
+  </message>
+  <message name="IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION" desc="Description for the toggle button that enables OS sync">
+    Your apps, settings, and Wi-Fi preferences will be synced. To make changes, go to Settings at any time after setup.
+  </message>
+  <message name="IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE" desc="Button label for OS sync consent screen.">
+    Continue
+  </message>
+
   <message name="IDS_LOGIN_RECOMMEND_APPS_SCREEN_TITLE" desc="The title of the dialog that recommend apps which user has installed in other devices">
     Install apps from your other devices
   </message>
@@ -893,7 +907,7 @@
     Confirm your password
   </message>
   <message name="IDS_DISCOVER_PIN_SETUP_PASSWORD_SUBTITLE" desc="A sub-title of the dialog that starts 'PIN-unlock' setup process, and asks user to type their password first.">
-    Enter your password to configure screen lock and sign-in
+    Enter your password to configure security and sign-in
   </message>
   <message name="IDS_DISCOVER_PIN_SETUP_DONE" desc="Label for the done button on the success screen in 'PIN-unlock' setup dialog.">
     Done
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE.png.sha1
new file mode 100644
index 0000000..76e7d8e
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE.png.sha1
@@ -0,0 +1 @@
+0bb041089cfdeaeffdf0e9da4a25f62f6a7bd33c
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TITLE.png.sha1
new file mode 100644
index 0000000..76e7d8e
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TITLE.png.sha1
@@ -0,0 +1 @@
+0bb041089cfdeaeffdf0e9da4a25f62f6a7bd33c
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..76e7d8e
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+0bb041089cfdeaeffdf0e9da4a25f62f6a7bd33c
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME.png.sha1
new file mode 100644
index 0000000..76e7d8e
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME.png.sha1
@@ -0,0 +1 @@
+0bb041089cfdeaeffdf0e9da4a25f62f6a7bd33c
\ No newline at end of file
diff --git a/chrome/app/extensions_strings.grdp b/chrome/app/extensions_strings.grdp
index a95deb2a..fdac86d 100644
--- a/chrome/app/extensions_strings.grdp
+++ b/chrome/app/extensions_strings.grdp
@@ -16,6 +16,9 @@
   <message name="IDS_EXTENSIONS_BACKGROUND_PAGE" desc="Display name for an autogenerated background page.">
     background page
   </message>
+  <message name="IDS_EXTENSIONS_DISABLED_BLOCKED_MATURE" desc="The tooltip displayed when the extension is blocked due to mature content for child users.">
+    This is blocked due to mature content.
+  </message>
   <message name="IDS_EXTENSIONS_CORRUPTED_EXTENSION" desc="The warning for the user that an extension may have been tampered with on disk.">
     This extension may have been corrupted.
   </message>
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_DISABLED_BLOCKED_MATURE.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_DISABLED_BLOCKED_MATURE.png.sha1
new file mode 100644
index 0000000..0b27c99b
--- /dev/null
+++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_DISABLED_BLOCKED_MATURE.png.sha1
@@ -0,0 +1 @@
+6c9f917fe0ca52c374a80b9d663376801a45cb9b
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 4d2ac71c..e419368 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -4090,8 +4090,8 @@
     <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK" desc="Text on the people page which opens up the quick unlock subpage and the title of the quick unlock subpage.">
       Screen lock
     </message>
-    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK" desc="Text on the people page which opens up the quick unlock subpage and the title of the quick unlock subpage.">
-      Screen lock and sign-in
+    <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK" desc="Text on the people page which opens up the security and sign-in section.">
+      Security and sign-in
     </message>
     <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK" desc="Text on the lock screen which is the subheader for the screen locking options.">
       Screen lock options
@@ -4246,8 +4246,8 @@
     <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings.">
       Enter your password to configure screen lock
     </message>
-    <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure these settings.">
-      Enter your password to configure screen lock and sign-in
+    <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK" desc="Text above a password input field that tells the user they need to submit their password to configure security and sign-in settings.">
+      Enter your password to configure security and sign-in
     </message>
     <message name="IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_PASSWORD_LABEL" desc="An input box label that tells the user to enter their password in that input box.">
       Password
@@ -5572,7 +5572,7 @@
     Add fingerprint
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_CHOOSE_NAME" desc="A label instructing the user to provide a descriptive name for a fingerprint enrolled to a security key.">
-    Choose a name for this fingerprint
+    Enter a name for this fingerprint
   </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_NAME_LABEL" desc="A label for a text input field containing a descriptive name for a fingerprint enrolled to a security key.">
     Name
@@ -5586,6 +5586,12 @@
   <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL" desc="A label instructing the user to repeatedly touch the fingerprint sensor on their security key (authentication hardware device) to take samples for a new fingerprint.">
     Keep touching your security key until your fingerprint is captured
   </message>
+  <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_TRY_AGAIN_LABEL" desc="A label instructing the user to touch the fingerprint sensor on their security key (authentication hardware device) again after taking a fingerprint sample failed.">
+    Try touching your security key again
+  </message>
+  <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_FAILED_LABEL" desc="An error shown after enrolling a new fingerprint to a security key (authentication hardware device) was unsuccessful.">
+    Adding a fingerprint to this security key failed
+  </message>
   <message name="IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL" desc="A label informing the user that adding a fingerprint to their security key succeeded.">
     Your fingerprint was captured
   </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index 4935e7a1..4918da1c 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -224,6 +224,10 @@
       "google_chrome/google_pay_logo.icon",
     ]
   }
+
+  if (is_chrome_branded && is_chromeos) {
+    icons += [ "google_chrome/assistant.icon" ]
+  }
 }
 
 source_set("vector_icons") {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9ea6d56..5e58d3ac 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3812,6 +3812,8 @@
       "notifications/web_page_notifier_controller.h",
       "policy/default_geolocation_policy_handler.cc",
       "policy/default_geolocation_policy_handler.h",
+      "renderer_context_menu/quick_answers_menu_observer.cc",
+      "renderer_context_menu/quick_answers_menu_observer.h",
       "signin/signin_error_notifier_ash.cc",
       "signin/signin_error_notifier_ash.h",
       "signin/signin_error_notifier_factory_ash.cc",
@@ -3846,6 +3848,7 @@
       "//chrome/browser/chromeos",
       "//chrome/services/app_service/public/cpp:instance_update",
       "//chromeos/components/account_manager",
+      "//chromeos/components/quick_answers",
       "//chromeos/components/sync_wifi",
       "//chromeos/services/assistant/public:feature_flags",
       "//chromeos/services/assistant/public/cpp:prefs",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d720870..ac252a05c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4039,6 +4039,10 @@
     {"d3d11-video-decoder", flag_descriptions::kD3D11VideoDecoderName,
      flag_descriptions::kD3D11VideoDecoderDescription, kOsWin,
      FEATURE_VALUE_TYPE(media::kD3D11VideoDecoder)},
+#elif defined(OS_CHROMEOS)
+    {"chromeos-video-decoder", flag_descriptions::kChromeosVideoDecoderName,
+     flag_descriptions::kChromeosVideoDecoderDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(media::kChromeosVideoDecoder)},
 #endif
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/android/metrics/BUILD.gn b/chrome/browser/android/metrics/BUILD.gn
index ebb7d8c..d79c9ff 100644
--- a/chrome/browser/android/metrics/BUILD.gn
+++ b/chrome/browser/android/metrics/BUILD.gn
@@ -9,9 +9,7 @@
 
   static_library("ukm_utils_for_test") {
     testonly = true
-    sources = [
-      "ukm_utils_for_test.cc",
-    ]
+    sources = [ "ukm_utils_for_test.cc" ]
     deps = [
       "//chrome/browser",
       "//chrome/browser/android/metrics:jni_headers",
@@ -28,16 +26,13 @@
   android_library("ukm_java_test_support") {
     testonly = true
     sources = _jni_sources
-    deps = [
-      "//base:base_java",
-    ]
+    deps = [ "//base:base_java" ]
   }
 
   android_library("ukm_javatests") {
     testonly = true
-    sources = [
-      "javatests/src/org/chromium/chrome/browser/metrics/UkmTest.java",
-    ]
+    sources =
+        [ "javatests/src/org/chromium/chrome/browser/metrics/UkmTest.java" ]
 
     deps = [
       ":ukm_java_test_support",
diff --git a/chrome/browser/android/webapk/BUILD.gn b/chrome/browser/android/webapk/BUILD.gn
index 6bcd0ac..7040962 100644
--- a/chrome/browser/android/webapk/BUILD.gn
+++ b/chrome/browser/android/webapk/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "webapk.proto",
-  ]
+  sources = [ "webapk.proto" ]
 }
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
index 5cb2591..db11d59 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -1918,11 +1918,16 @@
 void ArcBluetoothBridge::DeleteService(int32_t service_handle,
                                        DeleteServiceCallback callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+  auto itr = gatt_identifier_.find(service_handle);
+  if (itr == gatt_identifier_.end()) {
+    LOG(WARNING) << "DeleteService called with invalid service handle.";
+    return;
+  }
+
   BluetoothLocalGattService* service =
-      bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+      bluetooth_adapter_->GetGattService(itr->second);
   DCHECK(service);
-  gatt_identifier_.erase(service_handle);
+  gatt_identifier_.erase(itr);
   gatt_handle_.erase(service->GetIdentifier());
   service->Delete();
   OnGattOperationDone(std::move(callback));
diff --git a/chrome/browser/chromeos/crostini/BUILD.gn b/chrome/browser/chromeos/crostini/BUILD.gn
index b83dad2..8759b02 100644
--- a/chrome/browser/chromeos/crostini/BUILD.gn
+++ b/chrome/browser/chromeos/crostini/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("crostini_installer_types_mojom") {
-  sources = [
-    "crostini_installer_types.mojom",
-  ]
+  sources = [ "crostini_installer_types.mojom" ]
 }
diff --git a/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc b/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc
index 087c3d3..a387844 100644
--- a/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc
+++ b/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc
@@ -83,11 +83,21 @@
       return ash::prefs::kAccessibilityAutoclickEnabled;
     if (feature == "virtualKeyboard")
       return ash::prefs::kAccessibilityVirtualKeyboardEnabled;
+    if (feature == "caretHighlight")
+      return ash::prefs::kAccessibilityCaretHighlightEnabled;
+    if (feature == "cursorHighlight")
+      return ash::prefs::kAccessibilityCursorHighlightEnabled;
+    if (feature == "focusHighlight")
+      return ash::prefs::kAccessibilityFocusHighlightEnabled;
+    if (feature == "selectToSpeak")
+      return ash::prefs::kAccessibilitySelectToSpeakEnabled;
+    if (feature == "switchAccess")
+      return ash::prefs::kAccessibilitySwitchAccessEnabled;
     return NULL;
   }
 
   // Initializes preferences before running the test extension.
-  // |prefs| Pref service which should be initializzed.
+  // |prefs| Pref service which should be initialized.
   // |enabled_features| List of boolean preference whose value should be set to
   //     true.
   // |disabled_features| List of boolean preferences whose value should be set
@@ -163,32 +173,28 @@
   }
 };
 
-INSTANTIATE_TEST_SUITE_P(AccessibilityFeatureaApiTestInstantiatePermission,
+INSTANTIATE_TEST_SUITE_P(AccessibilityFeaturesApiTestInstantiatePermission,
                          AccessibilityFeaturesApiTest,
                          testing::Bool());
 
 // Tests that an extension with read permission can read accessibility features
 // state, while an extension that doesn't have the permission cannot.
 IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Get) {
-  // WARNING: Make sure that spoken feedback is not among enabled_features
-  // (see |Set| test for the reason).
-  std::vector<std::string> enabled_features;
-  enabled_features.push_back("largeCursor");
-  enabled_features.push_back("stickyKeys");
-  enabled_features.push_back("highContrast");
+  // WARNING: Make sure that features which load Chrome extension are not among
+  // enabled_features (see |Set| test for the reason).
+  std::vector<std::string> enabled_features = {
+      "largeCursor", "stickyKeys", "highContrast", "cursorHighlight"};
 
-  std::vector<std::string> disabled_features;
-  disabled_features.push_back("spokenFeedback");
-  disabled_features.push_back("screenMagnifier");
-  disabled_features.push_back("autoclick");
-  disabled_features.push_back("virtualKeyboard");
+  std::vector<std::string> disabled_features = {
+      "spokenFeedback", "screenMagnifier", "autoclick",    "virtualKeyboard",
+      "focusHighlight", "selectToSpeak",   "switchAccess", "caretHighlight"};
 
   ASSERT_TRUE(
       InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
 
   std::string test_arg;
-  ASSERT_TRUE(GenerateTestArg(
-      "getterTest", enabled_features, disabled_features, &test_arg));
+  ASSERT_TRUE(GenerateTestArg("getterTest", enabled_features, disabled_features,
+                              &test_arg));
   EXPECT_TRUE(
       RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()))
       << message_;
@@ -205,13 +211,14 @@
 // sets up access to accessibility prefs. Otherwise,this is the same as the
 // |Get| test.
 IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Get_ComponentApp) {
-  // WARNING: Make sure that spoken feedback is not among enabled_features
-  // (see |AccessibilityFeaturesApiTest.Set| test for the reason).
-  std::vector<std::string> enabled_features = {"largeCursor", "stickyKeys",
-                                               "highContrast"};
+  // WARNING: Make sure that features which load Chrome extension are not among
+  // enabled_features (see |Set| test for the reason).
+  std::vector<std::string> enabled_features = {
+      "largeCursor", "stickyKeys", "highContrast", "cursorHighlight"};
 
   std::vector<std::string> disabled_features = {
-      "spokenFeedback", "screenMagnifier", "autoclick", "virtualKeyboard"};
+      "spokenFeedback", "screenMagnifier", "autoclick",    "virtualKeyboard",
+      "focusHighlight", "selectToSpeak",   "switchAccess", "caretHighlight"};
 
   ASSERT_TRUE(
       InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
@@ -228,30 +235,28 @@
 // Tests that an extension with modify permission can modify accessibility
 // features, while an extension that doesn't have the permission can't.
 IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Set) {
-  // WARNING: Make sure that spoken feedback does not get enabled at this point
-  // (before the test app is loaded), as that may break the test:
+  // WARNING: Make sure that features which load Chrome extension are not
+  // enabled at this point (before the test app is loaded), as that may break
+  // the test:
   // |RunPlatformAppTestWithArg| waits for the test extension to load by
   // waiting for EXTENSION_LOADED notification to be observed. It also assumes
   // that there is only one extension being loaded during this time (it finishes
-  // when the first notification is seen). Enabling spoken feedback here would
-  // break this assumption as it would induce loading of ChromeVox extension.
-  std::vector<std::string> enabled_features;
-  enabled_features.push_back("stickyKeys");
-  enabled_features.push_back("virtualKeyboard");
+  // when the first notification is seen). Enabling spoken feedback, select to
+  // speak, autoclick, or switch access here would break this assumption as it
+  // would induce loading of Chrome extension.
+  std::vector<std::string> enabled_features = {
+      "stickyKeys", "virtualKeyboard", "caretHighlight", "focusHighlight"};
 
-  std::vector<std::string> disabled_features;
-  disabled_features.push_back("spokenFeedback");
-  disabled_features.push_back("largeCursor");
-  disabled_features.push_back("highContrast");
-  disabled_features.push_back("screenMagnifier");
-  disabled_features.push_back("autoclick");
+  std::vector<std::string> disabled_features = {
+      "spokenFeedback", "largeCursor",     "highContrast",  "screenMagnifier",
+      "autoclick",      "cursorHighlight", "selectToSpeak", "switchAccess"};
 
   ASSERT_TRUE(
       InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
 
   std::string test_arg;
-  ASSERT_TRUE(GenerateTestArg(
-      "setterTest", enabled_features, disabled_features, &test_arg));
+  ASSERT_TRUE(GenerateTestArg("setterTest", enabled_features, disabled_features,
+                              &test_arg));
 
   // The test extension attempts to flip all feature values.
   ASSERT_TRUE(
@@ -269,27 +274,24 @@
 // Tests that an extension with read permission is notified when accessibility
 // features change.
 IN_PROC_BROWSER_TEST_F(AccessibilityFeaturesApiTest, ObserveFeatures) {
-  // WARNING: Make sure that spoken feedback is not among enabled_features
-  // (see |Set| test for the reason).
-  std::vector<std::string> enabled_features;
-  enabled_features.push_back("largeCursor");
-  enabled_features.push_back("stickyKeys");
-  enabled_features.push_back("highContrast");
+  // WARNING: Make sure that features which load Chrome extension are not among
+  // enabled_features (see |Set| test for the reason).
+  std::vector<std::string> enabled_features = {"largeCursor", "stickyKeys",
+                                               "highContrast"};
 
-  std::vector<std::string> disabled_features;
-  disabled_features.push_back("screenMagnifier");
+  std::vector<std::string> disabled_features = {"screenMagnifier"};
 
   ASSERT_TRUE(
       InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
 
   std::string test_arg;
-  ASSERT_TRUE(GenerateTestArg(
-      "observerTest", enabled_features, disabled_features, &test_arg));
+  ASSERT_TRUE(GenerateTestArg("observerTest", enabled_features,
+                              disabled_features, &test_arg));
 
-  // The test extension is supposed to report result twice when runnign this
+  // The test extension is supposed to report result twice when running this
   // test. First time when in initializes it's feature listeners, and second
   // time, when gets all expected events. This is done so the extension is
-  // running when the accessibility features are flipped; oterwise, the
+  // running when the accessibility features are flipped; otherwise, the
   // extension may not see events.
   ASSERT_TRUE(RunPlatformAppTestWithArg(kTestExtensionPathReadPermission,
                                         test_arg.c_str()))
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index dfcbd38..babc570 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -469,6 +469,7 @@
         TestCase("openQuickViewTabIndexAudio"),
         TestCase("openQuickViewTabIndexVideo"),
         TestCase("pressEnterOnInfoBoxToOpenClose"),
+        TestCase("openQuickViewWithMultipleFiles"),
         TestCase("closeQuickView"),
         TestCase("openQuickViewFromDirectoryTree")));
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
index f38bdf81..0824688 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -169,8 +169,8 @@
 // Returns the list of locales (and related info) supported by demo mode.
 std::vector<ash::LocaleInfo> GetSupportedLocales() {
   const base::flat_set<std::string> kSupportedLocales(
-      {"da", "de", "en-GB", "en-US", "fi", "fr", "fr-CA", "ja", "nb", "nl",
-       "sv"});
+      {"da", "de", "en-GB", "en-US", "es", "fi", "fr", "fr-CA", "it", "ja",
+       "nb", "nl", "sv"});
 
   const std::vector<std::string>& available_locales =
       l10n_util::GetAvailableLocales();
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.h b/chrome/browser/chromeos/login/demo_mode/demo_session.h
index dc11ea3..68e8236 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_session.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_session.h
@@ -78,8 +78,8 @@
   // TODO(crbug.com/983359): Sort these by country name in the current locale
   // instead of using this hard-coded US-centric order.
   static constexpr char kSupportedCountries[][3] = {
-      "us", "be", "ca", "dk", "fi", "fr", "de",
-      "ie", "jp", "lu", "nl", "no", "se", "gb"};
+      "us", "be", "ca", "dk", "fi", "fr", "de", "ie",
+      "it", "jp", "lu", "nl", "no", "es", "se", "gb"};
 
   static std::string DemoConfigToString(DemoModeConfig config);
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
index a37b276..3ede916 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
@@ -605,10 +605,12 @@
        {"fr", "France"},
        {"de", "Germany"},
        {"ie", "Ireland"},
+       {"it", "Italy"},
        {"jp", "Japan"},
        {"lu", "Luxembourg"},
        {"nl", "Netherlands"},
        {"no", "Norway"},
+       {"es", "Spain"},
        {"se", "Sweden"},
        {"gb", "United Kingdom"}});
   for (const std::string country_code : DemoSession::kSupportedCountries) {
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
index ebc5e558..6de08ef 100644
--- a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
@@ -28,8 +28,12 @@
 #include "components/prefs/pref_service.h"
 #include "components/sync/base/pref_names.h"
 #include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "ui/base/l10n/l10n_util.h"
 
+using testing::Contains;
+using testing::UnorderedElementsAre;
+
 namespace chromeos {
 namespace {
 
@@ -328,22 +332,21 @@
   // Consent was recorded for the confirmation button.
   EXPECT_EQ(SyncConsentScreen::CONSENT_GIVEN,
             consent_recorded_waiter.consent_given_);
-  EXPECT_EQ("Accept and continue",
-            consent_recorded_waiter.consent_confirmation_string_);
-  EXPECT_EQ(IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE,
+  EXPECT_EQ("Continue", consent_recorded_waiter.consent_confirmation_string_);
+  EXPECT_EQ(IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE,
             consent_recorded_waiter.consent_confirmation_id_);
 
   // Consent was recorded for all descriptions, including the confirmation
   // button label.
-  // TODO(jamescook): When PLACEHOLDER strings are replaced, add checks for the
-  // correct text and IDs here.
-  std::vector<std::string> expected_desc_strings = {"Accept and continue"};
-  std::vector<int> expected_desc_ids = {
-      IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE};
-  EXPECT_EQ(expected_desc_strings,
-            consent_recorded_waiter.consent_description_strings_);
-  EXPECT_EQ(expected_desc_ids,
-            consent_recorded_waiter.consent_description_ids_);
+  EXPECT_THAT(consent_recorded_waiter.consent_description_ids_,
+              UnorderedElementsAre(IDS_LOGIN_OS_SYNC_CONSENT_TITLE,
+                                   IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME,
+                                   IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION,
+                                   IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE));
+
+  // Verify device-name substitution happened. Tests use "Chrome device".
+  EXPECT_THAT(consent_recorded_waiter.consent_description_strings_,
+              Contains("Sync my Chrome device"));
 
   // Toggle button is on-by-default, so OS sync should be on.
   EXPECT_TRUE(prefs->GetBoolean(syncer::prefs::kOsSyncFeatureEnabled));
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index f2db16a..b99a22d 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1415,16 +1415,18 @@
       // already present in |AccountManager|.
 
       // 2. Make sure that IdentityManager has been notified about it.
-      base::Optional<AccountInfo> maybe_account_info =
+      base::Optional<AccountInfo> account_info =
           identity_manager
               ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
                   gaia_id);
-      DCHECK(maybe_account_info.has_value());
-      // Make sure that the google service username is properly set (we do this
-      // on every sign in, not just the first login, to deal with existing
-      // profiles that might not have it set yet).
-      identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount(
-          maybe_account_info->account_id);
+      DCHECK(account_info.has_value());
+      if (user_manager->IsCurrentUserNew() || profile->IsNewProfile()) {
+        identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount(
+            account_info->account_id);
+      } else {
+        CHECK(identity_manager->HasPrimaryAccount());
+        CHECK_EQ(identity_manager->GetPrimaryAccountInfo().gaia, gaia_id);
+      }
     } else {
       // Make sure that the google service username is properly set (we do this
       // on every sign in, not just the first login, to deal with existing
diff --git a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.cc b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.cc
index b92b38f..0ff7924f 100644
--- a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.cc
+++ b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.cc
@@ -4,9 +4,24 @@
 
 #include "chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h"
 
+#include <memory>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/important_file_writer.h"
+#include "base/location.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task_runner_util.h"
+#include "base/threading/scoped_blocking_call.h"
 #include "chrome/browser/chromeos/power/ml/recent_events_counter.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/constants/devicetype.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/session_manager/core/session_manager_observer.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "services/metrics/public/cpp/metrics_utils.h"
 #include "ui/aura/env.h"
@@ -16,6 +31,8 @@
 namespace power {
 
 namespace {
+constexpr int kBucketSize = 15;
+
 // Interval at which data should be logged.
 constexpr base::TimeDelta kLoggingInterval = base::TimeDelta::FromMinutes(30);
 
@@ -27,11 +44,110 @@
 // Granularity of input events is per minute.
 constexpr int kNumUserInputEventsBuckets =
     kUserActivityDuration / base::TimeDelta::FromMinutes(1);
+
+constexpr char kSavedFileName[] = "past_charging_events.pb";
+constexpr char kSavedDir[] = "smartcharging";
+
+// Given a proto and file path, writes to disk and logs the error(if any).
+void WriteProtoToDisk(const PastChargingEvents& proto,
+                      const base::FilePath& file_path) {
+  std::string proto_string;
+  if (!proto.SerializeToString(&proto_string)) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return;
+  }
+  bool write_result;
+  {
+    base::ScopedBlockingCall scoped_blocking_call(
+        FROM_HERE, base::BlockingType::MAY_BLOCK);
+    write_result = base::ImportantFileWriter::WriteFileAtomically(
+        file_path, proto_string.data(), "SmartCharging");
+  }
+
+  if (!write_result) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return;
+  }
+  // TODO(crbug.com/1028853): adds a UMA log here.
+}
+
+// Reads a proto from a file path.
+std::unique_ptr<PastChargingEvents> ReadProto(const base::FilePath& file_path) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+  std::string proto_str;
+  if (!base::ReadFileToString(file_path, &proto_str)) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return nullptr;
+  }
+
+  auto proto = std::make_unique<PastChargingEvents>();
+  if (!proto->ParseFromString(proto_str)) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return nullptr;
+  }
+  // TODO(crbug.com/1028853): adds a UMA log here.
+  return proto;
+}
+
+// If |create_new_path| is true, try to create new path and return true if
+// success.
+// If |create_new_path| is false, try to get the path and return true if
+// sucesss.
+bool GetPathSuccess(const base::FilePath profile_path,
+                    base::FilePath* file_path,
+                    bool create_new_path) {
+  const base::FilePath path = profile_path.AppendASCII(kSavedDir);
+  if (create_new_path) {
+    if (!base::DirectoryExists(path) && !base::CreateDirectory(path)) {
+      // TODO(crbug.com/1028853): adds a UMA log here.
+      return false;
+    }
+  } else if (!base::PathExists(path.AppendASCII(kSavedFileName))) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return false;
+  }
+  // TODO(crbug.com/1028853): adds a UMA log here.
+  *file_path = path.AppendASCII(kSavedFileName);
+  return true;
+}
+
+// Checks if an event is a halt (shutdown/suspend) event.
+bool IsHaltEvent(const PastEvent& event) {
+  return event.reason() == UserChargingEvent::Event::SHUTDOWN ||
+         event.reason() == UserChargingEvent::Event::SUSPEND;
+}
+
+// Loads data from disk given a profile file path.
+std::unique_ptr<PastChargingEvents> LoadFromDisk(
+    const base::FilePath& profile_path) {
+  base::FilePath file_path;
+  std::unique_ptr<PastChargingEvents> proto;
+  if (GetPathSuccess(profile_path, &file_path, false /*create_new_path*/)) {
+    proto = ReadProto(file_path);
+  }
+  return proto;
+}
+
+// Saves data to disk given a profile file path.
+void SaveToDisk(const std::vector<PastEvent>& past_events,
+                const base::FilePath& profile_path) {
+  base::FilePath file_path;
+  if (GetPathSuccess(profile_path, &file_path, true /*create_new_path*/)) {
+    PastChargingEvents proto;
+    for (const auto& event : past_events) {
+      *proto.add_events() = event;
+    }
+    WriteProtoToDisk(proto, file_path);
+  }
+}
+
 }  // namespace
 
 SmartChargingManager::SmartChargingManager(
     ui::UserActivityDetector* detector,
     mojo::PendingReceiver<viz::mojom::VideoDetectorObserver> receiver,
+    session_manager::SessionManager* session_manager,
     std::unique_ptr<base::RepeatingTimer> periodic_timer)
     : periodic_timer_(std::move(periodic_timer)),
       receiver_(this, std::move(receiver)),
@@ -50,8 +166,13 @@
       ukm_logger_(std::make_unique<SmartChargingUkmLogger>()) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(detector);
+  DCHECK(session_manager);
   user_activity_observer_.Add(detector);
   power_manager_client_observer_.Add(chromeos::PowerManagerClient::Get());
+  session_manager_observer_.Add(session_manager);
+  blocking_task_runner_ = base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
 SmartChargingManager::~SmartChargingManager() = default;
@@ -70,6 +191,7 @@
   std::unique_ptr<SmartChargingManager> screen_brightness_manager =
       std::make_unique<SmartChargingManager>(
           detector, video_observer.InitWithNewPipeAndPassReceiver(),
+          session_manager::SessionManager::Get(),
           std::make_unique<base::RepeatingTimer>());
 
   aura::Env::GetInstance()
@@ -201,6 +323,21 @@
   is_video_playing_ = false;
 }
 
+void SmartChargingManager::OnUserSessionStarted(bool /* is_primary_user */) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // The first sign-in user is the primary user, hence if |OnUserSessionStarted|
+  // is called, the primary user profile should have been created. We will
+  // ignore |is_primary_user|.
+  if (loaded_from_disk_)
+    return;
+  if (!ProfileManager::GetPrimaryUserProfile()) {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+    return;
+  }
+  profile_path_ = ProfileManager::GetPrimaryUserProfile()->GetPath();
+  MaybeLoadFromDisk(profile_path_.value());
+}
+
 void SmartChargingManager::PopulateUserChargingEventProto(
     UserChargingEvent* proto) {
   auto& features = *proto->mutable_features();
@@ -229,8 +366,9 @@
   base::Time::Exploded now_exploded;
   now.LocalExplode(&now_exploded);
 
-  features.set_time_of_the_day(ukm::GetExponentialBucketMinForCounts1000(
-      now_exploded.hour * 60 + now_exploded.minute));
+  features.set_time_of_the_day(ukm::GetLinearBucketMin(
+      static_cast<int64_t>(now_exploded.hour * 60 + now_exploded.minute),
+      kBucketSize));
   features.set_day_of_week(static_cast<UserChargingEvent::Features::DayOfWeek>(
       now_exploded.day_of_week));
   features.set_day_of_month(now_exploded.day_of_month);
@@ -247,10 +385,41 @@
   } else {
     features.set_device_mode(UserChargingEvent::Features::UNKNOWN_MODE);
   }
+
+  // Last charge related features. This logic relies on the fact that
+  // there will be at most one halt event because of |UpdatePastEvents()|.
+  bool halt_from_last_charge = false;
+  for (const auto& event : past_events_) {
+    if (IsHaltEvent(event)) {
+      halt_from_last_charge = true;
+      break;
+    }
+  }
+  features.set_halt_from_last_charge(halt_from_last_charge);
+
+  PastEvent last_charge_plugged_in;
+  PastEvent last_charge_unplugged;
+  std::tie(last_charge_plugged_in, last_charge_unplugged) =
+      GetLastChargeEvents();
+
+  if (!last_charge_plugged_in.has_time() || !last_charge_unplugged.has_time())
+    return;
+  features.set_time_since_last_charge(ukm::GetExponentialBucketMinForCounts1000(
+      now.ToDeltaSinceWindowsEpoch().InMinutes() -
+      last_charge_unplugged.time()));
+  features.set_duration_of_last_charge(
+      ukm::GetExponentialBucketMinForCounts1000(last_charge_unplugged.time() -
+                                                last_charge_plugged_in.time()));
+  features.set_battery_percentage_before_last_charge(
+      last_charge_plugged_in.battery_percent());
+  features.set_battery_percentage_of_last_charge(
+      last_charge_unplugged.battery_percent());
+  features.set_timezone_difference_from_last_charge(
+      (now.UTCMidnight() - now.LocalMidnight()).InHours() -
+      last_charge_unplugged.timezone());
 }
 
-void SmartChargingManager::LogEvent(
-    const UserChargingEvent::Event::Reason& reason) {
+void SmartChargingManager::LogEvent(const EventReason& reason) {
   UserChargingEvent proto;
   proto.mutable_event()->set_event_id(++event_id_);
   proto.mutable_event()->set_reason(reason);
@@ -261,6 +430,16 @@
   user_charging_event_for_test_ = proto;
 
   ukm_logger_->LogEvent(proto);
+
+  AddPastEvent(reason);
+  // Calls |UpdatePastEvents()| after |AddPastEvent()| to keep the number of
+  // saved past events to be minimum.
+  UpdatePastEvents();
+  if (profile_path_.has_value()) {
+    MaybeSaveToDisk(profile_path_.value());
+  } else {
+    // TODO(crbug.com/1028853): adds a UMA log here.
+  }
 }
 
 void SmartChargingManager::OnTimerFired() {
@@ -306,5 +485,123 @@
   return total_time;
 }
 
+void SmartChargingManager::MaybeLoadFromDisk(
+    const base::FilePath& profile_path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&LoadFromDisk, profile_path),
+      base::BindOnce(&SmartChargingManager::OnLoadProtoFromDiskComplete,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SmartChargingManager::MaybeSaveToDisk(const base::FilePath& profile_path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  blocking_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&SaveToDisk, past_events_, profile_path));
+}
+
+void SmartChargingManager::OnLoadProtoFromDiskComplete(
+    std::unique_ptr<PastChargingEvents> proto) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!proto) {
+    return;
+  }
+  loaded_from_disk_ = true;
+  for (const auto& event : proto.get()->events()) {
+    past_events_.emplace_back(event);
+  }
+}
+
+void SmartChargingManager::AddPastEvent(const EventReason& reason) {
+  // Since we use |past_events_| to calculate last charge information, we don't
+  // need to save if the reason is PERIODIC_LOG.
+  if (reason == UserChargingEvent::Event::PERIODIC_LOG)
+    return;
+  PastEvent new_event;
+  const base::Time now = base::Time::Now();
+  new_event.set_time(now.ToDeltaSinceWindowsEpoch().InMinutes());
+  if (battery_percent_.has_value())
+    new_event.set_battery_percent(static_cast<int>(battery_percent_.value()));
+  new_event.set_timezone((now.UTCMidnight() - now.LocalMidnight()).InHours());
+  new_event.set_reason(reason);
+  past_events_.emplace_back(new_event);
+}
+
+void SmartChargingManager::UpdatePastEvents() {
+  PastEvent last_charge_plugged_in;
+  PastEvent last_charge_unplugged;
+  PastEvent new_plugged_in;
+  PastEvent new_halt;
+
+  std::tie(last_charge_plugged_in, last_charge_unplugged) =
+      GetLastChargeEvents();
+  if (last_charge_unplugged.has_time()) {
+    // Gets the unplugged and halt(shutdown/suspend) events after the unplug (if
+    // any).
+    for (const auto& event : past_events_) {
+      if (event.time() > last_charge_unplugged.time()) {
+        if (event.reason() == UserChargingEvent::Event::CHARGER_PLUGGED_IN) {
+          new_plugged_in = event;
+        } else if (IsHaltEvent(event)) {
+          new_halt = event;
+        }
+      }
+    }
+  } else {
+    // Gets the last halt and plugged in event.
+    for (const auto& event : past_events_) {
+      if (event.reason() == UserChargingEvent::Event::CHARGER_PLUGGED_IN) {
+        new_plugged_in = event;
+      }
+      if (IsHaltEvent(event)) {
+        new_halt = event;
+      }
+    }
+  }
+
+  // Removes everything else.
+  past_events_.clear();
+
+  // Adds useful events back.
+  if (last_charge_plugged_in.has_time())
+    past_events_.emplace_back(last_charge_plugged_in);
+  if (last_charge_unplugged.has_time())
+    past_events_.emplace_back(last_charge_unplugged);
+  if (new_plugged_in.has_time())
+    past_events_.emplace_back(new_plugged_in);
+  if (new_halt.has_time())
+    past_events_.emplace_back(new_halt);
+}
+
+// Returns the last pair of plug/unplug events. If can't find the last pair,
+// return a pair of empty events.
+std::tuple<PastEvent, PastEvent> SmartChargingManager::GetLastChargeEvents() {
+  PastEvent plugged_in;
+  PastEvent unplugged;
+  PastEvent temp_plugged_in;
+  // There could be multiple events with CHARGER_PLUGGED_IN and/or
+  // CHARGER_UNPLUGGED. This function relies on the fact that all events are
+  // sorted by time.
+  for (const auto& event : past_events_) {
+    if (event.has_reason()) {
+      if (event.reason() == UserChargingEvent::Event::CHARGER_PLUGGED_IN) {
+        temp_plugged_in = event;
+      } else if (event.reason() ==
+                 UserChargingEvent::Event::CHARGER_UNPLUGGED) {
+        if (!temp_plugged_in.has_time())
+          continue;
+        // Updates the pair of results.
+        if (!plugged_in.has_time() ||
+            temp_plugged_in.time() != plugged_in.time()) {
+          plugged_in = temp_plugged_in;
+          unplugged = event;
+        }
+      }
+    }
+  }
+  return std::make_tuple(plugged_in, unplugged);
+}
+
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h
index 52ac00f..3e52aac 100644
--- a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h
+++ b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_CHROMEOS_POWER_SMART_CHARGING_SMART_CHARGING_MANAGER_H_
 #define CHROME_BROWSER_CHROMEOS_POWER_SMART_CHARGING_SMART_CHARGING_MANAGER_H_
 
+#include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -15,7 +16,10 @@
 #include "chrome/browser/chromeos/power/ml/boot_clock.h"
 #include "chrome/browser/chromeos/power/smart_charging/smart_charging_ukm_logger.h"
 #include "chrome/browser/chromeos/power/smart_charging/user_charging_event.pb.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/power/power_manager_client.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/session_manager/core/session_manager_observer.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "services/viz/public/mojom/compositing/video_detector_observer.mojom.h"
 #include "ui/base/user_activity/user_activity_detector.h"
@@ -27,16 +31,21 @@
 class RecentEventsCounter;
 }  // namespace ml
 
+using PastEvent = PastChargingEvents::Event;
+using EventReason = UserChargingEvent::Event::Reason;
+
 // SmartChargingManager logs battery percentage and other features related to
 // user charging events. It is currently used to log data and will be
 // extended to do inference in the future.
 class SmartChargingManager : public ui::UserActivityObserver,
                              public PowerManagerClient::Observer,
-                             public viz::mojom::VideoDetectorObserver {
+                             public viz::mojom::VideoDetectorObserver,
+                             public session_manager::SessionManagerObserver {
  public:
   SmartChargingManager(
       ui::UserActivityDetector* detector,
       mojo::PendingReceiver<viz::mojom::VideoDetectorObserver> receiver,
+      session_manager::SessionManager* session_manager,
       std::unique_ptr<base::RepeatingTimer> periodic_timer);
   ~SmartChargingManager() override;
   SmartChargingManager(const SmartChargingManager&) = delete;
@@ -73,6 +82,9 @@
   void OnVideoActivityStarted() override;
   void OnVideoActivityEnded() override;
 
+  // session_manager::SessionManagerObserver overrides:
+  void OnUserSessionStarted(bool is_primary_user) override;
+
  private:
   friend class SmartChargingManagerTest;
 
@@ -80,7 +92,7 @@
   void PopulateUserChargingEventProto(UserChargingEvent* proto);
 
   // Log the event.
-  void LogEvent(const UserChargingEvent::Event::Reason& reason);
+  void LogEvent(const EventReason& reason);
 
   // Called when the periodic timer triggers.
   void OnTimerFired();
@@ -97,16 +109,40 @@
   // minutes).
   base::TimeDelta DurationRecentVideoPlaying();
 
+  // Tries to load data from user profile path.
+  void MaybeLoadFromDisk(const base::FilePath& profile_path);
+
+  // Tries to save data to user profile path.
+  void MaybeSaveToDisk(const base::FilePath& profile_path);
+
+  // Calls after saving from disk completes.
+  void OnLoadProtoFromDiskComplete(std::unique_ptr<PastChargingEvents> proto);
+
+  // Adds a past events given it's reason to |past_events_|.
+  void AddPastEvent(const EventReason& reason);
+
+  // Updates and deletes events.
+  void UpdatePastEvents();
+
+  // Gets the "plug in" and "unplug" events of the last charge.
+  std::tuple<PastEvent, PastEvent> GetLastChargeEvents();
+
   ScopedObserver<ui::UserActivityDetector, ui::UserActivityObserver>
       user_activity_observer_{this};
 
   ScopedObserver<chromeos::PowerManagerClient,
                  chromeos::PowerManagerClient::Observer>
       power_manager_client_observer_{this};
+  ScopedObserver<session_manager::SessionManager,
+                 session_manager::SessionManagerObserver>
+      session_manager_observer_{this};
 
   // Timer to trigger periodically for logging data.
   const std::unique_ptr<base::RepeatingTimer> periodic_timer_;
 
+  // Checks if data is loaded from disk yet.
+  bool loaded_from_disk_ = false;
+
   // Helper to return TimeSinceBoot.
   ml::BootClock boot_clock_;
   int event_id_ = -1;
@@ -134,15 +170,18 @@
   // TODO(crbug.com/1028853): This is for testing only. Need to remove when ukm
   // logger is available.
   UserChargingEvent user_charging_event_for_test_;
+  std::vector<PastEvent> past_events_;
 
   base::Optional<double> battery_percent_;
   base::Optional<double> screen_brightness_percent_;
   base::Optional<power_manager::PowerSupplyProperties::ExternalPower>
       external_power_;
 
+  base::Optional<base::FilePath> profile_path_;
   const std::unique_ptr<SmartChargingUkmLogger> ukm_logger_;
 
   SEQUENCE_CHECKER(sequence_checker_);
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
   base::WeakPtrFactory<SmartChargingManager> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager_unittest.cc b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager_unittest.cc
index cebebbc9..6ba5829 100644
--- a/chrome/browser/chromeos/power/smart_charging/smart_charging_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/smart_charging/smart_charging_manager_unittest.cc
@@ -4,15 +4,32 @@
 
 #include "chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h"
 
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/clock.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/chromeos/power/smart_charging/user_charging_event.pb.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "components/session_manager/core/session_manager.h"
 #include "ui/events/keycodes/dom/dom_code.h"
 
 namespace chromeos {
 namespace power {
+namespace {
+PastEvent CreateEvent(int time,
+                      int battery_percent,
+                      int timezone,
+                      const EventReason& reason) {
+  PastEvent event;
+  event.set_time(time);
+  event.set_battery_percent(battery_percent);
+  event.set_timezone(timezone);
+  event.set_reason(reason);
+  return event;
+}
+}  // namespace
 
 class SmartChargingManagerTest : public ChromeRenderViewHostTestHarness {
  public:
@@ -36,7 +53,7 @@
         task_environment()->GetMainThreadTaskRunner());
     smart_charging_manager_ = std::make_unique<SmartChargingManager>(
         &user_activity_detector_, observer.InitWithNewPipeAndPassReceiver(),
-        std::move(periodic_timer));
+        &session_manager_, std::move(periodic_timer));
   }
 
   void TearDown() override {
@@ -112,6 +129,40 @@
     return smart_charging_manager_->DurationRecentVideoPlaying();
   }
 
+  std::tuple<PastEvent, PastEvent> GetLastChargeEvents() {
+    return smart_charging_manager_->GetLastChargeEvents();
+  }
+
+  void UpdatePastEvents() { smart_charging_manager_->UpdatePastEvents(); }
+
+  std::vector<PastEvent> GetPastEvents() {
+    return smart_charging_manager_->past_events_;
+  }
+
+  void SetBatteryPercentage(double battery_percent) {
+    smart_charging_manager_->battery_percent_ = battery_percent;
+  }
+
+  void AddEvent(const PastEvent& event) {
+    smart_charging_manager_->past_events_.emplace_back(event);
+  }
+
+  void AddPastEvent(const EventReason& reason) {
+    smart_charging_manager_->AddPastEvent(reason);
+  }
+
+  void MaybeSaveToDisk(const base::FilePath& profile_path) {
+    smart_charging_manager_->MaybeSaveToDisk(profile_path);
+  }
+
+  void MaybeLoadFromDisk(const base::FilePath& profile_path) {
+    smart_charging_manager_->MaybeLoadFromDisk(profile_path);
+  }
+
+  void ClearPastEvents() { smart_charging_manager_->past_events_.clear(); }
+
+  void Wait() { task_environment()->RunUntilIdle(); }
+
   const gfx::Point kEventLocation = gfx::Point(90, 90);
   const ui::MouseEvent kMouseEvent = ui::MouseEvent(ui::ET_MOUSE_MOVED,
                                                     kEventLocation,
@@ -122,6 +173,7 @@
 
  private:
   ui::UserActivityDetector user_activity_detector_;
+  session_manager::SessionManager session_manager_;
   std::unique_ptr<SmartChargingManager> smart_charging_manager_;
 };
 
@@ -281,5 +333,187 @@
   EXPECT_EQ(GetUserChargingEvent().features().device_mode(),
             UserChargingEvent::Features::LAPTOP_MODE);
 }
+
+TEST_F(SmartChargingManagerTest, GetLastChargeEventsNoLastCharges) {
+  AddEvent(CreateEvent(1, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(2, 20, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(3, 30, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(
+      CreateEvent(4, 40, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(5, 50, 11, UserChargingEvent::Event::SHUTDOWN));
+  AddEvent(CreateEvent(6, 60, 11, UserChargingEvent::Event::PERIODIC_LOG));
+
+  PastEvent plugged_in;
+  PastEvent unplugged;
+  std::tie(plugged_in, unplugged) = GetLastChargeEvents();
+  EXPECT_FALSE(plugged_in.has_time());
+  EXPECT_FALSE(unplugged.has_time());
+}
+
+TEST_F(SmartChargingManagerTest, GetLastChargeEventsComplex) {
+  AddEvent(CreateEvent(1, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(2, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(3, 20, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(4, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(5, 30, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(
+      CreateEvent(6, 20, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(7, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(8, 30, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(9, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(10, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(11, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(12, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(13, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(14, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(
+      CreateEvent(15, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(16, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(17, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(18, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(19, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(20, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(21, 40, 1, UserChargingEvent::Event::SHUTDOWN));
+  AddEvent(
+      CreateEvent(22, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+
+  PastEvent plugged_in;
+  PastEvent unplugged;
+  std::tie(plugged_in, unplugged) = GetLastChargeEvents();
+  EXPECT_TRUE(plugged_in.has_time());
+  EXPECT_TRUE(unplugged.has_time());
+  EXPECT_EQ(plugged_in.time(), 15);
+  EXPECT_EQ(unplugged.time(), 18);
+}
+
+TEST_F(SmartChargingManagerTest, UpdatePastEventsNoLastCharge) {
+  AddEvent(CreateEvent(1, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(2, 20, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(3, 30, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(
+      CreateEvent(4, 40, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(5, 50, 11, UserChargingEvent::Event::SHUTDOWN));
+  AddEvent(CreateEvent(6, 60, 11, UserChargingEvent::Event::PERIODIC_LOG));
+
+  UpdatePastEvents();
+
+  const std::vector<PastEvent> events = GetPastEvents();
+  EXPECT_EQ(events.size(), static_cast<unsigned long>(2));
+  EXPECT_EQ(events[0].time(), 4);
+  EXPECT_EQ(events[1].time(), 5);
+}
+
+TEST_F(SmartChargingManagerTest, UpdatePastEventsComplex) {
+  AddEvent(CreateEvent(1, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(2, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(3, 20, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(4, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(5, 30, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(
+      CreateEvent(6, 20, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(7, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(8, 30, 11, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(9, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(10, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(11, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(12, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(13, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(14, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(
+      CreateEvent(15, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(16, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(17, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(18, 20, 1, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(19, 10, 1, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(
+      CreateEvent(20, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+  AddEvent(CreateEvent(21, 40, 1, UserChargingEvent::Event::SHUTDOWN));
+  AddEvent(
+      CreateEvent(22, 40, 1, UserChargingEvent::Event::CHARGER_PLUGGED_IN));
+
+  UpdatePastEvents();
+
+  const std::vector<PastEvent> events = GetPastEvents();
+  EXPECT_EQ(events.size(), static_cast<unsigned long>(4));
+  EXPECT_EQ(events[0].time(), 15);
+  EXPECT_EQ(events[1].time(), 18);
+  EXPECT_EQ(events[2].time(), 22);
+  EXPECT_EQ(events[3].time(), 21);
+}
+
+TEST_F(SmartChargingManagerTest, AddPastEventTest) {
+  SetBatteryPercentage(15.5);
+  AddPastEvent(UserChargingEvent::Event::CHARGER_PLUGGED_IN);
+  SetBatteryPercentage(25.7);
+  AddPastEvent(UserChargingEvent::Event::CHARGER_UNPLUGGED);
+
+  const std::vector<PastEvent> events = GetPastEvents();
+  EXPECT_EQ(events.size(), static_cast<unsigned long>(2));
+  EXPECT_EQ(events[0].battery_percent(), 15);
+  EXPECT_EQ(events[0].reason(), UserChargingEvent::Event::CHARGER_PLUGGED_IN);
+  EXPECT_EQ(events[1].battery_percent(), 25);
+  EXPECT_EQ(events[1].reason(), UserChargingEvent::Event::CHARGER_UNPLUGGED);
+}
+
+TEST_F(SmartChargingManagerTest, LoadAndSave) {
+  AddEvent(CreateEvent(1, 10, 11, UserChargingEvent::Event::PERIODIC_LOG));
+  AddEvent(CreateEvent(2, 20, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+  AddEvent(CreateEvent(3, 30, 11, UserChargingEvent::Event::CHARGER_UNPLUGGED));
+
+  EXPECT_EQ(GetPastEvents().size(), static_cast<unsigned long>(3));
+
+  // Save to disk
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  ASSERT_TRUE(
+      base::CreateDirectory(temp_dir.GetPath().AppendASCII("smartcharging")));
+  const base::FilePath file_path =
+      temp_dir.GetPath().AppendASCII("smartcharging/past_charging_events.pb");
+
+  MaybeSaveToDisk(temp_dir.GetPath());
+  Wait();
+  ASSERT_TRUE(base::PathExists(file_path));
+
+  // Clear memory
+  ClearPastEvents();
+
+  // Now there is no past event on memory
+  EXPECT_EQ(GetPastEvents().size(), static_cast<unsigned long>(0));
+
+  // Load from disk
+  MaybeLoadFromDisk(temp_dir.GetPath());
+  Wait();
+
+  // Check the result
+  const std::vector<PastEvent> events = GetPastEvents();
+  EXPECT_EQ(events.size(), static_cast<unsigned long>(3));
+  EXPECT_EQ(events[0].time(), 1);
+  EXPECT_EQ(events[1].time(), 2);
+  EXPECT_EQ(events[2].time(), 3);
+}
+
+TEST_F(SmartChargingManagerTest, LastChargeRelatedFeatures) {
+  ReportPowerChangeEvent(power_manager::PowerSupplyProperties::AC, 23.0f);
+  FastForwardTimeBySecs(3600);
+  ReportPowerChangeEvent(power_manager::PowerSupplyProperties::DISCONNECTED,
+                         80.0f);
+  FastForwardTimeBySecs(600);
+  ReportShutdownEvent();
+  FastForwardTimeBySecs(1800);
+  ReportPowerChangeEvent(power_manager::PowerSupplyProperties::AC, 75.0f);
+
+  const auto features = GetUserChargingEvent().features();
+
+  EXPECT_TRUE(features.halt_from_last_charge());
+  EXPECT_EQ(features.time_since_last_charge(), 38);
+  EXPECT_EQ(features.duration_of_last_charge(), 58);
+  EXPECT_EQ(features.battery_percentage_before_last_charge(), 23);
+  EXPECT_EQ(features.battery_percentage_of_last_charge(), 80);
+}
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/smart_charging/user_charging_event.proto b/chrome/browser/chromeos/power/smart_charging/user_charging_event.proto
index 2e112a6..6a38a98 100644
--- a/chrome/browser/chromeos/power/smart_charging/user_charging_event.proto
+++ b/chrome/browser/chromeos/power/smart_charging/user_charging_event.proto
@@ -117,3 +117,21 @@
   optional Features features = 1;
   optional Event event = 2;
 }
+
+// PastChargingEvents contain a list of events that have information about "past
+// charging events". It will only store the plug/unplug pair of the last charge
+// and a recent plug/halt event if any.
+message PastChargingEvents {
+  message Event {
+    // Time of the event in minutes since Windows epoch.
+    optional int32 time = 1;
+    // Battery percentage of the device.
+    optional int32 battery_percent = 2;
+    // Timezone of the device.
+    optional int32 timezone = 3;
+    // Reason for the event.
+    optional UserChargingEvent.Event.Reason reason = 4;
+  }
+  // A list containing past charging events.
+  repeated Event events = 1;
+}
diff --git a/chrome/browser/devtools/device/tcp_device_provider.h b/chrome/browser/devtools/device/tcp_device_provider.h
index 66699dae..a15bca62 100644
--- a/chrome/browser/devtools/device/tcp_device_provider.h
+++ b/chrome/browser/devtools/device/tcp_device_provider.h
@@ -13,7 +13,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/host_port_pair.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
 
 class TCPDeviceProvider : public AndroidDeviceManager::DeviceProvider {
  public:
diff --git a/chrome/browser/devtools/device/usb/android_usb_device.h b/chrome/browser/devtools/device/usb/android_usb_device.h
index 3a66cdb..195aa9bb 100644
--- a/chrome/browser/devtools/device/usb/android_usb_device.h
+++ b/chrome/browser/devtools/device/usb/android_usb_device.h
@@ -19,7 +19,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/devtools/device/usb/usb_device_manager_helper.h"
 #include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/usb_device.mojom.h"
+#include "services/device/public/mojom/usb_device.mojom-forward.h"
 
 namespace base {
 class RefCountedBytes;
diff --git a/chrome/browser/download/android/download_media_parser.h b/chrome/browser/download/android/download_media_parser.h
index b178db6..b3a0b9a 100644
--- a/chrome/browser/download/android/download_media_parser.h
+++ b/chrome/browser/download/android/download_media_parser.h
@@ -20,7 +20,7 @@
 #include "chrome/browser/download/download_stats.h"
 #include "chrome/common/media_galleries/metadata_types.h"
 #include "chrome/services/media_gallery_util/public/cpp/media_parser_provider.h"
-#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h"
+#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom-forward.h"
 #include "media/base/media_log.h"
 #include "media/mojo/mojom/interface_factory.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/chrome/browser/download/android/local_media_data_source_factory.h b/chrome/browser/download/android/local_media_data_source_factory.h
index 36607d2f..624b9bf9 100644
--- a/chrome/browser/download/android/local_media_data_source_factory.h
+++ b/chrome/browser/download/android/local_media_data_source_factory.h
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/sequenced_task_runner.h"
 #include "chrome/services/media_gallery_util/public/cpp/safe_media_metadata_parser.h"
-#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h"
+#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom-forward.h"
 
 namespace base {
 class FilePath;
diff --git a/chrome/browser/engagement/BUILD.gn b/chrome/browser/engagement/BUILD.gn
index 1965296..2744f70 100644
--- a/chrome/browser/engagement/BUILD.gn
+++ b/chrome/browser/engagement/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "site_engagement_details.mojom",
-  ]
+  sources = [ "site_engagement_details.mojom" ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/engagement/site_engagement_score.h b/chrome/browser/engagement/site_engagement_score.h
index 832f27d..571ef65 100644
--- a/chrome/browser/engagement/site_engagement_score.h
+++ b/chrome/browser/engagement/site_engagement_score.h
@@ -14,8 +14,8 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/browser/engagement/site_engagement_details.mojom.h"
-#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
+#include "chrome/browser/engagement/site_engagement_details.mojom-forward.h"
+#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom-forward.h"
 #include "url/gurl.h"
 
 namespace base {
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index ac0689ea..53e015b9 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -12,6 +12,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 
 namespace extensions {
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index 9652923..02fbee6 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -9,7 +9,7 @@
 
 #include "chrome/browser/extensions/api/image_writer_private/operation.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
 #include "services/network/public/mojom/url_response_head.mojom-forward.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc
index 8cb52619..6b7620401 100644
--- a/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -146,6 +146,15 @@
     {"autoclick", ash::prefs::kAccessibilityAutoclickEnabled,
      APIPermission::kAccessibilityFeaturesRead,
      APIPermission::kAccessibilityFeaturesModify},
+    {"caretHighlight", ash::prefs::kAccessibilityCaretHighlightEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"cursorHighlight", ash::prefs::kAccessibilityCursorHighlightEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"focusHighlight", ash::prefs::kAccessibilityFocusHighlightEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
     {"highContrast", ash::prefs::kAccessibilityHighContrastEnabled,
      APIPermission::kAccessibilityFeaturesRead,
      APIPermission::kAccessibilityFeaturesModify},
@@ -164,6 +173,9 @@
     {"stickyKeys", ash::prefs::kAccessibilityStickyKeysEnabled,
      APIPermission::kAccessibilityFeaturesRead,
      APIPermission::kAccessibilityFeaturesModify},
+    {"switchAccess", ash::prefs::kAccessibilitySwitchAccessEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
     {"virtualKeyboard", ash::prefs::kAccessibilityVirtualKeyboardEnabled,
      APIPermission::kAccessibilityFeaturesRead,
      APIPermission::kAccessibilityFeaturesModify},
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
index 956b805c..196cbcd1 100644
--- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
+++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
@@ -28,17 +28,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
-#include "chromeos/tpm/stub_install_attributes.h"
-#include "components/account_id/account_id.h"
-#include "components/user_manager/scoped_user_manager.h"
-#include "components/user_manager/user.h"
-#endif
-
 using ::testing::_;
 using ::testing::Mock;
 using ::testing::SaveArg;
@@ -828,30 +817,12 @@
 
     TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
         prefs::kUnsafeEventsReportingEnabled, is_policy_enabled_);
-
-#if defined(OS_CHROMEOS)
-    auto user_manager = std::make_unique<chromeos::FakeChromeUserManager>();
-    const AccountId account_id(
-        AccountId::FromUserEmail(profile_->GetProfileUserName()));
-    const user_manager::User* user = user_manager->AddUserWithAffiliation(
-        account_id, /*is_affiliated=*/true);
-    chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user,
-                                                                      profile_);
-    user_manager->UserLoggedIn(account_id, user->username_hash(),
-                               /*browser_restart=*/false,
-                               /*is_child=*/false);
-    scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
-        std::move(user_manager));
-    profile_->ScopedCrosSettingsTestHelper()
-        ->InstallAttributes()
-        ->SetCloudManaged("domain.com", "device_id");
-    profile_->GetProfilePolicyConnector()->OverrideIsManagedForTesting(
-        is_manageable_);
-#endif
   }
 
   bool should_init() {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if defined(OS_CHROMEOS)
+    return false;
+#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
     return is_feature_flag_enabled_;
 #else
     return is_feature_flag_enabled_ && is_manageable_;
@@ -864,11 +835,6 @@
   const bool is_manageable_;
   const bool is_policy_enabled_;
   const bool is_authorized_;
-
-#if defined(OS_CHROMEOS)
- private:
-  std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
-#endif
 };
 
 TEST_P(SafeBrowsingIsRealtimeReportingEnabledTest,
@@ -887,7 +853,9 @@
       api::safe_browsing_private::OnPolicySpecifiedPasswordChanged::kEventName);
   event_router_->AddEventObserver(&event_observer);
 
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if defined(OS_CHROMEOS)
+  bool should_report = false;
+#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
   bool should_report =
       is_feature_flag_enabled_ && is_policy_enabled_ && is_authorized_;
 #else
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
index dffc6abc..0941bdce 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.h
@@ -14,8 +14,8 @@
 #include "content/public/browser/browser_or_resource_context.h"
 #include "content/public/common/resource_type.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/network/public/mojom/network_context.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
 #include "ui/base/page_transition_types.h"
 
 namespace content {
diff --git a/chrome/browser/extensions/chrome_extension_cookies.h b/chrome/browser/extensions/chrome_extension_cookies.h
index 10e2996..f1f0420 100644
--- a/chrome/browser/extensions/chrome_extension_cookies.h
+++ b/chrome/browser/extensions/chrome_extension_cookies.h
@@ -16,7 +16,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "services/network/cookie_settings.h"
-#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/cookie_manager.mojom-forward.h"
 #include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
 
 class Profile;
diff --git a/chrome/browser/extensions/chrome_url_request_util.cc b/chrome/browser/extensions/chrome_url_request_util.cc
index 91444396..c4913582 100644
--- a/chrome/browser/extensions/chrome_url_request_util.cc
+++ b/chrome/browser/extensions/chrome_url_request_util.cc
@@ -30,6 +30,7 @@
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_response_info.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/template_expressions.h"
diff --git a/chrome/browser/extensions/chrome_url_request_util.h b/chrome/browser/extensions/chrome_url_request_util.h
index 8911a342..2daf041b 100644
--- a/chrome/browser/extensions/chrome_url_request_util.h
+++ b/chrome/browser/extensions/chrome_url_request_util.h
@@ -10,7 +10,7 @@
 #include "content/public/common/resource_type.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
+#include "services/network/public/mojom/url_loader.mojom-forward.h"
 #include "ui/base/page_transition_types.h"
 
 class GURL;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c9f6515..95623055 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -460,6 +460,13 @@
     "expiry_milestone": 83
   },
   {
+    "name": "chromeos-video-decoder",
+    "owners": [ "chromeos-video-eng@google.com" ],
+    // This flag should expire once all VDA-based ChromeOS video decoders have
+    // been removed.
+    "expiry_milestone": 90
+  },
+  {
     "name": "clear-old-browsing-data",
     "owners": [ "dullweber" ],
     "expiry_milestone": 78
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 015ab80d..efaeae8 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3348,6 +3348,11 @@
 const char kCameraSystemWebAppDescription[] =
     "Run the Chrome Camera App as a System Web App.";
 
+const char kChromeosVideoDecoderName[] = "New Chrome OS Video Decoder";
+const char kChromeosVideoDecoderDescription[] =
+    "Enables the new Chrome OS video decoder pipeline for hardware accelerated"
+    "video decoding.";
+
 const char kCrOSContainerName[] = "Chrome OS Container";
 const char kCrOSContainerDescription[] =
     "Enable the use of Chrome OS Container utility.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index d279e99..46fa716 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1983,6 +1983,9 @@
 extern const char kCameraSystemWebAppName[];
 extern const char kCameraSystemWebAppDescription[];
 
+extern const char kChromeosVideoDecoderName[];
+extern const char kChromeosVideoDecoderDescription[];
+
 extern const char kCrOSContainerName[];
 extern const char kCrOSContainerDescription[];
 
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
index 40ae43b..f3c2c7b 100644
--- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
+++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h
@@ -12,7 +12,7 @@
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
 #include "extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h"
 #include "ppapi/buildflags/buildflags.h"
-#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
+#include "third_party/blink/public/mojom/permissions/permission_status.mojom-forward.h"
 
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/common/plugin.mojom.h"
diff --git a/chrome/browser/language/translate_frame_binder.h b/chrome/browser/language/translate_frame_binder.h
index 2aef699..99ae5f2 100644
--- a/chrome/browser/language/translate_frame_binder.h
+++ b/chrome/browser/language/translate_frame_binder.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_LANGUAGE_TRANSLATE_FRAME_BINDER_H_
 #define CHROME_BROWSER_LANGUAGE_TRANSLATE_FRAME_BINDER_H_
 
-#include "components/translate/content/common/translate.mojom.h"
+#include "components/translate/content/common/translate.mojom-forward.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 
 namespace content {
diff --git a/chrome/browser/lookalikes/lookalike_url_service.h b/chrome/browser/lookalikes/lookalike_url_service.h
index 2b6af091..aa5237c 100644
--- a/chrome/browser/lookalikes/lookalike_url_service.h
+++ b/chrome/browser/lookalikes/lookalike_url_service.h
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "chrome/browser/engagement/site_engagement_details.mojom.h"
+#include "chrome/browser/engagement/site_engagement_details.mojom-forward.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/url_formatter/url_formatter.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/media/BUILD.gn b/chrome/browser/media/BUILD.gn
index 667ea10..6afb72b 100644
--- a/chrome/browser/media/BUILD.gn
+++ b/chrome/browser/media/BUILD.gn
@@ -11,13 +11,9 @@
     "media_engagement_score_details.mojom",
   ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_origin",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_origin" ]
 }
 
 proto_library("media_engagement_preload_proto") {
-  sources = [
-    "media_engagement_preload.proto",
-  ]
+  sources = [ "media_engagement_preload.proto" ]
 }
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity_record.cc b/chrome/browser/media/router/providers/cast/mirroring_activity_record.cc
index 10ff6dd..6684ff5 100644
--- a/chrome/browser/media/router/providers/cast/mirroring_activity_record.cc
+++ b/chrome/browser/media/router/providers/cast/mirroring_activity_record.cc
@@ -51,10 +51,11 @@
   if (type_value &&
       type_value->GetString() ==
           cast_util::EnumToString<cast_channel::CastMessageType,
-                                  cast_channel::CastMessageType::kRpc>())
-    return mirroring::mojom::kWebRtcNamespace;
-  else
+                                  cast_channel::CastMessageType::kRpc>()) {
     return mirroring::mojom::kRemotingNamespace;
+  } else {
+    return mirroring::mojom::kWebRtcNamespace;
+  }
 }
 
 }  // namespace
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index e567dcd..386de8d9 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -68,6 +68,7 @@
 #include "components/metrics/cpu_metrics_provider.h"
 #include "components/metrics/demographic_metrics_provider.h"
 #include "components/metrics/drive_metrics_provider.h"
+#include "components/metrics/entropy_state_provider.h"
 #include "components/metrics/field_trials_provider.h"
 #include "components/metrics/gpu/gpu_metrics_provider.h"
 #include "components/metrics/metrics_log_uploader.h"
@@ -655,6 +656,9 @@
       std::make_unique<metrics::CPUMetricsProvider>());
 
   metrics_service_->RegisterMetricsProvider(
+      std::make_unique<metrics::EntropyStateProvider>(local_state));
+
+  metrics_service_->RegisterMetricsProvider(
       std::make_unique<metrics::ScreenInfoMetricsProvider>());
 
   metrics_service_->RegisterMetricsProvider(CreateFileMetricsProvider(
diff --git a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
index 2b021f1..bccff5e5 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client_unittest.cc
@@ -150,7 +150,7 @@
   size_t expected_providers = 3;
 
   // This is the number of metrics providers that are outside any #if macros.
-  expected_providers += 19;
+  expected_providers += 20;
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   expected_providers++;  // ExtensionsMetricsProvider.
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index e01da50..4334423 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -14,6 +14,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/guid.h"
 #include "base/location.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
@@ -59,6 +60,7 @@
 #include "content/public/test/simple_url_loader_test_helper.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "net/base/address_list.h"
 #include "net/base/filename_util.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/load_flags.h"
@@ -67,6 +69,7 @@
 #include "net/cookies/cookie_options.h"
 #include "net/cookies/cookie_util.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "net/http/http_response_headers.h"
 #include "net/reporting/reporting_policy.h"
 #include "net/ssl/ssl_config.h"
@@ -85,9 +88,11 @@
 #include "services/network/public/cpp/network_connection_tracker.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
 #include "services/network/public/mojom/network_service.mojom.h"
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/test_dns_util.h"
 #include "services/network/test/test_url_loader_client.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -104,6 +109,9 @@
 
 namespace {
 
+constexpr char kHostname[] = "foo.test";
+constexpr char kAddress[] = "5.8.13.21";
+
 const char kCacheRandomPath[] = "/cacherandom";
 
 // Path using a ControllableHttpResponse that's part of the test fixture.
@@ -236,6 +244,8 @@
     // Used in a bunch of proxy tests. Should not resolve.
     host_resolver()->AddSimulatedFailure("does.not.resolve.test");
 
+    host_resolver()->AddRule(kHostname, kAddress);
+
     controllable_http_response_ =
         std::make_unique<net::test_server::ControllableHttpResponse>(
             embedded_test_server(), kControllablePath);
@@ -1109,6 +1119,53 @@
   }
 }
 
+// Make sure that NetworkContexts have separate DNS caches.
+IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
+                       DnsCacheIsolation) {
+  net::NetworkIsolationKey network_isolation_key =
+      net::NetworkIsolationKey::CreateTransient();
+  net::HostPortPair host_port_pair(kHostname, 0);
+
+  // Resolve |host_port_pair|, which should succeed and put it in the
+  // NetworkContext's cache.
+  network::DnsLookupResult result =
+      network::BlockingDnsLookup(network_context(), host_port_pair,
+                                 nullptr /* params */, network_isolation_key);
+  EXPECT_EQ(net::OK, result.error);
+  ASSERT_TRUE(result.resolved_addresses.has_value());
+  ASSERT_EQ(1u, result.resolved_addresses->size());
+  EXPECT_EQ(kAddress,
+            result.resolved_addresses.value()[0].ToStringWithoutPort());
+
+  // Make a cache-only request for the same hostname, for each other network
+  // context, and make sure no result is returned.
+  ForEachOtherContext(
+      base::BindLambdaForTesting([&](NetworkContextType network_context_type) {
+        network::mojom::ResolveHostParametersPtr params =
+            network::mojom::ResolveHostParameters::New();
+        // Cache only lookup.
+        params->source = net::HostResolverSource::LOCAL_ONLY;
+        network::DnsLookupResult result = network::BlockingDnsLookup(
+            GetNetworkContextForContextType(network_context_type),
+            host_port_pair, std::move(params), network_isolation_key);
+        EXPECT_EQ(net::ERR_DNS_CACHE_MISS, result.error);
+      }));
+
+  // Do a cache-only lookup using the original network context, which should
+  // return the same result it initially did.
+  network::mojom::ResolveHostParametersPtr params =
+      network::mojom::ResolveHostParameters::New();
+  // Cache only lookup.
+  params->source = net::HostResolverSource::LOCAL_ONLY;
+  result = network::BlockingDnsLookup(network_context(), host_port_pair,
+                                      std::move(params), network_isolation_key);
+  EXPECT_EQ(net::OK, result.error);
+  ASSERT_TRUE(result.resolved_addresses.has_value());
+  ASSERT_EQ(1u, result.resolved_addresses->size());
+  EXPECT_EQ(kAddress,
+            result.resolved_addresses.value()[0].ToStringWithoutPort());
+}
+
 // Visits a URL with an HSTS header, and makes sure it is respected.
 IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, PRE_Hsts) {
   if (IsRestartStateWithInProcessNetworkService())
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 54b89bc..4033bb5 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
@@ -558,6 +558,19 @@
     public static final String VR_SHOULD_REGISTER_ASSETS_COMPONENT_ON_STARTUP =
             "should_register_vr_assets_component_on_startup";
 
+    /**
+     * Name of the shared preference for the version number of the dynamically loaded dex.
+     */
+    public static final String WEBAPK_EXTRACTED_DEX_VERSION =
+            "org.chromium.chrome.browser.webapps.extracted_dex_version";
+
+    /**
+     * Name of the shared preference for the Android OS version at the time that the dex was last
+     * extracted from Chrome's assets and optimized.
+     */
+    public static final String WEBAPK_LAST_SDK_VERSION =
+            "org.chromium.chrome.browser.webapps.last_sdk_version";
+
     /** Key for deferred recording of list of uninstalled WebAPK packages. */
     public static final String WEBAPK_UNINSTALLED_PACKAGES = "webapk_uninstalled_packages";
 
@@ -784,6 +797,8 @@
                 VARIATION_CACHED_BOTTOM_TOOLBAR,
                 VERIFIED_DIGITAL_ASSET_LINKS,
                 VR_SHOULD_REGISTER_ASSETS_COMPONENT_ON_STARTUP,
+                WEBAPK_EXTRACTED_DEX_VERSION,
+                WEBAPK_LAST_SDK_VERSION,
                 WEBAPK_UNINSTALLED_PACKAGES
         );
         // clang-format on
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index ac123ac..acd5fb9 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -71,7 +71,6 @@
 #include "media/mojo/services/video_decode_perf_history.h"
 #include "net/http/transport_security_state.h"
 #include "ppapi/buildflags/buildflags.h"
-#include "services/network/public/mojom/network_context.mojom.h"
 #include "storage/browser/database/database_tracker.h"
 
 #if defined(OS_ANDROID)
@@ -190,12 +189,6 @@
   ChromePluginServiceFilter::GetInstance()->UnregisterProfile(this);
 #endif
 
-  // Clears any data the network stack contains that may be related to the
-  // OTR session. Must be done before DestroyBrowserContextServices, since
-  // the NetworkContext is managed by one such service.
-  GetDefaultStoragePartition(this)->GetNetworkContext()->ClearHostCache(
-      nullptr, network::mojom::NetworkContext::ClearHostCacheCallback());
-
   FullBrowserTransitionManager::Get()->OnProfileDestroyed(this);
 
   // The SimpleDependencyManager should always be passed after the
diff --git a/chrome/browser/profiling_host/BUILD.gn b/chrome/browser/profiling_host/BUILD.gn
index 5470239..ea427aa 100644
--- a/chrome/browser/profiling_host/BUILD.gn
+++ b/chrome/browser/profiling_host/BUILD.gn
@@ -31,9 +31,7 @@
 source_set("profiling_browsertests") {
   testonly = true
 
-  sources = [
-    "memlog_browsertest.cc",
-  ]
+  sources = [ "memlog_browsertest.cc" ]
 
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc
new file mode 100644
index 0000000..2720c70
--- /dev/null
+++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc
@@ -0,0 +1,134 @@
+// 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/renderer_context_menu/quick_answers_menu_observer.h"
+
+#include <utility>
+
+#include "base/strings/utf_string_conversions.h"
+#include "build/branding_buildflags.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chromeos/components/quick_answers/quick_answers_model.h"
+#include "components/renderer_context_menu/render_view_context_menu_proxy.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/common/context_menu_params.h"
+
+namespace {
+
+using chromeos::quick_answers::QuickAnswer;
+using chromeos::quick_answers::QuickAnswersClient;
+using chromeos::quick_answers::QuickAnswersRequest;
+
+// TODO(llin): Update the placeholder after finalizing on the design.
+constexpr char kLoadingPlaceholder[] = "Loading...";
+constexpr char kNoResult[] = "See result in Assistant";
+
+}  // namespace
+
+QuickAnswersMenuObserver::QuickAnswersMenuObserver(
+    RenderViewContextMenuProxy* proxy)
+    : proxy_(proxy) {
+  auto* assistant_state = ash::AssistantState::Get();
+  if (assistant_state && proxy_ && proxy_->GetBrowserContext()) {
+    auto* browser_context = proxy_->GetBrowserContext();
+    if (browser_context->IsOffTheRecord())
+      return;
+
+    quick_answers_client_ = std::make_unique<QuickAnswersClient>(
+        content::BrowserContext::GetDefaultStoragePartition(browser_context)
+            ->GetURLLoaderFactoryForBrowserProcess()
+            .get(),
+        assistant_state, this);
+  }
+}
+
+QuickAnswersMenuObserver::~QuickAnswersMenuObserver() = default;
+
+void QuickAnswersMenuObserver::InitMenu(
+    const content::ContextMenuParams& params) {
+  if (!is_eligible_ || !proxy_ || !quick_answers_client_)
+    return;
+
+  if (params.input_field_type ==
+      blink::ContextMenuDataInputFieldType::kPassword)
+    return;
+
+  auto selected_text = base::UTF16ToUTF8(params.selection_text);
+  if (selected_text.empty())
+    return;
+
+    // Add Quick Answer Menu item.
+    // TODO(llin): Update the menu item after finalizing on the design.
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  proxy_->AddMenuItemWithIcon(IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+                              params.selection_text, kAssistantIcon);
+#else
+  proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+                      params.selection_text);
+#endif
+  proxy_->AddMenuItem(IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+                      base::UTF8ToUTF16(kLoadingPlaceholder));
+  proxy_->AddSeparator();
+
+  // Fetch Quick Answer.
+  QuickAnswersRequest request;
+  request.selected_text = selected_text;
+  quick_answers_client_->SendRequest(request);
+}
+
+bool QuickAnswersMenuObserver::IsCommandIdSupported(int command_id) {
+  return (command_id == IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY ||
+          command_id == IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER);
+}
+
+bool QuickAnswersMenuObserver::IsCommandIdChecked(int command_id) {
+  return false;
+}
+
+bool QuickAnswersMenuObserver::IsCommandIdEnabled(int command_id) {
+  return command_id == IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY;
+}
+
+void QuickAnswersMenuObserver::ExecuteCommand(int command_id) {
+  // TODO(llin): Implements Quick Answers click action.
+}
+
+void QuickAnswersMenuObserver::OnQuickAnswerReceived(
+    std::unique_ptr<QuickAnswer> quick_answer) {
+  if (quick_answer) {
+    proxy_->UpdateMenuItem(
+        IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+        /*enabled=*/false,
+        /*hidden=*/false,
+        /*title=*/
+        base::UTF8ToUTF16(quick_answer->primary_answer.empty()
+                              ? kNoResult
+                              : quick_answer->primary_answer));
+
+    if (!quick_answer->secondary_answer.empty()) {
+      proxy_->UpdateMenuItem(
+          IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+          /*enabled=*/true,
+          /*hidden=*/false,
+          /*title=*/base::UTF8ToUTF16(quick_answer->secondary_answer));
+    }
+  } else {
+    proxy_->UpdateMenuItem(IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+                           /*enabled=*/false,
+                           /*hidden=*/false,
+                           /*title=*/base::UTF8ToUTF16(kNoResult));
+  }
+}
+
+void QuickAnswersMenuObserver::OnEligibilityChanged(bool eligible) {
+  is_eligible_ = eligible;
+}
+
+void QuickAnswersMenuObserver::SetQuickAnswerClientForTesting(
+    std::unique_ptr<chromeos::quick_answers::QuickAnswersClient>
+        quick_answers_client) {
+  quick_answers_client_ = std::move(quick_answers_client);
+}
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h
new file mode 100644
index 0000000..9bef9f186
--- /dev/null
+++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.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_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
+#define CHROME_BROWSER_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
+
+#include <memory>
+#include <string>
+
+#include "chromeos/components/quick_answers/quick_answers_client.h"
+#include "components/renderer_context_menu/render_view_context_menu_observer.h"
+
+class RenderViewContextMenuProxy;
+
+// A class that implements the quick answers menu.
+class QuickAnswersMenuObserver
+    : public RenderViewContextMenuObserver,
+      public chromeos::quick_answers::QuickAnswersClient::QuickAnswersDelegate {
+ public:
+  QuickAnswersMenuObserver(const QuickAnswersMenuObserver&) = delete;
+  QuickAnswersMenuObserver& operator=(const QuickAnswersMenuObserver&) = delete;
+
+  explicit QuickAnswersMenuObserver(RenderViewContextMenuProxy* proxy);
+  ~QuickAnswersMenuObserver() override;
+
+  // RenderViewContextMenuObserver implementation.
+  void InitMenu(const content::ContextMenuParams& params) override;
+  bool IsCommandIdSupported(int command_id) override;
+  bool IsCommandIdChecked(int command_id) override;
+  bool IsCommandIdEnabled(int command_id) override;
+  void ExecuteCommand(int command_id) override;
+
+  // QuickAnswersDelegate implementation.
+  void OnQuickAnswerReceived(
+      std::unique_ptr<chromeos::quick_answers::QuickAnswer> answer) override;
+  void OnEligibilityChanged(bool eligible) override;
+
+  void SetQuickAnswerClientForTesting(
+      std::unique_ptr<chromeos::quick_answers::QuickAnswersClient>
+          quick_answers_client);
+
+ private:
+  // The interface to add a context-menu item and update it.
+  RenderViewContextMenuProxy* proxy_;
+
+  std::unique_ptr<chromeos::quick_answers::QuickAnswersClient>
+      quick_answers_client_;
+
+  // Whether the feature is enabled and all eligibility criterias are met (
+  // locale, consents, etc).
+  bool is_eligible_ = false;
+};
+
+#endif  // CHROME_BROWSER_RENDERER_CONTEXT_MENU_QUICK_ANSWERS_MENU_OBSERVER_H_
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc b/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
new file mode 100644
index 0000000..b196827
--- /dev/null
+++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc
@@ -0,0 +1,255 @@
+// 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/renderer_context_menu/quick_answers_menu_observer.h"
+
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/components/quick_answers/quick_answers_client.h"
+#include "chromeos/components/quick_answers/quick_answers_model.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using chromeos::quick_answers::QuickAnswer;
+using chromeos::quick_answers::QuickAnswersClient;
+using chromeos::quick_answers::QuickAnswersRequest;
+
+using testing::_;
+
+class MockQuickAnswersClient : public QuickAnswersClient {
+ public:
+  MockQuickAnswersClient(network::mojom::URLLoaderFactory* url_loader_factory,
+                         ash::AssistantState* assistant_state,
+                         QuickAnswersMenuObserver* delegate)
+      : QuickAnswersClient(url_loader_factory, assistant_state, delegate) {}
+
+  MockQuickAnswersClient(const MockQuickAnswersClient&) = delete;
+  MockQuickAnswersClient& operator=(const MockQuickAnswersClient&) = delete;
+
+  // QuickAnswersClient::QuickAnswersClient:
+  MOCK_METHOD1(SendRequest, void(const QuickAnswersRequest&));
+};
+
+MATCHER_P(QuickAnswersRequestEqual, quick_answers_request, "") {
+  return (arg.selected_text == quick_answers_request.selected_text);
+}
+
+// A test class for Quick Answers. This test should be a browser test because it
+//// accesses resources.
+class QuickAnswersMenuObserverTest : public InProcessBrowserTest {
+ public:
+  QuickAnswersMenuObserverTest() = default;
+
+  QuickAnswersMenuObserverTest(const QuickAnswersMenuObserverTest&) = delete;
+  QuickAnswersMenuObserverTest& operator=(const QuickAnswersMenuObserverTest&) =
+      delete;
+
+  // InProcessBrowserTest overrides:
+  void SetUpOnMainThread() override {
+    Reset(false);
+    mock_quick_answers_cient_ = std::make_unique<MockQuickAnswersClient>(
+        /*url_loader_factory=*/nullptr,
+        /*assistant_state=*/ash::AssistantState::Get(),
+        /*delegate=*/observer_.get());
+    observer_->OnEligibilityChanged(true);
+  }
+  void TearDownOnMainThread() override {
+    observer_.reset();
+    menu_.reset();
+  }
+
+  void Reset(bool incognito) {
+    observer_.reset();
+    menu_ = std::make_unique<MockRenderViewContextMenu>(incognito);
+    observer_ = std::make_unique<QuickAnswersMenuObserver>(menu_.get());
+    menu_->SetObserver(observer_.get());
+  }
+
+  void InitMenu() {
+    content::ContextMenuParams params;
+    static const base::string16 selected_text = base::ASCIIToUTF16("sel");
+    params.selection_text = selected_text;
+    observer_->InitMenu(params);
+  }
+
+  MockRenderViewContextMenu* menu() { return menu_.get(); }
+  QuickAnswersMenuObserver* observer() { return observer_.get(); }
+
+ protected:
+  void VerifyMenuItems(int index,
+                       int expected_command_id,
+                       const std::string& expected_title,
+                       bool enabled) {
+    MockRenderViewContextMenu::MockMenuItem item;
+    menu()->GetMenuItem(index, &item);
+    EXPECT_EQ(expected_command_id, item.command_id);
+    EXPECT_EQ(base::UTF8ToUTF16(expected_title), item.title);
+    EXPECT_EQ(enabled, item.enabled);
+    EXPECT_FALSE(item.hidden);
+  }
+
+  void MockQuickAnswerClient() {
+    std::unique_ptr<QuickAnswersRequest> expected_quick_answers_request =
+        std::make_unique<QuickAnswersRequest>();
+    expected_quick_answers_request->selected_text = "sel";
+    EXPECT_CALL(
+        *mock_quick_answers_cient_,
+        SendRequest(QuickAnswersRequestEqual(*expected_quick_answers_request)))
+        .Times(1);
+    observer_->SetQuickAnswerClientForTesting(
+        std::move(mock_quick_answers_cient_));
+  }
+
+  std::unique_ptr<QuickAnswersMenuObserver> observer_;
+  std::unique_ptr<MockQuickAnswersClient> mock_quick_answers_cient_;
+
+  std::unique_ptr<MockRenderViewContextMenu> menu_;
+};
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, PlaceHolderMenuItems) {
+  MockQuickAnswerClient();
+  InitMenu();
+
+  // Shows quick answers loading state.
+  ASSERT_EQ(3u, menu()->GetMenuSize());
+
+  // Verify the query menu item.
+  VerifyMenuItems(
+      /*index=*/0,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+      /*expected_title=*/"sel",
+      /*enabled=*/true);
+  // Verify the answer menu item.
+  VerifyMenuItems(
+      /*index=*/1,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+      /*expected_title=*/"Loading...",
+      /*enabled=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, PrimaryAnswerOnly) {
+  MockQuickAnswerClient();
+  InitMenu();
+
+  std::unique_ptr<QuickAnswer> quick_answer = std::make_unique<QuickAnswer>();
+  quick_answer->primary_answer = "primary answer";
+  observer_->OnQuickAnswerReceived(std::move(quick_answer));
+
+  // Verify that quick answer menu items is showing.
+  ASSERT_EQ(3u, menu()->GetMenuSize());
+
+  // Verify the query menu item.
+  VerifyMenuItems(
+      /*index=*/0,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+      /*expected_title=*/"sel",
+      /*enabled=*/true);
+
+  // Verify the answer menu item.
+  VerifyMenuItems(
+      /*index=*/1,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+      /*expected_title=*/"primary answer",
+      /*enabled=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, SecondaryAnswerOnly) {
+  MockQuickAnswerClient();
+  InitMenu();
+
+  std::unique_ptr<QuickAnswer> quick_answer = std::make_unique<QuickAnswer>();
+  quick_answer->secondary_answer = "secondary answer";
+  observer_->OnQuickAnswerReceived(std::move(quick_answer));
+
+  // Verify that quick answer menu items is showing.
+  ASSERT_EQ(3u, menu()->GetMenuSize());
+
+  // Verify the query menu item.
+  VerifyMenuItems(
+      /*index=*/0,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+      /*expected_title=*/"secondary answer",
+      /*enabled=*/true);
+
+  // Verify the answer menu item.
+  VerifyMenuItems(
+      /*index=*/1,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+      /*expected_title=*/"See result in Assistant",
+      /*enabled=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest,
+                       PrimaryAndSecondaryAnswer) {
+  MockQuickAnswerClient();
+  InitMenu();
+
+  std::unique_ptr<QuickAnswer> quick_answer = std::make_unique<QuickAnswer>();
+  quick_answer->primary_answer = "primary answer";
+  quick_answer->secondary_answer = "secondary answer";
+  observer_->OnQuickAnswerReceived(std::move(quick_answer));
+
+  // Verify that quick answer menu items is showing.
+  ASSERT_EQ(3u, menu()->GetMenuSize());
+
+  // Verify the query menu item.
+  VerifyMenuItems(
+      /*index=*/0,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+      /*expected_title=*/"secondary answer",
+      /*enabled=*/true);
+
+  // Verify the answer menu item.
+  VerifyMenuItems(
+      /*index=*/1,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+      /*expected_title=*/"primary answer",
+      /*enabled=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, NoAnswer) {
+  MockQuickAnswerClient();
+  InitMenu();
+
+  observer_->OnQuickAnswerReceived(nullptr);
+
+  // Verify that quick answer menu items is showing.
+  ASSERT_EQ(3u, menu()->GetMenuSize());
+
+  // Verify the query menu item.
+  VerifyMenuItems(
+      /*index=*/0,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_QUERY,
+      /*expected_title=*/"sel",
+      /*enabled=*/true);
+
+  // Verify the answer menu item.
+  VerifyMenuItems(
+      /*index=*/1,
+      /*command_id=*/IDC_CONTENT_CONTEXT_QUICK_ANSWERS_INLINE_ANSWER,
+      /*expected_title=*/"See result in Assistant",
+      /*enabled=*/false);
+}
+
+IN_PROC_BROWSER_TEST_F(QuickAnswersMenuObserverTest, FeatureIneligible) {
+  observer_->OnEligibilityChanged(false);
+
+  // Verify that quick answer client is not called to fetch result.
+  EXPECT_CALL(*mock_quick_answers_cient_, SendRequest(testing::_)).Times(0);
+  observer_->SetQuickAnswerClientForTesting(
+      std::move(mock_quick_answers_cient_));
+
+  InitMenu();
+
+  // Verify that no Quick Answer menu items shown.
+  ASSERT_EQ(0u, menu()->GetMenuSize());
+}
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index e369057..e70bae63 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -181,7 +181,7 @@
 
 #if BUILDFLAG(ENABLE_PRINTING)
 #include "chrome/browser/printing/print_view_manager_common.h"
-#include "components/printing/common/print_messages.h"
+#include "components/printing/common/print.mojom.h"
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 #include "chrome/browser/printing/print_preview_context_menu_observer.h"
@@ -198,6 +198,7 @@
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/intent_helper/open_with_menu.h"
 #include "chrome/browser/chromeos/arc/intent_helper/start_smart_selection_action_menu.h"
+#include "chrome/browser/renderer_context_menu/quick_answers_menu_observer.h"
 #endif
 
 using base::UserMetricsAction;
@@ -804,6 +805,8 @@
 void RenderViewContextMenu::InitMenu() {
   RenderViewContextMenuBase::InitMenu();
 
+  AppendQuickAnswersItems();
+
   if (content_type_->SupportsGroup(
           ContextMenuContentType::ITEM_GROUP_PASSWORD)) {
     AppendPasswordItems();
@@ -1331,6 +1334,18 @@
 #endif
 }
 
+void RenderViewContextMenu::AppendQuickAnswersItems() {
+#if defined(OS_CHROMEOS)
+  if (!quick_answers_menu_observer_) {
+    quick_answers_menu_observer_ =
+        std::make_unique<QuickAnswersMenuObserver>(this);
+  }
+
+  observers_.AddObserver(quick_answers_menu_observer_.get());
+  quick_answers_menu_observer_->InitMenu(params_);
+#endif
+}
+
 void RenderViewContextMenu::AppendSmartSelectionActionItems() {
 #if defined(OS_CHROMEOS)
   start_smart_selection_action_menu_observer_ =
@@ -2954,10 +2969,11 @@
 void RenderViewContextMenu::ExecPrint() {
 #if BUILDFLAG(ENABLE_PRINTING)
   if (params_.media_type != ContextMenuDataMediaType::kNone) {
-    RenderFrameHost* render_frame_host = GetRenderFrameHost();
-    if (render_frame_host) {
-      render_frame_host->Send(new PrintMsg_PrintNodeUnderContextMenu(
-          render_frame_host->GetRoutingID()));
+    RenderFrameHost* rfh = GetRenderFrameHost();
+    if (rfh) {
+      mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> remote;
+      rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote);
+      remote->PrintNodeUnderContextMenu();
     }
     return;
   }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index d5195d4..da5e511f 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -37,6 +37,7 @@
 class ClickToCallContextMenuObserver;
 class PrintPreviewContextMenuObserver;
 class Profile;
+class QuickAnswersMenuObserver;
 class SharedClipboardContextMenuObserver;
 class SpellingMenuObserver;
 class SpellingOptionsSubMenuObserver;
@@ -159,6 +160,7 @@
   void AppendOpenWithLinkItems();
   void AppendSmartSelectionActionItems();
   void AppendOpenInBookmarkAppLinkItems();
+  void AppendQuickAnswersItems();
   void AppendImageItems();
   void AppendAudioItems();
   void AppendCanvasItems();
@@ -275,6 +277,7 @@
   // An observer that handles smart text selection action items.
   std::unique_ptr<RenderViewContextMenuObserver>
       start_smart_selection_action_menu_observer_;
+  std::unique_ptr<QuickAnswersMenuObserver> quick_answers_menu_observer_;
 #endif
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/chrome/browser/resource_coordinator/BUILD.gn b/chrome/browser/resource_coordinator/BUILD.gn
index 48db683..4d26a15 100644
--- a/chrome/browser/resource_coordinator/BUILD.gn
+++ b/chrome/browser/resource_coordinator/BUILD.gn
@@ -15,9 +15,7 @@
 }
 
 proto_library("intervention_policy_database_proto") {
-  sources = [
-    "intervention_policy_database.proto",
-  ]
+  sources = [ "intervention_policy_database.proto" ]
 }
 
 source_set("tab_manager_features") {
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 9464bb4f..25bf80e36 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -93,15 +93,11 @@
     if (optimize_webui) {
       source = "bookmarks/bookmarks_resources_vulcanized.grd"
 
-      deps = [
-        "//chrome/browser/resources/bookmarks:build",
-      ]
+      deps = [ "//chrome/browser/resources/bookmarks:build" ]
     } else {
       source = "bookmarks/bookmarks_resources.grd"
 
-      deps = [
-        "//chrome/browser/resources/bookmarks:polymer3_elements",
-      ]
+      deps = [ "//chrome/browser/resources/bookmarks:polymer3_elements" ]
     }
 
     defines = chrome_grit_defines
@@ -124,9 +120,7 @@
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
     ]
 
-    deps = [
-      "//chrome/browser/resources/pdf/elements:polymer3_elements",
-    ]
+    deps = [ "//chrome/browser/resources/pdf/elements:polymer3_elements" ]
 
     defines = chrome_grit_defines
     if (enable_hangout_services_extension) {
@@ -153,15 +147,11 @@
     if (optimize_webui) {
       source = "history/history_resources_vulcanized.grd"
 
-      deps = [
-        "//chrome/browser/resources/history:build",
-      ]
+      deps = [ "//chrome/browser/resources/history:build" ]
     } else {
       source = "history/history_resources.grd"
 
-      deps = [
-        "//chrome/browser/resources/history:polymer3_elements",
-      ]
+      deps = [ "//chrome/browser/resources/history:polymer3_elements" ]
     }
 
     defines = chrome_grit_defines
@@ -218,9 +208,7 @@
       # The .grd contains references to generated files.
       source_is_generated = true
 
-      deps = [
-        "//chrome/browser/resources/settings:build",
-      ]
+      deps = [ "//chrome/browser/resources/settings:build" ]
       grit_flags = [
         "-E",
         "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -243,9 +231,7 @@
     if (optimize_webui) {
       source = "downloads/downloads_resources_vulcanized.grd"
 
-      deps = [
-        "//chrome/browser/resources/downloads:build",
-      ]
+      deps = [ "//chrome/browser/resources/downloads:build" ]
     } else {
       source = "downloads/downloads_resources.grd"
 
@@ -282,9 +268,7 @@
       # The .grd contains references to generated files.
       source_is_generated = true
 
-      deps = [
-        "//chrome/browser/resources/settings/chromeos:build",
-      ]
+      deps = [ "//chrome/browser/resources/settings/chromeos:build" ]
 
       grit_flags = [
         "-E",
@@ -312,9 +296,7 @@
     # The .grd contains references to generated files.
     source_is_generated = true
 
-    deps = [
-      "//chrome/browser/resources/welcome:polymer3_elements",
-    ]
+    deps = [ "//chrome/browser/resources/welcome:polymer3_elements" ]
     grit_flags = [
       "-E",
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -343,15 +325,11 @@
     if (optimize_webui) {
       source = "extensions/extensions_resources_vulcanized.grd"
 
-      deps = [
-        "//chrome/browser/resources/extensions:build",
-      ]
+      deps = [ "//chrome/browser/resources/extensions:build" ]
     } else {
       source = "extensions/extensions_resources.grd"
 
-      deps = [
-        "//chrome/browser/resources/extensions:polymer3_elements",
-      ]
+      deps = [ "//chrome/browser/resources/extensions:polymer3_elements" ]
     }
 
     defines = chrome_grit_defines
@@ -389,14 +367,10 @@
     if (optimize_webui) {
       source = "print_preview/print_preview_resources_vulcanized.grd"
 
-      deps = [
-        "//chrome/browser/resources/print_preview:build",
-      ]
+      deps = [ "//chrome/browser/resources/print_preview:build" ]
     } else {
       source = "print_preview/print_preview_resources.grd"
-      deps = [
-        "//chrome/browser/resources/print_preview/ui:polymer3_elements",
-      ]
+      deps = [ "//chrome/browser/resources/print_preview/ui:polymer3_elements" ]
     }
 
     defines = chrome_grit_defines
@@ -414,9 +388,7 @@
   grit("tab_strip_resources") {
     source = "tab_strip/tab_strip_resources.grd"
     defines = chrome_grit_defines
-    deps = [
-      "tab_strip:tab_strip_modules",
-    ]
+    deps = [ "tab_strip:tab_strip_modules" ]
     source_is_generated = true
     outputs = [
       "grit/tab_strip_resources.h",
@@ -472,9 +444,7 @@
 
 js2gtest("resources_unitjs_tests") {
   test_type = "webui"
-  sources = [
-    "gaia_auth_host/password_change_authenticator_test.unitjs",
-  ]
+  sources = [ "gaia_auth_host/password_change_authenticator_test.unitjs" ]
 
   # This has to be a gen_include, so it doesn't collide with other js2gtests
   gen_include_files = [ "//ui/webui/resources/js/cr.js" ]
@@ -490,7 +460,5 @@
 
 source_set("browser_tests_js") {
   testonly = true
-  deps = [
-    ":resources_unitjs_tests",
-  ]
+  deps = [ ":resources_unitjs_tests" ]
 }
diff --git a/chrome/browser/resources/about_nacl/BUILD.gn b/chrome/browser/resources/about_nacl/BUILD.gn
index d4080c4b..67a1b9e7b 100644
--- a/chrome/browser/resources/about_nacl/BUILD.gn
+++ b/chrome/browser/resources/about_nacl/BUILD.gn
@@ -6,9 +6,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":about_nacl",
-  ]
+  deps = [ ":about_nacl" ]
 }
 
 js_library("about_nacl") {
diff --git a/chrome/browser/resources/bluetooth_internals/BUILD.gn b/chrome/browser/resources/bluetooth_internals/BUILD.gn
index 3c64f9f..8dcc33cd 100644
--- a/chrome/browser/resources/bluetooth_internals/BUILD.gn
+++ b/chrome/browser/resources/bluetooth_internals/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/grit/grit_rule.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":bluetooth_internals",
-  ]
+  deps = [ ":bluetooth_internals" ]
 }
 
 js_library("bluetooth_internals") {
@@ -46,9 +44,7 @@
 }
 
 js_library("node_utils") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("page") {
@@ -86,7 +82,5 @@
     "-E",
     "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
   ]
-  deps = [
-    "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js",
-  ]
+  deps = [ "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js" ]
 }
diff --git a/chrome/browser/resources/bookmarks/BUILD.gn b/chrome/browser/resources/bookmarks/BUILD.gn
index a0b0f5d..0399fc3 100644
--- a/chrome/browser/resources/bookmarks/BUILD.gn
+++ b/chrome/browser/resources/bookmarks/BUILD.gn
@@ -29,9 +29,7 @@
     pak_file = bookmarks_pak_file
     out_folder = unpak_folder
 
-    deps = [
-      ":flattened_resources",
-    ]
+    deps = [ ":flattened_resources" ]
   }
 
   grit("flattened_resources") {
@@ -44,9 +42,7 @@
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
     ]
 
-    deps = [
-      ":polymer3_elements",
-    ]
+    deps = [ ":polymer3_elements" ]
     defines = chrome_grit_defines
     outputs = [
       "grit/bookmarks_resources.h",
@@ -193,7 +189,7 @@
     ":store",
     ":store_client",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_splitter:cr_splitter.m",
+    "//ui/webui/resources/cr_elements/cr_splitter:cr_splitter",
     "//ui/webui/resources/js:find_shortcut_behavior.m",
     "//ui/webui/resources/js:load_time_data.m",
   ]
@@ -240,9 +236,7 @@
 }
 
 js_library("dialog_focus_manager") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
 js_library("dnd_manager") {
@@ -381,15 +375,11 @@
 }
 
 js_library("types") {
-  deps = [
-    ":constants",
-  ]
+  deps = [ ":constants" ]
   externs_list = [ "$externs_path/chrome_extensions.js" ]
 }
 
 js_library("util") {
-  deps = [
-    ":types",
-  ]
+  deps = [ ":types" ]
   externs_list = [ "$externs_path/chrome_extensions.js" ]
 }
diff --git a/chrome/browser/resources/bookmarks/app.js b/chrome/browser/resources/bookmarks/app.js
index f085a0dd..3f90d04 100644
--- a/chrome/browser/resources/bookmarks/app.js
+++ b/chrome/browser/resources/bookmarks/app.js
@@ -6,7 +6,7 @@
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.m.js';
-import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.m.js';
+import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js';
 import './folder_node.js';
 import './list.js';
 import './router.js';
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
index 95900fb..dfae197 100644
--- a/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -46,9 +46,7 @@
   ]
   output_dir = "$root_gen_dir/chrome"
 
-  deps = [
-    "//media/capture/video/chromeos/mojom:cros_camera_js",
-  ]
+  deps = [ "//media/capture/video/chromeos/mojom:cros_camera_js" ]
 
   # The .grd contains references to generated files.
   source_is_generated = true
diff --git a/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
index 7e81852..87c9f49 100644
--- a/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
@@ -8,9 +8,7 @@
 assert(is_chromeos || is_chromecast)
 
 copy("braille_ime_manifest") {
-  sources = [
-    "manifest.json",
-  ]
+  sources = [ "manifest.json" ]
   outputs = [
     "$root_out_dir/resources/chromeos/accessibility/braille_ime/manifest.json",
   ]
@@ -31,7 +29,5 @@
 }
 
 js_library("main") {
-  deps = [
-    ":braille_ime",
-  ]
+  deps = [ ":braille_ime" ]
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
index 5bbeac71..c6715aa 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -154,6 +154,10 @@
       (announceText) => {
         ChromeVox.tts.speak(announceText.join(' '), QueueMode.FLUSH);
       });
+
+  // Set the darkScreen state to false, since the display will be on whenever
+  // ChromeVox starts.
+  sessionStorage.setItem('darkScreen', 'false');
 };
 
 Background.prototype = {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
index 52934c8..4f6589b 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -262,8 +262,7 @@
       });
     });
 
-// Flaky: https://crbug.com/1042673
-TEST_F('ChromeVoxBackgroundTest', 'DISABLED_SelectSingleBasic', function() {
+TEST_F('ChromeVoxBackgroundTest', 'SelectSingleBasic', function() {
   var mockFeedback = this.createMockFeedback();
   this.runWithLoadedTree(this.formsDoc, function() {
     mockFeedback.expectSpeech('apple', 'has pop up', 'Collapsed')
@@ -2345,3 +2344,16 @@
         mockFeedback.replay();
       });
 });
+
+TEST_F('ChromeVoxBackgroundTest', 'ToggleDarkScreen', function() {
+  var mockFeedback = this.createMockFeedback();
+  this.runWithLoadedTree('<div>Unimportant web content</div>', function() {
+    mockFeedback.call(doCmd('toggleDarkScreen'))
+        .expectSpeech('Darken screen')
+        .call(doCmd('toggleDarkScreen'))
+        .expectSpeech('Undarken screen')
+        .call(doCmd('toggleDarkScreen'))
+        .expectSpeech('Darken screen')
+        .replay();
+  });
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_data.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_data.js
index e019140..d0bd368 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_data.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/braille_command_data.js
@@ -143,9 +143,8 @@
   // Question.
   map([1, 4, 5, 6], 'toggleKeyboardHelp');
 
-  // All cells (with 7 as mod).
-  map([1, 2, 3, 4, 5, 6, 7], 'darkenScreen');
-  map([1, 2, 3, 4, 5, 6], 'undarkenScreen');
+  // All cells.
+  map([1, 2, 3, 4, 5, 6], 'toggleDarkScreen');
 
   // s.
   map([1, 2, 3, 4, 5], 'toggleSpeechOnOrOff');
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
index 11b3775..0053a00 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -234,13 +234,14 @@
       (new PanelCommand(PanelCommandType.UPDATE_NOTES)).send();
       localStorage['notifications_update_notification_shown'] = true;
       return false;
-    case 'darkenScreen':
-      chrome.accessibilityPrivate.darkenScreen(true);
-      new Output().format('@darken_screen').go();
-      return false;
-    case 'undarkenScreen':
-      chrome.accessibilityPrivate.darkenScreen(false);
-      new Output().format('@undarken_screen').go();
+    case 'toggleDarkScreen':
+      var oldState = sessionStorage.getItem('darkScreen');
+      var newState = (oldState === 'true') ? false : true;
+      sessionStorage.setItem('darkScreen', (newState) ? 'true' : 'false');
+      chrome.accessibilityPrivate.darkenScreen(newState);
+      new Output()
+          .format((newState) ? '@darken_screen' : '@undarken_screen')
+          .go();
       return false;
     case 'toggleSpeechOnOrOff':
       var state = ChromeVox.tts.toggleSpeechOnOrOff();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/keymaps/default_keymap.json b/chrome/browser/resources/chromeos/accessibility/chromevox/background/keymaps/default_keymap.json
index b80afd57..07a8f26 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/keymaps/default_keymap.json
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/keymaps/default_keymap.json
@@ -939,17 +939,7 @@
       }
     },
     {
-      "command": "darkenScreen",
-      "sequence": {
-        "cvoxModifier": true,
-        "keys": {
-          "keyCode": [118],
-          "shiftKey": [true]
-        }
-      }
-    },
-    {
-      "command": "undarkenScreen",
+      "command": "toggleDarkScreen",
       "sequence": {
         "cvoxModifier": true,
         "keys": {
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/command_store.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/command_store.js
index e39c040f..26191f8 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/command_store.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/command_store.js
@@ -383,9 +383,7 @@
     category: 'information'
   },
 
-  'undarkenScreen': {msgId: 'undarken_screen'},
-
-  'darkenScreen': {msgId: 'darken_screen'},
+  'toggleDarkScreen': {announce: false, msgId: 'toggle_dark_screen'},
 
   'toggleBrailleTable':
       {msgId: 'toggle_braille_table', category: 'help_commands'},
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
index 2dc862a..f9c1d37 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
@@ -3010,6 +3010,9 @@
       <message desc="Describes a command to turn the visual display on for accessibility undoing any previous request to turn off the visual display." name="IDS_CHROMEVOX_UNDARKEN_SCREEN">
         Undarken screen
       </message>
+      <message desc="Describes a command to toggle on/off the visual display for accessibility." name="IDS_CHROMEVOX_TOGGLE_DARK_SCREEN">
+        Toggle dark screen
+      </message>
       <message desc="Describes a command that turns text to speech feedback off." name="IDS_CHROMEVOX_SPEECH_OFF">
         Speech off
       </message>
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
index 3e3fe93..86610b8 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
@@ -121,6 +121,13 @@
   }
 
   /**
+   * Updates the focus ring locations in response to an automation event.
+   */
+  refreshFocusRings() {
+    this.focusRingManager_.setFocusNodes(this.node_, this.group_);
+  }
+
+  /**
    * Selects the current node.
    */
   selectCurrentNode() {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
index 10d475d..717dff5 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
@@ -20,6 +20,9 @@
 
     /** @private {boolean} */
     this.isGroup_ = SwitchAccessPredicate.isGroup(this.baseNode_, parent);
+
+    /** @private {function(chrome.automation.AutomationEvent)} */
+    this.locationChangedHandler_ = SwitchAccess.refreshFocusRings;
   }
 
   // ================= Getters and setters =================
@@ -118,6 +121,20 @@
   }
 
   /** @override */
+  onFocus() {
+    this.baseNode_.addEventListener(
+        chrome.automation.EventType.LOCATION_CHANGED,
+        this.locationChangedHandler_, false /* is_capture */);
+  }
+
+  /** @override */
+  onUnfocus() {
+    this.baseNode_.removeEventListener(
+        chrome.automation.EventType.LOCATION_CHANGED,
+        this.locationChangedHandler_, false /* is_capture */);
+  }
+
+  /** @override */
   performAction(action) {
     let ancestor;
     switch (action) {
@@ -191,6 +208,9 @@
 
     /** @private {!AutomationNode} */
     this.baseNode_ = baseNode;
+
+    /** @private {function(chrome.automation.AutomationEvent)} */
+    this.locationChangedHandler_ = SwitchAccess.refreshFocusRings;
   }
 
   // ================= Getters and setters =================
@@ -234,6 +254,20 @@
     return !!this.baseNode_.role && super.isValidGroup();
   }
 
+  /** @override */
+  onFocus() {
+    this.baseNode_.addEventListener(
+        chrome.automation.EventType.LOCATION_CHANGED,
+        this.locationChangedHandler_, false /* is_capture */);
+  }
+
+  /** @override */
+  onUnfocus() {
+    this.baseNode_.removeEventListener(
+        chrome.automation.EventType.LOCATION_CHANGED,
+        this.locationChangedHandler_, false /* is_capture */);
+  }
+
   // ================= Static methods =================
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
index e8b3ce8..178a606 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
@@ -341,4 +341,11 @@
       return this.navigationManager_.getTreeForDebugging(wholeTree);
     }
   }
+
+  static refreshFocusRings() {
+    const switchAccess = SwitchAccess.get();
+    if (switchAccess.navigationManager_) {
+      switchAccess.navigationManager_.refreshFocusRings();
+    }
+  }
 }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css
index af36f6f..4d61044 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css
@@ -46,7 +46,7 @@
   color: var(--google-grey-900);
   font-family: 'Google Sans', Roboto, sans-serif;
   font-size: 28px;
-  padding: 32px 0 16px 0;
+  padding: 20px 0 16px 0;
 }
 
 .sub-title {
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
index f529c8d5..e7e7cc85 100644
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
@@ -17,9 +17,7 @@
 }
 
 js_type_check("closure_compile") {
-  deps = [
-    ":bluetooth_pairing_dialog",
-  ]
+  deps = [ ":bluetooth_pairing_dialog" ]
 }
 
 js_library("bluetooth_pairing_dialog") {
diff --git a/chrome/browser/resources/chromeos/camera/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css
index d1a8bf5..075fffb 100644
--- a/chrome/browser/resources/chromeos/camera/src/css/main.css
+++ b/chrome/browser/resources/chromeos/camera/src/css/main.css
@@ -503,16 +503,16 @@
   display: none;
 }
 
-#camera,
-#settings,
-#gridsettings,
-#timersettings,
-#resolutionsettings,
-#photoresolutionsettings,
-#videoresolutionsettings,
-#expertsettings,
-#message-dialog,
-#warning {
+#view-camera,
+#view-settings,
+#view-grid-settings,
+#view-timer-settings,
+#view-resolution-settings,
+#view-photo-resolution-settings,
+#view-video-resolution-settings,
+#view-expert-settings,
+#view-message-dialog,
+#view-warning {
   bottom: 0;
   left: 0;
   opacity: 0;
@@ -523,51 +523,51 @@
   visibility: hidden;
 }
 
-body.camera #camera,
-body.settings #settings,
-body.gridsettings #gridsettings,
-body.timersettings #timersettings,
-body.resolutionsettings #resolutionsettings,
-body.photoresolutionsettings #photoresolutionsettings,
-body.videoresolutionsettings #videoresolutionsettings,
-body.expertsettings #expertsettings,
-body.message-dialog #message-dialog,
-body.warning #warning {
+body.view-camera #view-camera,
+body.view-settings #view-settings,
+body.view-grid-settings #view-grid-settings,
+body.view-timer-settings #view-timer-settings,
+body.view-resolution-settings #view-resolution-settings,
+body.view-photo-resolution-settings #view-photo-resolution-settings,
+body.view-video-resolution-settings #view-video-resolution-settings,
+body.view-expert-settings #view-expert-settings,
+body.view-message-dialog #view-message-dialog,
+body.view-warning #view-warning {
   opacity: 1;
   transition: opacity 100ms;
   visibility: visible;
 }
 
-body.gridsettings #gridsettings,
-body.timersettings #timersettings,
-body.resolutionsettings #resolutionsettings,
-body.photoresolutionsettings #photoresolutionsettings,
-body.videoresolutionsettings #videoresolutionsettings,
-body.expertsettings #expertsettings,
-body.settings #settings {
+body.view-grid-settings #view-grid-settings,
+body.view-timer-settings #view-timer-settings,
+body.view-resolution-settings #view-resolution-settings,
+body.view-photo-resolution-settings #view-photo-resolution-settings,
+body.view-video-resolution-settings #view-video-resolution-settings,
+body.view-expert-settings #view-expert-settings,
+body.view-settings #view-settings {
   /* Avoid flicking for transition between settings. */
   transition: opacity 0ms;
 }
 
-body.settings .left-stripe,
-body.gridsettings .left-stripe,
-body.gridsettings #settings,
-body.timersettings .left-stripe,
-body.timersettings #settings,
-body.resolutionsettings .left-stripe,
-body.resolutionsettings #settings,
-body.photoresolutionsettings .left-stripe,
-body.photoresolutionsettings #settings,
-body.photoresolutionsettings #resolutionsettings,
-body.videoresolutionsettings .left-stripe,
-body.videoresolutionsettings #settings,
-body.videoresolutionsettings #resolutionsettings,
-body.expertsettings .left-stripe,
-body.expertsettings #settings {
+body.view-settings .left-stripe,
+body.view-grid-settings .left-stripe,
+body.view-grid-settings #view-settings,
+body.view-timer-settings .left-stripe,
+body.view-timer-settings #view-settings,
+body.view-resolution-settings .left-stripe,
+body.view-resolution-settings #view-settings,
+body.view-photo-resolution-settings .left-stripe,
+body.view-photo-resolution-settings #view-settings,
+body.view-photo-resolution-settings #view-resolution-settings,
+body.view-video-resolution-settings .left-stripe,
+body.view-video-resolution-settings #view-settings,
+body.view-video-resolution-settings #view-resolution-settings,
+body.view-expert-settings .left-stripe,
+body.view-expert-settings #view-settings {
   opacity: 0;
 }
 
-#camera,
+#view-camera,
 #preview-wrapper {
   align-items: center;
   display: flex;
@@ -575,7 +575,7 @@
   overflow: hidden;
 }
 
-#camera {
+#view-camera {
   --big-icon: 48px;
   --bottom-line: 40px;
   --mode-item-height: 48px;
@@ -585,29 +585,29 @@
   --small-icon: 40px;
 }
 
-body.max-wnd #camera {
+body.max-wnd #view-camera {
   --bottom-line: 56px;
 }
 
-body.w-letterbox.w-letterbox-s #camera {
+body.w-letterbox.w-letterbox-s #view-camera {
   justify-content: flex-end;
 }
 
-body.w-letterbox.w-letterbox-m #camera,
-body.w-letterbox.w-letterbox-l #camera {
+body.w-letterbox.w-letterbox-m #view-camera,
+body.w-letterbox.w-letterbox-l #view-camera {
   justify-content: flex-start;
 }
 
-body.w-letterbox.w-letterbox-xl #camera {
+body.w-letterbox.w-letterbox-xl #view-camera {
   justify-content: center;
 }
 
-body:not(.w-letterbox) #camera {
+body:not(.w-letterbox) #view-camera {
   flex-direction: column;
   justify-content: center;
 }
 
-body:not(.w-letterbox).preview-vertical-dock #camera {
+body:not(.w-letterbox).preview-vertical-dock #view-camera {
   justify-content: flex-end;
 }
 
@@ -769,19 +769,19 @@
 }
 
 body.grid._3x3 #preview-grid-horizontal,
-body.gridsettings._3x3 #preview-grid-horizontal {
+body.view-grid-settings._3x3 #preview-grid-horizontal {
   height: 33.333%;
 }
 
 body.grid.golden #preview-grid-horizontal,
-body.gridsettings.golden #preview-grid-horizontal {
+body.view-grid-settings.golden #preview-grid-horizontal {
   height: 23.607%;
 }
 
 body.grid._4x4 #preview-grid-horizontal,
 body.grid._4x4 #preview-grid-horizontal::before,
-body.gridsettings._4x4 #preview-grid-horizontal,
-body.gridsettings._4x4 #preview-grid-horizontal::before {
+body.view-grid-settings._4x4 #preview-grid-horizontal,
+body.view-grid-settings._4x4 #preview-grid-horizontal::before {
   height: 50%;
 }
 
@@ -807,19 +807,19 @@
 }
 
 body.grid._3x3 #preview-grid-vertical,
-body.gridsettings._3x3 #preview-grid-vertical {
+body.view-grid-settings._3x3 #preview-grid-vertical {
   width: 33.333%;
 }
 
 body.grid.golden #preview-grid-vertical,
-body.gridsettings.golden #preview-grid-vertical {
+body.view-grid-settings.golden #preview-grid-vertical {
   width: 23.607%;
 }
 
 body.grid._4x4 #preview-grid-vertical,
 body.grid._4x4 #preview-grid-vertical::before,
-body.gridsettings._4x4 #preview-grid-vertical,
-body.gridsettings._4x4 #preview-grid-vertical::before {
+body.view-grid-settings._4x4 #preview-grid-vertical,
+body.view-grid-settings._4x4 #preview-grid-vertical::before {
   width: 50%;
 }
 
@@ -833,10 +833,10 @@
   transition: width 500ms, visibility 500ms;
 }
 
-body:not(.grid):not(.gridsettings) #preview-grid-horizontal,
-body:not(.grid):not(.gridsettings) #preview-grid-horizontal::before,
-body:not(.grid):not(.gridsettings) #preview-grid-vertical,
-body:not(.grid):not(.gridsettings) #preview-grid-vertical::before {
+body:not(.grid):not(.view-grid-settings) #preview-grid-horizontal,
+body:not(.grid):not(.view-grid-settings) #preview-grid-horizontal::before,
+body:not(.grid):not(.view-grid-settings) #preview-grid-vertical,
+body:not(.grid):not(.view-grid-settings) #preview-grid-vertical::before {
   visibility: hidden;
 }
 
@@ -1103,7 +1103,7 @@
   background-image: url(../images/settings_button_expand.svg);
 }
 
-#warning,
+#view-warning,
 .dialog {
   align-items: center;
   display: flex;
@@ -1111,12 +1111,12 @@
   z-index: 1;
 }
 
-#warning {
+#view-warning {
   background: black;
   color: white;
 }
 
-#warning #error-msg {
+#view-warning #error-msg {
   font-family: 'Roboto', sans-serif;
   font-size: 18px;
   line-height: 32px;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
index 59b7224..0978f7b 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
@@ -124,15 +124,11 @@
 }
 
 js_library("toast") {
-  deps = [
-    ":util",
-  ]
+  deps = [ ":util" ]
 }
 
 js_library("tooltip") {
-  deps = [
-    ":chrome_util",
-  ]
+  deps = [ ":chrome_util" ]
 }
 
 js_library("util") {
diff --git a/chrome/browser/resources/chromeos/camera/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js
index f7299d04..e250c5f 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/main.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/main.js
@@ -101,16 +101,18 @@
     util.setupI18nElements(document.body);
     this.setupToggles_();
 
+    const resolutionSettings = new ResolutionSettings(
+        this.infoUpdater_, this.photoPreferrer_, this.videoPreferrer_);
+
     // Set up views navigation by their DOM z-order.
     nav.setup([
       this.cameraView_,
       new MasterSettings(),
       new BaseSettings(ViewName.GRID_SETTINGS),
       new BaseSettings(ViewName.TIMER_SETTINGS),
-      new ResolutionSettings(
-          this.infoUpdater_, this.photoPreferrer_, this.videoPreferrer_),
-      new BaseSettings(ViewName.PHOTO_RESOLUTION_SETTINGS),
-      new BaseSettings(ViewName.VIDEO_RESOLUTION_SETTINGS),
+      resolutionSettings,
+      resolutionSettings.photoResolutionSettings,
+      resolutionSettings.videoResolutionSettings,
       new BaseSettings(ViewName.EXPERT_SETTINGS),
       new Warning(),
       new Dialog(ViewName.MESSAGE_DIALOG),
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js
index e6fead9..682df91 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js
@@ -436,7 +436,7 @@
   async setReprocessOption(deviceId, effect) {
     const device = await this.getDevice_(deviceId);
     const {status, blob} = await device.setReprocessOption(effect);
-    if (blob === null) {
+    if (blob === null || status !== 0) {
       throw new Error('Set reprocess failed: ' + status);
     }
     return blob;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/settings.js b/chrome/browser/resources/chromeos/camera/src/js/views/settings.js
index 2e4647ff..e8c0025d 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/settings.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/settings.js
@@ -3,16 +3,20 @@
 // found in the LICENSE file.
 
 // eslint-disable-next-line no-unused-vars
+import {assertInstanceof} from '../chrome_util.js';
+// eslint-disable-next-line no-unused-vars
 import {Camera3DeviceInfo} from '../device/camera3_device_info.js';
-import {PhotoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
-        VideoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
+import {
+  PhotoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
+  VideoConstraintsPreferrer,  // eslint-disable-line no-unused-vars
 } from '../device/constraints_preferrer.js';
 // eslint-disable-next-line no-unused-vars
 import {DeviceInfoUpdater} from '../device/device_info_updater.js';
 import * as nav from '../nav.js';
 import * as state from '../state.js';
-import {Resolution,      // eslint-disable-line no-unused-vars
-        ResolutionList,  // eslint-disable-line no-unused-vars
+import {
+  Resolution,      // eslint-disable-line no-unused-vars
+  ResolutionList,  // eslint-disable-line no-unused-vars
 } from '../type.js';
 import * as util from '../util.js';
 import {View, ViewName} from './view.js';
@@ -175,25 +179,41 @@
     this.videoPreferrer_ = videoPreferrer;
 
     /**
-     * @type {!HTMLElement}
-     * @private
+     * @const {!BaseSettings}
+     * @public
      */
-    this.resMenu_ = /** @type {!HTMLElement} */ (
-        document.querySelector('#resolutionsettings>div.menu'));
+    this.photoResolutionSettings =
+        new BaseSettings(ViewName.PHOTO_RESOLUTION_SETTINGS);
+
+    /**
+     * @const {!BaseSettings}
+     * @public
+     */
+    this.videoResolutionSettings =
+        new BaseSettings(ViewName.VIDEO_RESOLUTION_SETTINGS);
 
     /**
      * @type {!HTMLElement}
      * @private
      */
-    this.videoResMenu_ = /** @type {!HTMLElement} */ (
-        document.querySelector('#videoresolutionsettings>div.menu'));
+    this.resMenu_ =
+        assertInstanceof(this.root.querySelector('div.menu'), HTMLElement);
 
     /**
      * @type {!HTMLElement}
      * @private
      */
-    this.photoResMenu_ = /** @type {!HTMLElement} */ (
-        document.querySelector('#photoresolutionsettings>div.menu'));
+    this.videoResMenu_ = assertInstanceof(
+        this.videoResolutionSettings.root.querySelector('div.menu'),
+        HTMLElement);
+
+    /**
+     * @type {!HTMLElement}
+     * @private
+     */
+    this.photoResMenu_ = assertInstanceof(
+        this.photoResolutionSettings.root.querySelector('div.menu'),
+        HTMLElement);
 
     /**
      * @type {!HTMLElement}
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/view.js b/chrome/browser/resources/chromeos/camera/src/js/views/view.js
index f259bb8..41f9606 100644
--- a/chrome/browser/resources/chromeos/camera/src/js/views/view.js
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/view.js
@@ -9,16 +9,16 @@
  * @enum {string}
  */
 export const ViewName = {
-  CAMERA: 'camera',
-  EXPERT_SETTINGS: 'expertsettings',
-  GRID_SETTINGS: 'gridsettings',
-  MESSAGE_DIALOG: 'message-dialog',
-  PHOTO_RESOLUTION_SETTINGS: 'photoresolutionsettings',
-  RESOLUTION_SETTINGS: 'resolutionsettings',
-  SETTINGS: 'settings',
-  TIMER_SETTINGS: 'timersettings',
-  VIDEO_RESOLUTION_SETTINGS: 'videoresolutionsettings',
-  WARNING: 'warning',
+  CAMERA: 'view-camera',
+  EXPERT_SETTINGS: 'view-expert-settings',
+  GRID_SETTINGS: 'view-grid-settings',
+  MESSAGE_DIALOG: 'view-message-dialog',
+  PHOTO_RESOLUTION_SETTINGS: 'view-photo-resolution-settings',
+  RESOLUTION_SETTINGS: 'view-resolution-settings',
+  SETTINGS: 'view-settings',
+  TIMER_SETTINGS: 'view-timer-settings',
+  VIDEO_RESOLUTION_SETTINGS: 'view-video-resolution-settings',
+  WARNING: 'view-warning',
 };
 
 /* eslint-disable no-unused-vars */
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
index 702dab6..b9bfaea 100644
--- a/chrome/browser/resources/chromeos/camera/src/views/main.html
+++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -23,7 +23,7 @@
     <script type="module" src="../js/main.js"></script>
   </head>
   <body class="sound mirror mic _3x3">
-    <div id="camera">
+    <div id="view-camera">
       <div id="preview-wrapper">
         <img id="review-photo-result" class="preview-content"
           aria-hidden="true">
@@ -154,7 +154,7 @@
         <div id="timer-tick-msg"></div>
       </div>
     </div>
-    <div id="settings">
+    <div id="view-settings">
       <div class="menu">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -207,7 +207,7 @@
         </button>
       </div>
     </div>
-    <div id="gridsettings">
+    <div id="view-grid-settings">
       <div class="menu">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -230,7 +230,7 @@
         </label>
       </div>
     </div>
-    <div id="timersettings">
+    <div id="view-timer-settings">
       <div class="menu">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -249,7 +249,7 @@
         </label>
       </div>
     </div>
-    <div id="resolutionsettings">
+    <div id="view-resolution-settings">
       <div class="menu">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -306,7 +306,7 @@
         </button>
       </div>
     </div>
-    <div id="photoresolutionsettings">
+    <div id="view-photo-resolution-settings">
       <div class="menu" data-name="photores">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -314,7 +314,7 @@
         </div>
       </div>
     </div>
-    <div id="videoresolutionsettings">
+    <div id="view-video-resolution-settings">
       <div class="menu" data-name="videores">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -322,7 +322,7 @@
         </div>
       </div>
     </div>
-    <div id="expertsettings">
+    <div id="view-expert-settings">
       <div class="menu">
         <div class="menu-header circle">
           <button class="icon" tabindex="0" i18n-aria="back_button"></button>
@@ -343,10 +343,10 @@
       </div>
     </div>
     <div class="centered-overlay" id="spinner"></div>
-    <div id="warning">
+    <div id="view-warning">
       <div id="error-msg" aria-live="polite"></div>
     </div>
-    <div id="message-dialog" class="dialog">
+    <div id="view-message-dialog" class="dialog">
       <div class="dialog-popup" role="dialog" aria-labelledby="dialog-msg">
         <div class="dialog-msg dialog-msg-holder"></div>
         <div class="dialog-buttons">
diff --git a/chrome/browser/resources/chromeos/login/sync_consent.html b/chrome/browser/resources/chromeos/login/sync_consent.html
index b9ecae8..095d8d62 100644
--- a/chrome/browser/resources/chromeos/login/sync_consent.html
+++ b/chrome/browser/resources/chromeos/login/sync_consent.html
@@ -73,32 +73,24 @@
 
     <!-- Dialog used with SplitSettingsSync. -->
     <oobe-dialog id="osSyncConsentDialog" role="dialog" has-buttons
-        aria-label$="Sync and personalization options PLACEHOLDER"
+        aria-label$="[[i18nDynamic(locale, 'osSyncConsentTitle')]]"
         hidden>
       <hd-iron-icon slot="oobe-icon"
           icon1x="sync-consent-32:googleg" icon2x="sync-consent-64:googleg">
       </hd-iron-icon>
-      <!-- TODO(jamescook): When replacing the PLACEHOLDER strings add the
-            consent-description attribute to the h1 and the divs. The consent
-            auditor system requires real string IDs so it won't work with the
-            placeholders. -->
-      <h1 slot="title">
-        Sync and personalization options PLACEHOLDER
+      <h1 slot="title" consent-description>
+        [[i18nDynamic(locale, 'osSyncConsentTitle')]]
       </h1>
-      <div slot="subtitle">
-        Speedy, secure, stateless... feature description PLACEHOLDER
-      </div>
       <div slot="footer" class="layout vertical">
         <div class="overview-list-item flex layout horizontal center">
           <div class="overview-list-item-text flex layout vertical
               center-justified">
             <div role="heading" aria-level="2" class="overview-list-item-title"
-                id="enableOsSyncLabel">
-              Keep my Chromebook synced PLACEHOLDER
+                id="enableOsSyncLabel" consent-description>
+              [[i18nDynamic(locale, 'osSyncConsentToggleName')]]
             </div>
-            <div class="overview-list-item-description">
-              Chrome OS will sync your apps, settings, and Wi-Fi preferences to
-              keep your transition seamless. PLACEHOLDER
+            <div class="overview-list-item-description" consent-description>
+              [[i18nDynamic(locale, 'osSyncConsentToggleDescription')]]
             </div>
           </div>
           <cr-toggle id="enableOsSyncToggle" checked
@@ -110,7 +102,7 @@
         <oobe-text-button id="osSyncAcceptAndContinueButton"
             on-click="onOsSyncAcceptAndContinue_" class="focus-on-show" inverse>
           <div slot="text" consent-description consent-confirmation>
-            [[i18nDynamic(locale, 'syncConsentAcceptAndContinue')]]
+            [[i18nDynamic(locale, 'osSyncConsentContinue')]]
           </div>
         </oobe-text-button>
       </div>
diff --git a/chrome/browser/resources/chromeos/machine_learning/BUILD.gn b/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
index bca7700..a4f22168 100644
--- a/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
+++ b/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
@@ -14,9 +14,7 @@
 }
 
 js_library("test_model_tab") {
-  deps = [
-    ":machine_learning_internals_utils",
-  ]
+  deps = [ ":machine_learning_internals_utils" ]
 }
 
 js_library("machine_learning_internals") {
diff --git a/chrome/browser/resources/chromeos/network_ui/BUILD.gn b/chrome/browser/resources/chromeos/network_ui/BUILD.gn
index fafbe28d..6060563 100644
--- a/chrome/browser/resources/chromeos/network_ui/BUILD.gn
+++ b/chrome/browser/resources/chromeos/network_ui/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":network_ui",
-  ]
+  deps = [ ":network_ui" ]
 }
 
 js_library("network_ui") {
diff --git a/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn b/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
index ce57213..fea6290 100644
--- a/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
@@ -25,9 +25,7 @@
 }
 
 js_library("set_time_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
@@ -38,7 +36,5 @@
 }
 
 group("polymer3_elements") {
-  deps = [
-    ":set_time_dialog_module",
-  ]
+  deps = [ ":set_time_dialog_module" ]
 }
diff --git a/chrome/browser/resources/chromeos/sys_internals/BUILD.gn b/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
index 0e3b810..b365621 100644
--- a/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
+++ b/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
@@ -24,13 +24,9 @@
 }
 
 js_library("constants") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("types") {
-  deps = [
-    "line_chart:data_series",
-  ]
+  deps = [ "line_chart:data_series" ]
 }
diff --git a/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn b/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
index 817f99cb9..a43a8342 100644
--- a/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
+++ b/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
@@ -43,9 +43,7 @@
 }
 
 js_library("unit_label") {
-  deps = [
-    ":constants",
-  ]
+  deps = [ ":constants" ]
 }
 
 js_library("menu") {
@@ -57,9 +55,7 @@
 }
 
 js_library("data_series") {
-  deps = [
-    ":constants",
-  ]
+  deps = [ ":constants" ]
 }
 
 js_library("constants") {
diff --git a/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn b/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
index cda7844..642f6bd 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
+++ b/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
@@ -15,13 +15,9 @@
 zip_archiver_dir = "$root_out_dir/resources/chromeos/zip_archiver"
 
 copy("zip_archiver_css") {
-  sources = [
-    "css/passphrase.css",
-  ]
+  sources = [ "css/passphrase.css" ]
 
-  outputs = [
-    "$zip_archiver_dir/css/{{source_file_part}}",
-  ]
+  outputs = [ "$zip_archiver_dir/css/{{source_file_part}}" ]
 }
 
 copy("zip_archiver_html") {
@@ -30,9 +26,7 @@
     "html/passphrase.html",
   ]
 
-  outputs = [
-    "$zip_archiver_dir/html/{{source_file_part}}",
-  ]
+  outputs = [ "$zip_archiver_dir/html/{{source_file_part}}" ]
 }
 
 copy("zip_archiver_icons") {
@@ -44,9 +38,7 @@
     "icons/icon96.png",
   ]
 
-  outputs = [
-    "$zip_archiver_dir/icons/{{source_file_part}}",
-  ]
+  outputs = [ "$zip_archiver_dir/icons/{{source_file_part}}" ]
 }
 
 copy("zip_archiver_js") {
@@ -66,9 +58,7 @@
     "js/volume.js",
   ]
 
-  outputs = [
-    "$zip_archiver_dir/js/{{source_file_part}}",
-  ]
+  outputs = [ "$zip_archiver_dir/js/{{source_file_part}}" ]
 }
 
 copy("zip_archiver_root") {
@@ -76,9 +66,7 @@
           "//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)",
           "root_out_dir")
 
-  deps = [
-    "//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)",
-  ]
+  deps = [ "//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)" ]
 
   sources = [
     "$pexe_dir/zip_archiver_pnacl.pexe",
@@ -86,9 +74,7 @@
     "module.nmf",
   ]
 
-  outputs = [
-    "$zip_archiver_dir/{{source_file_part}}",
-  ]
+  outputs = [ "$zip_archiver_dir/{{source_file_part}}" ]
 }
 
 static_library("char_coding") {
@@ -97,7 +83,5 @@
     "cpp/char_coding.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn b/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
index 688f339..d925f456 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
@@ -55,16 +55,12 @@
     "//testing/gtest",
   ]
 
-  data = [
-    "//chrome/browser/resources/chromeos/zip_archiver/test/data/",
-  ]
+  data = [ "//chrome/browser/resources/chromeos/zip_archiver/test/data/" ]
 }
 
 if (is_nacl) {
   executable("zip_archiver_pnacl") {
-    sources = [
-      "module.cc",
-    ]
+    sources = [ "module.cc" ]
 
     deps = [
       ":zip_archiver_library",
diff --git a/chrome/browser/resources/components/BUILD.gn b/chrome/browser/resources/components/BUILD.gn
index 0834c1c..5f65e31 100644
--- a/chrome/browser/resources/components/BUILD.gn
+++ b/chrome/browser/resources/components/BUILD.gn
@@ -6,9 +6,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":components",
-  ]
+  deps = [ ":components" ]
 }
 
 js_library("components") {
diff --git a/chrome/browser/resources/discards/BUILD.gn b/chrome/browser/resources/discards/BUILD.gn
index 4c44f55..6cf5dd6e 100644
--- a/chrome/browser/resources/discards/BUILD.gn
+++ b/chrome/browser/resources/discards/BUILD.gn
@@ -82,18 +82,14 @@
     "graph_doc_template.html",
     "graph_tab_template.html",
   ]
-  outputs = [
-    "$target_gen_dir/graph_tab.js",
-  ]
+  outputs = [ "$target_gen_dir/graph_tab.js" ]
 
   args = rebase_path(outputs) + rebase_path([
                                               "graph_doc_template.html",
                                               "graph_doc.js",
                                             ]) +
          rebase_path([ "$target_gen_dir/graph_tab_template.js" ])
-  deps = [
-    ":graph_tab_module",
-  ]
+  deps = [ ":graph_tab_module" ]
 }
 
 # Action with a transparent name.
diff --git a/chrome/browser/resources/download_internals/BUILD.gn b/chrome/browser/resources/download_internals/BUILD.gn
index 615d902d..52b8603a 100644
--- a/chrome/browser/resources/download_internals/BUILD.gn
+++ b/chrome/browser/resources/download_internals/BUILD.gn
@@ -23,13 +23,9 @@
 }
 
 js_library("download_internals_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
 js_library("download_internals_visuals") {
-  deps = [
-    ":download_internals_browser_proxy",
-  ]
+  deps = [ ":download_internals_browser_proxy" ]
 }
diff --git a/chrome/browser/resources/engagement/BUILD.gn b/chrome/browser/resources/engagement/BUILD.gn
index 56a3ba2b..8fd5dfdc 100644
--- a/chrome/browser/resources/engagement/BUILD.gn
+++ b/chrome/browser/resources/engagement/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":site_engagement",
-  ]
+  deps = [ ":site_engagement" ]
 }
 
 js_library("site_engagement") {
diff --git a/chrome/browser/resources/history/BUILD.gn b/chrome/browser/resources/history/BUILD.gn
index 2da3970..5eb4934b 100644
--- a/chrome/browser/resources/history/BUILD.gn
+++ b/chrome/browser/resources/history/BUILD.gn
@@ -36,9 +36,7 @@
     pak_file = history_pak_file
     out_folder = unpak_folder
 
-    deps = [
-      ":flattened_resources",
-    ]
+    deps = [ ":flattened_resources" ]
   }
 
   grit("flattened_resources") {
@@ -51,9 +49,7 @@
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
     ]
 
-    deps = [
-      ":polymer3_elements",
-    ]
+    deps = [ ":polymer3_elements" ]
     defines = chrome_grit_defines
     outputs = [
       "grit/history_resources.h",
diff --git a/chrome/browser/resources/interventions_internals/BUILD.gn b/chrome/browser/resources/interventions_internals/BUILD.gn
index e6c48042..0b1deb57 100644
--- a/chrome/browser/resources/interventions_internals/BUILD.gn
+++ b/chrome/browser/resources/interventions_internals/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":index",
-  ]
+  deps = [ ":index" ]
 }
 
 js_library("index") {
diff --git a/chrome/browser/resources/local_ntp/BUILD.gn b/chrome/browser/resources/local_ntp/BUILD.gn
index 15edd04..77846905 100644
--- a/chrome/browser/resources/local_ntp/BUILD.gn
+++ b/chrome/browser/resources/local_ntp/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":local_ntp",
-  ]
+  deps = [ ":local_ntp" ]
 }
 
 js_library("local_ntp") {
@@ -23,8 +21,6 @@
     "utils.js",
     "voice.js",
   ]
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
   externs_list = [ "externs.js" ]
 }
diff --git a/chrome/browser/resources/local_state/BUILD.gn b/chrome/browser/resources/local_state/BUILD.gn
index 7b50454e..47ea708c 100644
--- a/chrome/browser/resources/local_state/BUILD.gn
+++ b/chrome/browser/resources/local_state/BUILD.gn
@@ -6,9 +6,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":local_state",
-  ]
+  deps = [ ":local_state" ]
 }
 
 js_library("local_state") {
diff --git a/chrome/browser/resources/management/icons.html b/chrome/browser/resources/management/icons.html
index e6a0757..2014aedf 100644
--- a/chrome/browser/resources/management/icons.html
+++ b/chrome/browser/resources/management/icons.html
@@ -8,6 +8,7 @@
       <g id="supervised-user"><path d="M11.99 2c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm3.61 6.34c1.07 0 1.93.86 1.93 1.93 0 1.07-.86 1.93-1.93 1.93-1.07 0-1.93-.86-1.93-1.93-.01-1.07.86-1.93 1.93-1.93zm-6-1.58c1.3 0 2.36 1.06 2.36 2.36 0 1.3-1.06 2.36-2.36 2.36s-2.36-1.06-2.36-2.36c0-1.31 1.05-2.36 2.36-2.36zm0 9.13v3.75c-2.4-.75-4.3-2.6-5.14-4.96 1.05-1.12 3.67-1.69 5.14-1.69.53 0 1.2.08 1.9.22-1.64.87-1.9 2.02-1.9 2.68zM11.99 20c-.27 0-.53-.01-.79-.04v-4.07c0-1.42 2.94-2.13 4.4-2.13 1.07 0 2.92.39 3.84 1.15-1.17 2.97-4.06 5.09-7.45 5.09z"></path></g>
       <g id="timelapse"><path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
       <g id="linux"><path d="M 6.9375 22.042969 C 3.867188 20.457031 1.886719 17.347656 1.824219 13.234375 C 1.527344 13.378906 1.1875 13.402344 0.800781 13.265625 C -0.3125 12.875 -0.0625 11.578125 0.34375 10.421875 C 0.683594 9.460938 1.835938 8.761719 2.402344 8.613281 C 3.71875 3.78125 6.804688 0 12 0 C 17.257812 0 20.367188 3.625 21.644531 8.628906 C 22.222656 8.796875 23.324219 9.484375 23.65625 10.421875 C 24.0625 11.578125 24.3125 12.875 23.199219 13.265625 C 22.8125 13.402344 22.472656 13.378906 22.175781 13.234375 C 22.117188 17.375 20.140625 20.472656 17.070312 22.046875 C 17.257812 22.191406 17.363281 22.375 17.363281 22.613281 C 17.363281 23.378906 17.75 24 14.898438 24 C 12.8125 24 12.457031 23.578125 12.417969 23.117188 C 12.28125 23.035156 12.140625 22.910156 12 22.910156 C 11.859375 22.910156 11.71875 23.042969 11.582031 23.128906 C 11.535156 23.582031 11.171875 24 9.101562 24 C 6.25 24 6.636719 23.378906 6.636719 22.613281 C 6.636719 22.371094 6.746094 22.183594 6.9375 22.042969 Z M 12 21.222656 C 17.929688 21.222656 20.070312 17.1875 20.070312 11.820312 C 20.070312 7.371094 18.125 3.28125 14.898438 2.597656 C 13.863281 2.378906 13.136719 4.761719 12 4.761719 C 10.863281 4.761719 10.035156 2.378906 9.101562 2.597656 C 5.863281 3.359375 3.929688 7.605469 3.929688 11.820312 C 3.929688 16.882812 6.070312 21.222656 12 21.222656 Z M 8.277344 9.324219 C 7.589844 9.324219 7.035156 8.789062 7.035156 8.132812 C 7.035156 7.476562 7.589844 6.941406 8.277344 6.941406 C 8.960938 6.941406 9.515625 7.476562 9.515625 8.132812 C 9.515625 8.789062 8.960938 9.324219 8.277344 9.324219 Z M 15.722656 9.324219 C 15.039062 9.324219 14.484375 8.789062 14.484375 8.132812 C 14.484375 7.476562 15.039062 6.941406 15.722656 6.941406 C 16.410156 6.941406 16.964844 7.476562 16.964844 8.132812 C 16.964844 8.789062 16.410156 9.324219 15.722656 9.324219 Z M 12.226562 9.964844 L 13.929688 10.683594 C 14.222656 10.804688 14.355469 11.132812 14.226562 11.414062 C 14.199219 11.46875 14.164062 11.519531 14.121094 11.5625 L 12.425781 13.308594 C 12.210938 13.535156 11.839844 13.546875 11.601562 13.339844 C 11.589844 13.332031 11.578125 13.320312 11.566406 13.308594 L 9.878906 11.558594 C 9.660156 11.332031 9.675781 10.980469 9.914062 10.773438 C 9.960938 10.734375 10.011719 10.703125 10.070312 10.679688 L 11.75 9.964844 C 11.898438 9.902344 12.074219 9.902344 12.226562 9.964844 Z M 12.226562 9.964844"></path></g>
+      <g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"></path></g>
 </if>
       <g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"></path><path d="M0 0h24v24H0z" fill="none"></path></g>
       <g id="public"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"></path></g>
diff --git a/chrome/browser/resources/management/management_browser_proxy.js b/chrome/browser/resources/management/management_browser_proxy.js
index 9c56140..3b06fb7 100644
--- a/chrome/browser/resources/management/management_browser_proxy.js
+++ b/chrome/browser/resources/management/management_browser_proxy.js
@@ -70,7 +70,10 @@
   DEVICE: 'device',
   LOGS: 'logs',
   PRINT: 'print',
-  CROSTINI: 'crostini'
+  CROSTINI: 'crostini',
+  USERNAME: 'username',
+  EXTENSION: 'extension',
+  ANDROID_APPLICATION: 'android application'
 };
 
 
diff --git a/chrome/browser/resources/management/management_ui.js b/chrome/browser/resources/management/management_ui.js
index 2ebce75..cb24354 100644
--- a/chrome/browser/resources/management/management_ui.js
+++ b/chrome/browser/resources/management/management_ui.js
@@ -225,6 +225,12 @@
         return 'cr:print';
       case DeviceReportingType.CROSTINI:
         return 'management:linux';
+      case DeviceReportingType.USERNAME:
+        return 'management:account-circle';
+      case DeviceReportingType.EXTENSION:
+        return 'cr:extension';
+      case DeviceReportingType.ANDROID_APPLICATION:
+        return 'management:android';
       default:
         return 'cr:computer';
     }
diff --git a/chrome/browser/resources/notifications_internals/BUILD.gn b/chrome/browser/resources/notifications_internals/BUILD.gn
index bd68968e..021f90a 100644
--- a/chrome/browser/resources/notifications_internals/BUILD.gn
+++ b/chrome/browser/resources/notifications_internals/BUILD.gn
@@ -21,7 +21,5 @@
 }
 
 js_library("notifications_internals_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
diff --git a/chrome/browser/resources/optimize_webui.gni b/chrome/browser/resources/optimize_webui.gni
index 7292b296..bfc1f5a 100644
--- a/chrome/browser/resources/optimize_webui.gni
+++ b/chrome/browser/resources/optimize_webui.gni
@@ -29,9 +29,7 @@
   node(target_name) {
     script = "//chrome/browser/resources/optimize_webui.py"
 
-    inputs = [
-      "//chrome/browser/resources/unpack_pak.py",
-    ]
+    inputs = [ "//chrome/browser/resources/unpack_pak.py" ]
 
     # This depfile is generated by optimize_webui.py
     depfile = "${target_gen_dir}/${target_name}.d"
@@ -93,13 +91,9 @@
   action(target_name) {
     script = "//chrome/browser/resources/unpack_pak.py"
 
-    inputs = [
-      "$target_gen_dir/${invoker.pak_file}",
-    ]
+    inputs = [ "$target_gen_dir/${invoker.pak_file}" ]
 
-    outputs = [
-      "$target_gen_dir/${invoker.out_folder}/unpack.stamp",
-    ]
+    outputs = [ "$target_gen_dir/${invoker.out_folder}/unpack.stamp" ]
 
     deps = invoker.deps
 
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn
index f0acff7..5dbfe48 100644
--- a/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -32,9 +32,7 @@
     pak_file = print_preview_pak_file
     out_folder = unpak_folder
 
-    deps = [
-      ":flattened_resources",
-    ]
+    deps = [ ":flattened_resources" ]
   }
 
   grit("flattened_resources") {
@@ -47,9 +45,7 @@
       "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
     ]
 
-    deps = [
-      "ui:polymer3_elements",
-    ]
+    deps = [ "ui:polymer3_elements" ]
     defines = chrome_grit_defines
     outputs = [
       "grit/print_preview_resources.h",
@@ -92,9 +88,7 @@
 }
 
 js_library("metrics") {
-  deps = [
-    ":native_layer",
-  ]
+  deps = [ ":native_layer" ]
 }
 
 js_library("cloud_print_interface") {
@@ -128,9 +122,7 @@
 }
 
 js_library("cloud_print_interface_native") {
-  deps = [
-    ":cloud_print_interface",
-  ]
+  deps = [ ":cloud_print_interface" ]
 }
 
 js_library("native_layer") {
@@ -145,7 +137,5 @@
 }
 
 js_library("dark_mode_behavior") {
-  deps = [
-    "//ui/webui/resources/js:assert.m",
-  ]
+  deps = [ "//ui/webui/resources/js:assert.m" ]
 }
diff --git a/chrome/browser/resources/print_preview/data/BUILD.gn b/chrome/browser/resources/print_preview/data/BUILD.gn
index 4720df3d..030f5a20 100644
--- a/chrome/browser/resources/print_preview/data/BUILD.gn
+++ b/chrome/browser/resources/print_preview/data/BUILD.gn
@@ -82,9 +82,7 @@
 }
 
 js_library("invitation") {
-  deps = [
-    ":destination",
-  ]
+  deps = [ ":destination" ]
 }
 
 js_library("destination") {
@@ -114,9 +112,7 @@
 }
 
 js_library("measurement_system") {
-  deps = [
-    "//ui/webui/resources/js:assert.m",
-  ]
+  deps = [ "//ui/webui/resources/js:assert.m" ]
 }
 
 js_library("model") {
diff --git a/chrome/browser/resources/print_preview/data/model.js b/chrome/browser/resources/print_preview/data/model.js
index ae8a524..4aee304 100644
--- a/chrome/browser/resources/print_preview/data/model.js
+++ b/chrome/browser/resources/print_preview/data/model.js
@@ -6,7 +6,7 @@
 import {isMac, isWindows} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
-import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BackgroundGraphicsModeRestriction, Policies} from '../native_layer.js';
 
diff --git a/chrome/browser/resources/print_preview/ui/BUILD.gn b/chrome/browser/resources/print_preview/ui/BUILD.gn
index fb256729..fc045b4 100644
--- a/chrome/browser/resources/print_preview/ui/BUILD.gn
+++ b/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -318,9 +318,7 @@
 }
 
 js_library("input_behavior") {
-  deps = [
-    "//ui/webui/resources/js:assert.m",
-  ]
+  deps = [ "//ui/webui/resources/js:assert.m" ]
 }
 
 js_library("select_behavior") {
diff --git a/chrome/browser/resources/print_preview/ui/destination_list.js b/chrome/browser/resources/print_preview/ui/destination_list.js
index a4628b90..370f9e1 100644
--- a/chrome/browser/resources/print_preview/ui/destination_list.js
+++ b/chrome/browser/resources/print_preview/ui/destination_list.js
@@ -61,6 +61,21 @@
         'destinations.*, searchQuery, loadingDestinations)',
   ],
 
+  /** @private {?function(Event)} */
+  boundUpdateHeight_: null,
+
+  /** @override */
+  attached() {
+    this.boundUpdateHeight_ = () => this.updateHeight_();
+    window.addEventListener('resize', this.boundUpdateHeight_);
+  },
+
+  /** @override */
+  detached() {
+    window.removeEventListener('resize', this.boundUpdateHeight_);
+    this.boundUpdateHeight_ = null;
+  },
+
   /**
    * This is a workaround to ensure that the iron-list correctly updates the
    * displayed destination information when the elements in the
@@ -74,6 +89,30 @@
     this.$.list.fire('iron-resize');
   },
 
+  /**
+   * @param {number=} numDestinations
+   * @private
+   */
+  updateHeight_(numDestinations) {
+    const count = numDestinations === undefined ?
+        this.matchingDestinations_.length :
+        numDestinations;
+
+    const maxDisplayedItems = this.offsetHeight / DESTINATION_ITEM_HEIGHT;
+    const isListFullHeight = maxDisplayedItems <= count;
+    const listHeight =
+        isListFullHeight ? this.offsetHeight : count * DESTINATION_ITEM_HEIGHT;
+
+    // Update the throbber and "No destinations" message.
+    this.hasDestinations_ = count > 0 || this.loadingDestinations;
+    this.throbberHidden_ =
+        !this.loadingDestinations || isListFullHeight || !this.hasDestinations_;
+
+    this.$.list.style.height = listHeight > DESTINATION_ITEM_HEIGHT ?
+        `${listHeight}px` :
+        `${DESTINATION_ITEM_HEIGHT}px`;
+  },
+
   /** @private */
   updateMatchingDestinations_() {
     if (this.destinations === undefined) {
@@ -85,20 +124,8 @@
             d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
         this.destinations.slice();
 
-    const maxDisplayedItems = this.offsetHeight / DESTINATION_ITEM_HEIGHT;
-    const isListFullHeight = maxDisplayedItems <= matchingDestinations.length;
-    const listHeight = isListFullHeight ?
-        this.offsetHeight :
-        matchingDestinations.length * DESTINATION_ITEM_HEIGHT;
-
-    // Update the throbber and "No destinations" message.
-    this.hasDestinations_ =
-        matchingDestinations.length > 0 || this.loadingDestinations;
-    this.throbberHidden_ =
-        !this.loadingDestinations || isListFullHeight || !this.hasDestinations_;
-
     // Update the height before updating the list.
-    this.$.list.style.height = `${listHeight}px`;
+    this.updateHeight_(matchingDestinations.length);
     this.updateList(
         'matchingDestinations_', destination => destination.key,
         matchingDestinations);
diff --git a/chrome/browser/resources/print_preview/ui/margin_control_container.js b/chrome/browser/resources/print_preview/ui/margin_control_container.js
index 5160bffa..8b7d976 100644
--- a/chrome/browser/resources/print_preview/ui/margin_control_container.js
+++ b/chrome/browser/resources/print_preview/ui/margin_control_container.js
@@ -194,13 +194,8 @@
     }
 
     this.resetMargins_ = true;
-    const marginsSetting = this.getSetting('margins');
-    if (marginsSetting.value === MarginsType.CUSTOM) {
-      // Set the margins value to default first.
-      this.setSetting('margins', MarginsType.DEFAULT);
-    }
-    // Reset custom margins so that the sticky value is not restored for the
-    // new paper size.
+    // Reset custom margins so that the sticky value is not restored for the new
+    // paper size.
     this.setSetting('customMargins', {});
   },
 
diff --git a/chrome/browser/resources/print_preview/ui/margins_settings.html b/chrome/browser/resources/print_preview/ui/margins_settings.html
index a5841a4d3e..f06afa2 100644
--- a/chrome/browser/resources/print_preview/ui/margins_settings.html
+++ b/chrome/browser/resources/print_preview/ui/margins_settings.html
@@ -4,8 +4,7 @@
   <span id="margins-label" slot="title">$i18n{marginsLabel}</span>
   <div slot="controls">
     <select class="md-select" aria-labelledby="margins-label"
-        disabled$="[[getMarginsSettingsDisabled_(disabled,
-                         settings.pagesPerSheet.value)]]"
+        disabled$="[[marginsDisabled_]]"
         value="{{selectedValue::change}}">
       <!-- The order of these options must match the natural order of their
       values, which come from MarginsType. -->
diff --git a/chrome/browser/resources/print_preview/ui/margins_settings.js b/chrome/browser/resources/print_preview/ui/margins_settings.js
index 07b79100..baf5f69 100644
--- a/chrome/browser/resources/print_preview/ui/margins_settings.js
+++ b/chrome/browser/resources/print_preview/ui/margins_settings.js
@@ -9,6 +9,7 @@
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {MarginsType} from '../data/margins.js';
+import {State} from '../data/state.js';
 
 import {SelectBehavior} from './select_behavior.js';
 import {SettingsBehavior} from './settings_behavior.js';
@@ -21,23 +22,66 @@
   behaviors: [SettingsBehavior, SelectBehavior],
 
   properties: {
-    disabled: Boolean,
+    disabled: {
+      type: Boolean,
+      observer: 'updateMarginsDisabled_',
+    },
+
+    /** @type {!State} */
+    state: {
+      type: Number,
+      observer: 'onStateChange_',
+    },
+
+    /** @private */
+    marginsDisabled_: Boolean,
 
     /** Mirroring the enum so that it can be used from HTML bindings. */
     MarginsTypeEnum: Object,
   },
 
-  observers: ['onMarginsSettingChange_(settings.margins.value)'],
+  observers: [
+    'onMarginsSettingChange_(settings.margins.value)',
+    'onMediaSizeOrLayoutChange_(' +
+        'settings.mediaSize.value, settings.layout.value)',
+    'onPagesPerSheetSettingChange_(settings.pagesPerSheet.value)'
+  ],
+
+  /** @private {boolean} */
+  loaded_: false,
 
   /** @override */
   ready() {
     this.MarginsTypeEnum = MarginsType;
   },
 
+  /** @private */
+  onStateChange_() {
+    if (this.state === State.READY) {
+      this.loaded_ = true;
+    }
+  },
+
+  /** @private */
+  onMediaSizeOrLayoutChange_() {
+    if (this.loaded_ &&
+        this.getSetting('margins').value === MarginsType.CUSTOM) {
+      this.setSetting('margins', MarginsType.DEFAULT);
+    }
+  },
+
   /**
-   * @param {*} newValue The new value of the margins setting.
+   * @param {number} newValue The new value of the pages per sheet setting.
    * @private
    */
+  onPagesPerSheetSettingChange_(newValue) {
+    if (newValue > 1) {
+      this.setSetting('margins', MarginsType.DEFAULT);
+    }
+    this.updateMarginsDisabled_();
+  },
+
+  /** @param {*} newValue The new value of the margins setting. */
   onMarginsSettingChange_(newValue) {
     this.selectedValue =
         /** @type {!MarginsType} */ (newValue).toString();
@@ -48,13 +92,10 @@
     this.setSetting('margins', parseInt(value, 10));
   },
 
-  /**
-   * @param {boolean} globallyDisabled Value of the |disabled| property.
-   * @param {number} pagesPerSheet Number of pages per sheet.
-   * @return {boolean} Whether the margins settings button should be disabled.
-   * @private
-   */
-  getMarginsSettingsDisabled_(globallyDisabled, pagesPerSheet) {
-    return globallyDisabled || pagesPerSheet > 1;
+  /** @private */
+  updateMarginsDisabled_() {
+    this.marginsDisabled_ =
+        /** @type {number} */ (this.getSettingValue('pagesPerSheet')) > 1 ||
+        this.disabled;
   },
 });
diff --git a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
index 5d792b7..9c5d692 100644
--- a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
+++ b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
@@ -32,7 +32,6 @@
    */
   onPagesPerSheetSettingChange_(newValue) {
     this.selectedValue = /** @type {number} */ (newValue).toString();
-    this.setSetting('margins', MarginsType.DEFAULT);
   },
 
   /** @param {string} value The new select value. */
diff --git a/chrome/browser/resources/print_preview/ui/sidebar.html b/chrome/browser/resources/print_preview/ui/sidebar.html
index f370c61..f7d5585 100644
--- a/chrome/browser/resources/print_preview/ui/sidebar.html
+++ b/chrome/browser/resources/print_preview/ui/sidebar.html
@@ -90,7 +90,7 @@
         hidden$="[[!settings.pagesPerSheet.available]]"
         class="settings-section">
     </print-preview-pages-per-sheet-settings>
-    <print-preview-margins-settings settings="[[settings]]"
+    <print-preview-margins-settings settings="[[settings]]" state="[[state]]"
         disabled="[[controlsDisabled_]]"
         hidden$="[[!settings.margins.available]]"
         class="settings-section">
diff --git a/chrome/browser/resources/quota_internals/BUILD.gn b/chrome/browser/resources/quota_internals/BUILD.gn
index 84aa0b4..64a65073 100644
--- a/chrome/browser/resources/quota_internals/BUILD.gn
+++ b/chrome/browser/resources/quota_internals/BUILD.gn
@@ -23,9 +23,7 @@
 }
 
 js_library("message_dispatcher") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 grit("quota_internals_resources") {
diff --git a/chrome/browser/resources/reset_password/BUILD.gn b/chrome/browser/resources/reset_password/BUILD.gn
index f00ec67..8f9b1c85 100644
--- a/chrome/browser/resources/reset_password/BUILD.gn
+++ b/chrome/browser/resources/reset_password/BUILD.gn
@@ -6,9 +6,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":reset_password",
-  ]
+  deps = [ ":reset_password" ]
 }
 
 js_library("reset_password") {
diff --git a/chrome/browser/resources/sandbox_internals/BUILD.gn b/chrome/browser/resources/sandbox_internals/BUILD.gn
index 121a5e8f..edf3d6e6 100644
--- a/chrome/browser/resources/sandbox_internals/BUILD.gn
+++ b/chrome/browser/resources/sandbox_internals/BUILD.gn
@@ -6,14 +6,10 @@
 
 js_type_check("closure_compile") {
   if (is_win) {
-    deps = [
-      ":sandbox_internals_win",
-    ]
+    deps = [ ":sandbox_internals_win" ]
   }
   if (is_android || is_linux) {
-    deps = [
-      ":sandbox_internals",
-    ]
+    deps = [ ":sandbox_internals" ]
   }
 }
 
diff --git a/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js b/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
index 20024ac..3797fb8 100644
--- a/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
+++ b/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
@@ -7,7 +7,8 @@
  *   processId: number,
  *   processType: string,
  *   name: string,
- *   metricsName: string
+ *   metricsName: string,
+ *   sandboxType: string
  * }}
  */
 let BrowserHostProcess;
@@ -58,16 +59,17 @@
  * @param {number} pid
  * @param {string} type
  * @param {string} name
+ * @param {string} sandbox
  * @param {PolicyDiagnostic} policy
  */
-function addRowForProcess(pid, type, name, policy) {
+function addRowForProcess(pid, type, name, sandbox, policy) {
   if (policy) {
     addRow([
-      pid, type, name, policy.lockdownLevel, policy.desiredIntegrityLevel,
-      policy.platformMitigations
+      pid, type, name, sandbox, policy.lockdownLevel,
+      policy.desiredIntegrityLevel, policy.platformMitigations
     ]);
   } else {
-    addRow([pid, type, name, 'Not Sandboxed', '', '']);
+    addRow([pid, type, name, 'Not Sandboxed', '', '', '']);
   }
 }
 
@@ -83,19 +85,22 @@
   }
 
   // Titles.
-  addRow(['Process', 'Type', 'Name', 'Sandbox', 'Integrity', 'Mitigations']);
+  addRow([
+    'Process', 'Type', 'Name', 'Sandbox', 'Lockdown', 'Integrity', 'Mitigations'
+  ]);
 
   // Browser Processes.
   for (const process of results.browser) {
     const pid = process.processId;
     const name = process.name || process.metricsName;
-    addRowForProcess(pid, process.processType, name, policies.get(pid));
+    addRowForProcess(
+        pid, process.processType, name, process.sandboxType, policies.get(pid));
   }
 
   // Renderer Processes.
   for (const process of results.renderer) {
     const pid = process.processId;
-    addRowForProcess(pid, 'Renderer', '', policies.get(pid));
+    addRowForProcess(pid, 'Renderer', '', 'Renderer', policies.get(pid));
   }
 
   // Raw Diagnostics.
diff --git a/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn
index 5eb69540..e0ab9716 100644
--- a/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn
@@ -12,9 +12,7 @@
 }
 
 js_library("google_assistant_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/chromeos/localized_link/BUILD.gn b/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn
index 092ab03..c480094 100644
--- a/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn
@@ -5,13 +5,9 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":localized_link",
-  ]
+  deps = [ ":localized_link" ]
 }
 
 js_library("localized_link") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
diff --git a/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
index c4ae127b..84cb81f6 100644
--- a/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
@@ -5,13 +5,10 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":os_privacy_page",
-  ]
+  deps = [ ":os_privacy_page" ]
 }
 
 js_library("os_privacy_page") {
-  deps = [
-    "//chrome/browser/resources/settings/controls:settings_toggle_button",
-  ]
+  deps =
+      [ "//chrome/browser/resources/settings/controls:settings_toggle_button" ]
 }
diff --git a/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
index 3a3d3ef5..dc0592c 100644
--- a/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
@@ -29,8 +29,6 @@
 }
 
 js_library("os_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/chromeos/os_toolbar/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
index 4b5035459..9c449624 100644
--- a/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
@@ -5,13 +5,10 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":os_toolbar",
-  ]
+  deps = [ ":os_toolbar" ]
 }
 
 js_library("os_toolbar") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field",
-  ]
+  deps =
+      [ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field" ]
 }
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
index 66be7bc1..7dfde636 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.js
@@ -88,7 +88,8 @@
       this.addWebUIListener(
           'security-keys-bio-enroll-error', this.onError_.bind(this));
       this.addWebUIListener(
-          'security-keys-bio-enroll-status', this.onEnrolling_.bind(this));
+          'security-keys-bio-enroll-status',
+          this.onEnrollmentSample_.bind(this));
       this.browserProxy_ =
           settings.SecurityKeysBioEnrollProxyImpl.getInstance();
       this.browserProxy_.startBioEnroll().then(() => {
@@ -195,50 +196,68 @@
       this.dialogPage_ = BioEnrollDialogPage.ENROLL;
 
       this.browserProxy_.startEnrolling().then(response => {
-        this.onEnrolling_(response);
+        this.onEnrollmentComplete_(response);
       });
     },
 
     /**
      * @private
-     * @param {!settings.EnrollmentStatus} response
+     * @param {!settings.SampleResponse} response
      */
-    onEnrolling_(response) {
+    onEnrollmentSample_(response) {
+      if (response.status != settings.SampleStatus.OK) {
+        this.progressArcLabel_ =
+            this.i18n('securityKeysBioEnrollmentTryAgainLabel');
+        this.fire('iron-announce', {text: this.progressArcLabel_});
+        return;
+      }
+
+      this.progressArcLabel_ =
+          this.i18n('securityKeysBioEnrollmentEnrollingLabel');
+
+      assert(response.remaining >= 0);
+
+      if (this.maxSamples_ == -1) {
+        this.maxSamples_ = response.remaining + 1;
+      }
+
+      this.$.arc.setProgress(
+          100 * (this.maxSamples_ - response.remaining - 1) / this.maxSamples_,
+          100 * (this.maxSamples_ - response.remaining) / this.maxSamples_,
+          false);
+    },
+
+    /**
+     * @private
+     * @param {!settings.EnrollmentResponse} response
+     */
+    onEnrollmentComplete_(response) {
       if (response.code == settings.Ctap2Status.ERR_KEEPALIVE_CANCEL) {
         this.showEnrollmentsPage_();
         return;
       }
+      if (response.code != settings.Ctap2Status.OK) {
+        this.onError_(
+            this.i18n('securityKeysBioEnrollmentEnrollingFailedLabel'));
+        return;
+      }
 
-      if (this.maxSamples_ == -1 && response.status != null) {
-        if (response.status == 0) {
-          // If the first sample is valid, remaining is one less than max
-          // samples required.
-          this.maxSamples_ = response.remaining + 1;
-        } else {
-          // If the first sample failed for any reason (timed out, key full,
-          // etc), the remaining number of samples is the max samples required.
-          this.maxSamples_ = response.remaining;
-        }
-      }
-      // If 0 samples remain, the enrollment has finished in some state.
-      // Currently not checking response['code'] for an error.
+      this.maxSamples_ = Math.max(this.maxSamples_, 1);
       this.$.arc.setProgress(
-          100 - (100 * (response.remaining + 1) / this.maxSamples_),
-          100 - (100 * response.remaining / this.maxSamples_),
-          response.remaining == 0);
-      if (response.remaining == 0) {
-        assert(response.enrollment);
-        this.recentEnrollmentId_ = response.enrollment.id;
-        this.recentEnrollmentName_ = response.enrollment.name;
-        this.cancelButtonVisible_ = false;
-        this.confirmButtonVisible_ = true;
-        this.confirmButtonDisabled_ = false;
-        this.progressArcLabel_ =
-            this.i18n('securityKeysBioEnrollmentEnrollingCompleteLabel');
-        this.$.confirmButton.focus();
-        // Make screen-readers announce enrollment completion.
-        this.fire('iron-announce', {text: this.progressArcLabel_});
-      }
+          100 * (this.maxSamples_ - 1) / this.maxSamples_, 100, true);
+
+      assert(response.enrollment);
+      this.recentEnrollmentId_ = response.enrollment.id;
+      this.recentEnrollmentName_ = response.enrollment.name;
+      this.cancelButtonVisible_ = false;
+      this.confirmButtonVisible_ = true;
+      this.confirmButtonDisabled_ = false;
+      this.progressArcLabel_ =
+          this.i18n('securityKeysBioEnrollmentEnrollingCompleteLabel');
+      this.$.confirmButton.focus();
+      // Make screen-readers announce enrollment completion.
+      this.fire('iron-announce', {text: this.progressArcLabel_});
+
       this.fire('bio-enroll-dialog-ready-for-testing');
     },
 
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.js b/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.js
index f72d863d..ad4c1bf 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.js
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.js
@@ -10,6 +10,7 @@
    */
   const Ctap2Status = {
     OK: 0x0,
+    ERR_INVALID_OPTION: 0x2C,
     ERR_KEEPALIVE_CANCEL: 0x2D,
   };
 
@@ -36,24 +37,33 @@
   let Credential;
 
   /**
-   * EnrollmentStatus represents the current status of an enrollment
-   * suboperation, where 'remaining' is the number of samples left, 'status' is
-   * the last enrollment status, 'code' indicates the final
-   * CtapDeviceResponseCode of the operation, and 'enrollment' contains the new
-   * Enrollment.
+   * SampleStatus is the result for reading an individual sample ("touch")
+   * during a fingerprint enrollment. This is a subset of the
+   * lastEnrollSampleStatus enum defined in the CTAP spec.
+   * @enum {number}
+   */
+  const SampleStatus = {
+    OK: 0x0,
+  };
+
+  /**
+   * SampleResponse indicates the result of an individual sample (sensor touch)
+   * for an enrollment suboperation.
    *
-   * For each enrollment sample, 'status' is set - when the enrollment operation
-   * reaches an end state, 'code' and, if successful, 'enrollment' are set. |OK|
-   * indicates successful enrollment. A code of |ERR_KEEPALIVE_CANCEL| indicates
-   * user-initated cancellation.
+   * @typedef {{status: settings.SampleStatus,
+   *            remaining: number}}
+   * @see chrome/browser/ui/webui/settings/settings_security_key_handler.cc
+   */
+  let SampleResponse;
+
+  /**
+   * EnrollmentResponse is the final response to an enrollment suboperation,
    *
-   * @typedef {{status: ?number,
-   *            code: ?settings.Ctap2Status,
-   *            remaining: number,
+   * @typedef {{code: settings.Ctap2Status,
    *            enrollment: ?settings.Enrollment}}
    * @see chrome/browser/ui/webui/settings/settings_security_key_handler.cc
    */
-  let EnrollmentStatus;
+  let EnrollmentResponse;
 
   /**
    * Enrollment represents a valid fingerprint template stored on a security
@@ -201,7 +211,7 @@
      * out waiting for a touch, or has successfully processed a touch. Any
      * errors will fire the 'security-keys-bio-enrollment-error' WebListener.
      *
-     * @return {!Promise<!settings.EnrollmentStatus>} resolves when the
+     * @return {!Promise<!settings.EnrollmentResponse>} resolves when the
      *     enrollment operation is finished successfully.
      */
     startEnrolling() {}
@@ -354,7 +364,9 @@
     Credential,
     Ctap2Status,
     Enrollment,
-    EnrollmentStatus,
+    EnrollmentResponse,
+    SampleStatus,
+    SampleResponse,
     SecurityKeysBioEnrollProxy,
     SecurityKeysBioEnrollProxyImpl,
     SecurityKeysCredentialBrowserProxy,
diff --git a/chrome/browser/resources/signin/BUILD.gn b/chrome/browser/resources/signin/BUILD.gn
index be812e8..8f82620 100644
--- a/chrome/browser/resources/signin/BUILD.gn
+++ b/chrome/browser/resources/signin/BUILD.gn
@@ -5,9 +5,7 @@
 import("//tools/polymer/polymer.gni")
 
 group("closure_compile") {
-  deps = [
-    "sync_confirmation:closure_compile",
-  ]
+  deps = [ "sync_confirmation:closure_compile" ]
   if (!is_chromeos) {
     deps += [ "signin_email_confirmation:closure_compile" ]
   }
diff --git a/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn b/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
index 436f8ea..0204fe8e 100644
--- a/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
+++ b/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
@@ -7,9 +7,7 @@
 
 js_type_check("closure_compile") {
   is_polymer3 = true
-  deps = [
-    ":signin_email_confirmation_app",
-  ]
+  deps = [ ":signin_email_confirmation_app" ]
 }
 
 js_library("signin_email_confirmation_app") {
@@ -21,9 +19,7 @@
 }
 
 group("polymer3_elements") {
-  deps = [
-    ":signin_email_confirmation_app_module",
-  ]
+  deps = [ ":signin_email_confirmation_app_module" ]
 }
 
 polymer_modulizer("signin_email_confirmation_app") {
diff --git a/chrome/browser/resources/signin/sync_confirmation/BUILD.gn b/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
index 4492e543..12f084d 100644
--- a/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
+++ b/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
@@ -13,9 +13,7 @@
 }
 
 js_type_check("closure_compile_polymer2") {
-  deps = [
-    ":sync_disabled_confirmation",
-  ]
+  deps = [ ":sync_disabled_confirmation" ]
 }
 
 js_type_check("closure_compile_polymer3") {
@@ -45,9 +43,7 @@
 }
 
 js_library("sync_confirmation_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [
     "$externs_path/chrome_send.js",
     "$externs_path/metrics_private.js",
@@ -63,9 +59,7 @@
 }
 
 group("polymer3_elements") {
-  deps = [
-    ":sync_confirmation_app_module",
-  ]
+  deps = [ ":sync_confirmation_app_module" ]
 }
 
 polymer_modulizer("sync_confirmation_app") {
diff --git a/chrome/browser/resources/tools/rollup_plugin.js b/chrome/browser/resources/tools/rollup_plugin.js
index e1942718..f462ab1 100644
--- a/chrome/browser/resources/tools/rollup_plugin.js
+++ b/chrome/browser/resources/tools/rollup_plugin.js
@@ -12,7 +12,7 @@
 
 // TODO: Determine whether it is worth maintaining this list vs always checking
 // both directories for the existence of a file.
-const nonGeneratedFiles = ['cr.m.js', 'action_link.js'];
+const nonGeneratedFiles = ['cr.m.js', 'cr_splitter.js', 'action_link.js'];
 
 function normalizeSlashes(filepath) {
   return filepath.replace(/\\/gi, '/');
diff --git a/chrome/browser/resources/user_manager/BUILD.gn b/chrome/browser/resources/user_manager/BUILD.gn
index ec9959fe..6adf635f 100644
--- a/chrome/browser/resources/user_manager/BUILD.gn
+++ b/chrome/browser/resources/user_manager/BUILD.gn
@@ -38,15 +38,11 @@
 }
 
 js_library("profile_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("user_manager_pages") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager",
-  ]
+  deps = [ "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager" ]
 }
 
 js_library("user_manager_tutorial") {
diff --git a/chrome/browser/resources/webapks/BUILD.gn b/chrome/browser/resources/webapks/BUILD.gn
index 7012bb6..8798ad55 100644
--- a/chrome/browser/resources/webapks/BUILD.gn
+++ b/chrome/browser/resources/webapks/BUILD.gn
@@ -8,9 +8,7 @@
 
 js_type_check("closure_compile") {
   uses_js_modules = true
-  deps = [
-    ":about_webapks",
-  ]
+  deps = [ ":about_webapks" ]
 }
 
 js_library("about_webapks") {
diff --git a/chrome/browser/resources/welcome/BUILD.gn b/chrome/browser/resources/welcome/BUILD.gn
index f82bd8f..b70b8cd 100644
--- a/chrome/browser/resources/welcome/BUILD.gn
+++ b/chrome/browser/resources/welcome/BUILD.gn
@@ -38,9 +38,7 @@
 }
 
 js_library("landing_view_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/metrics_private.js" ]
 }
 
@@ -54,9 +52,7 @@
 }
 
 js_library("signin_view_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/metrics_private.js" ]
 }
 
@@ -81,9 +77,7 @@
 }
 
 js_library("welcome_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
diff --git a/chrome/browser/resources/welcome/google_apps/BUILD.gn b/chrome/browser/resources/welcome/google_apps/BUILD.gn
index f6f678ed..5e14c83a 100644
--- a/chrome/browser/resources/welcome/google_apps/BUILD.gn
+++ b/chrome/browser/resources/welcome/google_apps/BUILD.gn
@@ -35,16 +35,12 @@
 }
 
 js_library("google_app_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/chrome_send.js" ]
 }
 
 js_library("google_apps_metrics_proxy") {
-  deps = [
-    "../shared:module_metrics_proxy",
-  ]
+  deps = [ "../shared:module_metrics_proxy" ]
 }
 
 polymer_modulizer("nux_google_apps") {
diff --git a/chrome/browser/resources/welcome/set_as_default/BUILD.gn b/chrome/browser/resources/welcome/set_as_default/BUILD.gn
index 0c82491..d553722 100644
--- a/chrome/browser/resources/welcome/set_as_default/BUILD.gn
+++ b/chrome/browser/resources/welcome/set_as_default/BUILD.gn
@@ -11,9 +11,7 @@
                     "js_module_root=../../chrome/browser/resources/welcome/",
                     "js_module_root=gen/chrome/browser/resources/welcome/",
                   ]
-  deps = [
-    ":nux_set_as_default",
-  ]
+  deps = [ ":nux_set_as_default" ]
 }
 
 js_library("nux_set_as_default") {
@@ -28,9 +26,7 @@
 }
 
 js_library("nux_set_as_default_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/metrics_private.js" ]
 }
 
diff --git a/chrome/browser/resources/welcome/shared/BUILD.gn b/chrome/browser/resources/welcome/shared/BUILD.gn
index 9ebc573..6c46e75 100644
--- a/chrome/browser/resources/welcome/shared/BUILD.gn
+++ b/chrome/browser/resources/welcome/shared/BUILD.gn
@@ -20,9 +20,7 @@
 }
 
 js_library("bookmark_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [
     "$externs_path/chrome_extensions.js",
     "$externs_path/chrome_send.js",
diff --git a/chrome/browser/safe_browsing/incident_reporting/BUILD.gn b/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
index 4de023f..2934b9b 100644
--- a/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
+++ b/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("state_store_data_proto") {
-  sources = [
-    "state_store_data.proto",
-  ]
+  sources = [ "state_store_data.proto" ]
 }
diff --git a/chrome/browser/search/BUILD.gn b/chrome/browser/search/BUILD.gn
index c610750..affdfff 100644
--- a/chrome/browser/search/BUILD.gn
+++ b/chrome/browser/search/BUILD.gn
@@ -25,9 +25,7 @@
     voice_js,
   ]
 
-  outputs = [
-    header_path,
-  ]
+  outputs = [ header_path ]
 
   args = [
     "--output_path=" + rebase_path(header_path, root_build_dir),
@@ -44,7 +42,5 @@
 source_set("generated") {
   sources = get_target_outputs(":local_ntp_code_generate")
 
-  public_deps = [
-    ":local_ntp_code_generate",
-  ]
+  public_deps = [ ":local_ntp_code_generate" ]
 }
diff --git a/chrome/browser/share/BUILD.gn b/chrome/browser/share/BUILD.gn
index d35da0b..5cf94f2 100644
--- a/chrome/browser/share/BUILD.gn
+++ b/chrome/browser/share/BUILD.gn
@@ -7,7 +7,5 @@
     "features.cc",
     "features.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/chrome/browser/share/android/BUILD.gn b/chrome/browser/share/android/BUILD.gn
index ba6fd64..3b676cc 100644
--- a/chrome/browser/share/android/BUILD.gn
+++ b/chrome/browser/share/android/BUILD.gn
@@ -7,9 +7,7 @@
 android_resources("java_resources") {
   # TODO(gayane): remove dependency on chrome/android:chrome_app_java_resources
   # once strings and common styles move out of chrome/android
-  deps = [
-    "//chrome/android:chrome_app_java_resources",
-  ]
+  deps = [ "//chrome/android:chrome_app_java_resources" ]
   resource_dirs = [ "java/res" ]
   custom_package = "org.chromium.chrome.browser.share.qrcode"
 }
diff --git a/chrome/browser/startup_data.cc b/chrome/browser/startup_data.cc
index ba8b5a11..09d11d2d 100644
--- a/chrome/browser/startup_data.cc
+++ b/chrome/browser/startup_data.cc
@@ -8,6 +8,8 @@
 #include "chrome/browser/metrics/chrome_feature_list_creator.h"
 #include "chrome/browser/prefs/profile_pref_store_manager.h"
 #include "chrome/common/channel_info.h"
+#include "components/metrics/delegating_provider.h"
+#include "components/metrics/entropy_state_provider.h"
 #include "components/metrics/field_trials_provider.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/persistent_system_profile.h"
@@ -73,11 +75,20 @@
       chrome_feature_list_creator_->actual_locale(),
       metrics::GetAppPackageName(), &system_profile);
 
+  metrics::DelegatingProvider delegating_provider;
+
   // TODO(hanxi): Create SyntheticTrialRegistry and pass it to
   // |field_trial_provider|.
-  variations::FieldTrialsProvider field_trial_provider(nullptr,
-                                                       base::StringPiece());
-  field_trial_provider.ProvideSystemProfileMetricsWithLogCreationTime(
+  delegating_provider.RegisterMetricsProvider(
+      std::make_unique<variations::FieldTrialsProvider>(nullptr,
+                                                        base::StringPiece()));
+
+  // Persists low entropy source values.
+  delegating_provider.RegisterMetricsProvider(
+      std::make_unique<metrics::EntropyStateProvider>(
+          chrome_feature_list_creator_->local_state()));
+
+  delegating_provider.ProvideSystemProfileMetricsWithLogCreationTime(
       base::TimeTicks(), &system_profile);
 
   // TODO(crbug.com/965482): Records information from other providers.
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn b/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
index 997f2b5..0c22b4c 100644
--- a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
+++ b/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
@@ -24,17 +24,13 @@
 
 if (is_android) {
   java_cpp_enum("enums_srcjar") {
-    sources = [
-      "supervised_user_error_page.h",
-    ]
+    sources = [ "supervised_user_error_page.h" ]
   }
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "supervised_user_error_page_unittest.cc",
-  ]
+  sources = [ "supervised_user_error_page_unittest.cc" ]
   deps = [
     ":supervised_user_error_page",
     "//base",
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 26e0214..7241065 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1356,6 +1356,8 @@
       "webui/settings/settings_startup_pages_handler.h",
       "webui/settings/settings_ui.cc",
       "webui/settings/settings_ui.h",
+      "webui/settings/shared_settings_localized_strings_provider.cc",
+      "webui/settings/shared_settings_localized_strings_provider.h",
       "webui/settings/site_settings_handler.cc",
       "webui/settings/site_settings_handler.h",
       "webui/settings_utils.cc",
@@ -1948,6 +1950,8 @@
       "webui/settings/chromeos/kerberos_accounts_handler.h",
       "webui/settings/chromeos/multidevice_handler.cc",
       "webui/settings/chromeos/multidevice_handler.h",
+      "webui/settings/chromeos/os_settings_localized_strings_provider.cc",
+      "webui/settings/chromeos/os_settings_localized_strings_provider.h",
       "webui/settings/chromeos/os_settings_ui.cc",
       "webui/settings/chromeos/os_settings_ui.h",
       "webui/settings/chromeos/parental_controls_handler.cc",
diff --git a/chrome/browser/ui/android/appmenu/BUILD.gn b/chrome/browser/ui/android/appmenu/BUILD.gn
index a0a3e95..00811f5e 100644
--- a/chrome/browser/ui/android/appmenu/BUILD.gn
+++ b/chrome/browser/ui/android/appmenu/BUILD.gn
@@ -16,18 +16,12 @@
     "java/src/org/chromium/chrome/browser/ui/appmenu/CustomViewBinder.java",
     "java/src/org/chromium/chrome/browser/ui/appmenu/MenuButtonDelegate.java",
   ]
-  deps = [
-    "//chrome/lib/lifecycle/public/android:java",
-  ]
+  deps = [ "//chrome/lib/lifecycle/public/android:java" ]
 }
 
 android_library_factory("factory_java") {
-  deps = [
-    ":java",
-  ]
-  sources = [
-    "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuCoordinatorFactory.java",
-  ]
+  deps = [ ":java" ]
+  sources = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuCoordinatorFactory.java" ]
 }
 
 android_library("test_support_java") {
diff --git a/chrome/browser/ui/android/appmenu/internal/BUILD.gn b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
index af18e561..a3085f38 100644
--- a/chrome/browser/ui/android/appmenu/internal/BUILD.gn
+++ b/chrome/browser/ui/android/appmenu/internal/BUILD.gn
@@ -76,18 +76,14 @@
 
   custom_package = "org.chromium.chrome.browser.ui.appmenu.test"
   resource_dirs = [ "test/java/res" ]
-  deps = [
-    ":java_resources",
-  ]
+  deps = [ ":java_resources" ]
 }
 
 java_library("junit") {
   # Skip platform checks since Robolectric depends on requires_android targets.
   bypass_platform_checks = true
   testonly = true
-  sources = [
-    "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuPopupPositionTest.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuPopupPositionTest.java" ]
   deps = [
     ":java",
     "//base:base_junit_test_support",
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn b/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
index 19d6c058..5f0ddf0 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
+++ b/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("cros_action_proto") {
-  sources = [
-    "cros_action.proto",
-  ]
+  sources = [ "cros_action.proto" ]
 }
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn b/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
index f3737af7..cdbb313 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
@@ -5,21 +5,15 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("app_launch_event_logger_proto") {
-  sources = [
-    "app_launch_event_logger.proto",
-  ]
+  sources = [ "app_launch_event_logger.proto" ]
 }
 
 proto_library("app_launch_predictor_proto") {
-  sources = [
-    "app_launch_predictor.proto",
-  ]
+  sources = [ "app_launch_predictor.proto" ]
 }
 
 proto_library("app_list_launch_recorder_proto") {
-  sources = [
-    "app_list_launch_recorder_state.proto",
-  ]
+  sources = [ "app_list_launch_recorder_state.proto" ]
 }
 
 proto_library("recurrence_ranker_proto") {
@@ -32,7 +26,5 @@
 }
 
 proto_library("search_ranking_event_proto") {
-  sources = [
-    "search_ranking_event.proto",
-  ]
+  sources = [ "search_ranking_event.proto" ]
 }
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
index 001e4af..cca2947 100644
--- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -29,14 +29,14 @@
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 // Internal builds add an extra accelerator for the Feedback app.
 // The total number of Chrome accelerators (available on Chrome OS).
-constexpr int kChromeAcceleratorsTotalNum = 93;
+constexpr int kChromeAcceleratorsTotalNum = 95;
 // The hash of Chrome accelerators (available on Chrome OS).
-constexpr char kChromeAcceleratorsHash[] = "73c842a72d77e7b9e69e92a6ee7900d3";
+constexpr char kChromeAcceleratorsHash[] = "ef0b7eb1a1dabd26e964c6593e4698a4";
 #else
 // The total number of Chrome accelerators (available on Chrome OS).
-constexpr int kChromeAcceleratorsTotalNum = 92;
+constexpr int kChromeAcceleratorsTotalNum = 94;
 // The hash of Chrome accelerators (available on Chrome OS).
-constexpr char kChromeAcceleratorsHash[] = "7c45362e298cf77aae142dec7154adcf";
+constexpr char kChromeAcceleratorsHash[] = "f22167989af00d94f8de75cbc89b977e";
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 const char* BooleanToString(bool value) {
diff --git a/chrome/browser/ui/color/BUILD.gn b/chrome/browser/ui/color/BUILD.gn
index 9dfbdcd..5a9aa19 100644
--- a/chrome/browser/ui/color/BUILD.gn
+++ b/chrome/browser/ui/color/BUILD.gn
@@ -5,13 +5,9 @@
 import("//ui/base/ui_features.gni")
 
 source_set("color_headers") {
-  sources = [
-    "chrome_color_id.h",
-  ]
+  sources = [ "chrome_color_id.h" ]
 
-  public_deps = [
-    "//ui/color:color_headers",
-  ]
+  public_deps = [ "//ui/color:color_headers" ]
 
   if (!use_color_pipeline) {
     public_deps += [ "//chrome/browser:theme_properties" ]
@@ -22,9 +18,7 @@
   executable("dump_colors") {
     testonly = true
 
-    sources = [
-      "tools/dump_colors.cc",
-    ]
+    sources = [ "tools/dump_colors.cc" ]
 
     deps = [
       ":color_headers",
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
index 771e8f6..7465700e 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -383,6 +383,8 @@
     if (visible_count_delta)
       SetVisibleIconCount(visible_icon_count() + visible_count_delta);
   }
+
+  UpdatePinnedActionIds();
 }
 
 void ToolbarActionsModel::RemoveAction(const ActionId& action_id) {
@@ -397,6 +399,11 @@
 
   action_ids_.erase(pos);
 
+  // TODO(pbos): Remove previously-pinned actions from ExtensionPrefs if this is
+  // an uninstall and not a disable. This might need to be handled in another
+  // place (ExtensionPrefs?) as we don't know the reason for RemoveAction here.
+  UpdatePinnedActionIds();
+
   // If we're in highlight mode, we also have to remove the action from
   // the highlighted list.
   if (is_highlighting()) {
@@ -485,8 +492,11 @@
   else
     Populate();
 
-  if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu))
+  if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
+    // Set |pinned_action_ids_| directly to avoid notifying observers that they
+    // have changed even though they haven't.
     pinned_action_ids_ = GetFilteredPinnedActionIds();
+  }
 }
 
 void ToolbarActionsModel::Populate() {
@@ -658,14 +668,7 @@
   if (!actions_initialized_)
     return;
 
-  if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
-    std::vector<ActionId> pinned_extensions = GetFilteredPinnedActionIds();
-    if (pinned_extensions != pinned_action_ids_) {
-      pinned_action_ids_ = pinned_extensions;
-      for (Observer& observer : observers_)
-        observer.OnToolbarPinnedActionsChanged();
-    }
-  }
+  UpdatePinnedActionIds();
 
   // Recalculate |last_known_positions_| to be |pref_positions| followed by
   // ones that are only in |last_known_positions_|.
@@ -784,6 +787,18 @@
   return index < visible_icon_count();
 }
 
+void ToolbarActionsModel::UpdatePinnedActionIds() {
+  if (!base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu))
+    return;
+  std::vector<ActionId> pinned_extensions = GetFilteredPinnedActionIds();
+  if (pinned_extensions == pinned_action_ids_)
+    return;
+
+  pinned_action_ids_ = pinned_extensions;
+  for (Observer& observer : observers_)
+    observer.OnToolbarPinnedActionsChanged();
+}
+
 std::vector<ToolbarActionsModel::ActionId>
 ToolbarActionsModel::GetFilteredPinnedActionIds() const {
   // TODO(pbos): Make sure that the pinned IDs are pruned from ExtensionPrefs on
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.h b/chrome/browser/ui/toolbar/toolbar_actions_model.h
index ef6618f78..ad92de9 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.h
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.h
@@ -266,6 +266,10 @@
   // Returns true if the action is visible on the toolbar.
   bool IsActionVisible(const ActionId& action_id) const;
 
+  // Updates |pinned_action_ids_| per GetFilteredPinnedActionIds() and notifies
+  // observers if they have changed.
+  void UpdatePinnedActionIds();
+
   // Gets a list of pinned action ids that only contains that only contains IDs
   // with a corresponding action in the model.
   std::vector<ActionId> GetFilteredPinnedActionIds() const;
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc
index ba35bf0..ab03451 100644
--- a/chrome/browser/ui/views/accelerator_table.cc
+++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -170,6 +170,7 @@
     // bindings as well. Mapping with just Alt appear here, and should have an
     // alternative mapping in the block above.
     {ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK},
+    {ui::VKEY_LEFT, ui::EF_ALTGR_DOWN, IDC_BACK},
 #if BUILDFLAG(ENABLE_PRINTING)
     {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT},
 #endif  // ENABLE_PRINTING
@@ -190,6 +191,7 @@
     {ui::VKEY_K, ui::EF_CONTROL_DOWN, IDC_FOCUS_SEARCH},
     {ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, IDC_FOCUS_TOOLBAR},
     {ui::VKEY_RIGHT, ui::EF_ALT_DOWN, IDC_FORWARD},
+    {ui::VKEY_RIGHT, ui::EF_ALTGR_DOWN, IDC_FORWARD},
     {ui::VKEY_HOME, ui::EF_ALT_DOWN, IDC_HOME},
     {ui::VKEY_E, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
     {ui::VKEY_F, ui::EF_ALT_DOWN, IDC_SHOW_APP_MENU},
diff --git a/chrome/browser/ui/views/accelerator_table_unittest.cc b/chrome/browser/ui/views/accelerator_table_unittest.cc
index 0c26fbb..cca3dba 100644
--- a/chrome/browser/ui/views/accelerator_table_unittest.cc
+++ b/chrome/browser/ui/views/accelerator_table_unittest.cc
@@ -42,7 +42,8 @@
         << "Duplicated accelerator: " << entry.keycode << ", "
         << (entry.modifiers & ui::EF_SHIFT_DOWN) << ", "
         << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", "
-        << (entry.modifiers & ui::EF_ALT_DOWN);
+        << (entry.modifiers & ui::EF_ALT_DOWN) << ", "
+        << (entry.modifiers & ui::EF_ALTGR_DOWN);
   }
 }
 
@@ -98,7 +99,8 @@
         << "Duplicated accelerator: " << entry.keycode << ", "
         << (entry.modifiers & ui::EF_SHIFT_DOWN) << ", "
         << (entry.modifiers & ui::EF_CONTROL_DOWN) << ", "
-        << (entry.modifiers & ui::EF_ALT_DOWN) << ", action "
+        << (entry.modifiers & ui::EF_ALT_DOWN) << ", "
+        << (entry.modifiers & ui::EF_ALTGR_DOWN) << ", action "
         << (ash_entry.action);
   }
 }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
index 544fae6..161260e 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view.cc
@@ -467,9 +467,8 @@
 }
 
 void ExtensionsMenuView::OnToolbarPinnedActionsChanged() {
-  for (auto* menu_item : extensions_menu_items_) {
+  for (auto* menu_item : extensions_menu_items_)
     menu_item->UpdatePinButton();
-  }
 }
 
 // static
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index f15669b..e8f1d15 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -1584,7 +1584,9 @@
 
 void TabDragController::RevertDrag() {
   std::vector<TabSlotView*> views;
-  for (size_t i = 0; i < drag_data_.size(); ++i) {
+  if (header_drag_)
+    views.push_back(drag_data_[0].attached_view);
+  for (size_t i = first_tab_index(); i < drag_data_.size(); ++i) {
     if (drag_data_[i].contents) {
       // Contents is NULL if a tab was destroyed while the drag was under way.
       views.push_back(drag_data_[i].attached_view);
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 779701d..673550d 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -2061,6 +2061,92 @@
   EXPECT_EQ(tab_strip2->GetGroupColorId(groups2[0]), group_color);
 }
 
+// Drags a tab group by the header to a new position and presses escape to
+// revert the drag.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestWithTabGroupsEnabled,
+                       PressEscapeDuringHeaderDrag) {
+  TabStrip* tab_strip = GetTabStripForBrowser(browser());
+  TabStripModel* model = browser()->tab_strip_model();
+  AddTabsAndResetBrowser(browser(), 1);
+  tab_groups::TabGroupId group = model->AddToNewGroup({0});
+  StopAnimating(tab_strip);
+
+  TabGroupHeader* group_header = tab_strip->group_header(group);
+  EXPECT_FALSE(group_header->dragging());
+  ASSERT_TRUE(PressInput(GetCenterInScreenCoordinates(group_header)));
+  ASSERT_TRUE(DragInputTo(GetCenterInScreenCoordinates(tab_strip->tab_at(1))));
+  ASSERT_TRUE(group_header->dragging());
+
+  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
+      browser()->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false,
+      false, false));
+
+  EXPECT_EQ(1u, browser_list->size());
+  EXPECT_FALSE(group_header->dragging());
+  EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+  std::vector<tab_groups::TabGroupId> groups =
+      model->group_model()->ListTabGroups();
+  EXPECT_EQ(1u, groups.size());
+  EXPECT_THAT(model->group_model()->GetTabGroup(groups[0])->ListTabs(),
+              testing::ElementsAre(0));
+}
+
+namespace {
+
+void PressEscapeWhileDetachedHeaderStep2(
+    DetachToBrowserTabDragControllerTest* test) {
+  // At this moment there should be a new browser window for the dragged tabs.
+  EXPECT_EQ(2u, test->browser_list->size());
+  Browser* new_browser = test->browser_list->get(1);
+  std::vector<tab_groups::TabGroupId> new_browser_groups =
+      new_browser->tab_strip_model()->group_model()->ListTabGroups();
+  EXPECT_EQ(1u, new_browser_groups.size());
+  EXPECT_EQ(0u, test->browser()
+                    ->tab_strip_model()
+                    ->group_model()
+                    ->ListTabGroups()
+                    .size());
+
+  TabGroupHeader* new_group_header =
+      GetTabStripForBrowser(new_browser)->group_header(new_browser_groups[0]);
+  EXPECT_TRUE(new_group_header->dragging());
+
+  ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync(
+      new_browser->window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false,
+      false, false));
+}
+
+}  // namespace
+
+// Drags a tab group by the header and while detached presses escape to revert
+// the drag.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTestWithTabGroupsEnabled,
+                       PressEscapeDuringHeaderDragWhileDetached) {
+  TabStrip* tab_strip = GetTabStripForBrowser(browser());
+  TabStripModel* model = browser()->tab_strip_model();
+  AddTabsAndResetBrowser(browser(), 1);
+  tab_groups::TabGroupId group = model->AddToNewGroup({0});
+  StopAnimating(tab_strip);
+
+  DragGroupAndNotify(tab_strip,
+                     base::BindOnce(&PressEscapeWhileDetachedHeaderStep2, this),
+                     group);
+
+  TabGroupHeader* group_header =
+      GetTabStripForBrowser(browser())->group_header(group);
+  EXPECT_FALSE(group_header->dragging());
+
+  ASSERT_FALSE(tab_strip->GetDragContext()->IsDragSessionActive());
+  ASSERT_FALSE(TabDragController::IsActive());
+  EXPECT_EQ(1u, browser_list->size());
+  EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+  std::vector<tab_groups::TabGroupId> groups =
+      model->group_model()->ListTabGroups();
+  EXPECT_EQ(1u, groups.size());
+  EXPECT_THAT(model->group_model()->GetTabGroup(groups[0])->ListTabs(),
+              testing::ElementsAre(0));
+}
+
 namespace {
 
 // Invoked from the nested run loop.
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
index 72ecdef..73b68e09 100644
--- a/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
+++ b/chrome/browser/ui/views/toolbar/webui_tab_counter_button.cc
@@ -313,7 +313,9 @@
     TabStripModel* tab_strip_model,
     const TabStripModelChange& change,
     const TabStripSelectionChange& selection) {
-  UpdateText(tab_strip_model->count());
+  int num_tabs = tab_strip_model->count();
+  if (num_tabs != last_num_tabs_)
+    UpdateText(num_tabs);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn b/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
index 210d8f3..d2a1810 100644
--- a/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
@@ -12,9 +12,7 @@
     "bluetooth_internals_ui.h",
   ]
 
-  public_deps = [
-    "//device/bluetooth:deprecated_experimental_mojo",
-  ]
+  public_deps = [ "//device/bluetooth:deprecated_experimental_mojo" ]
 
   deps = [
     ":mojo_bindings",
@@ -31,11 +29,8 @@
 }
 
 mojom("mojo_bindings") {
-  sources = [
-    "bluetooth_internals.mojom",
-  ]
+  sources = [ "bluetooth_internals.mojom" ]
 
-  deps = [
-    "//device/bluetooth/public/mojom:deprecated_experimental_interfaces",
-  ]
+  deps =
+      [ "//device/bluetooth/public/mojom:deprecated_experimental_interfaces" ]
 }
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn b/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
index 54b63f6b..4e580f6 100644
--- a/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
+++ b/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "add_supervision.mojom",
-  ]
+  sources = [ "add_supervision.mojom" ]
 }
diff --git a/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn b/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
index 78b1683..10e8045 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
+++ b/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
@@ -5,11 +5,8 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "crostini_installer.mojom",
-  ]
+  sources = [ "crostini_installer.mojom" ]
 
-  public_deps = [
-    "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom",
-  ]
+  public_deps =
+      [ "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom" ]
 }
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn b/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
index 9ec0720..bccf718e 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "crostini_upgrader.mojom",
-  ]
+  sources = [ "crostini_upgrader.mojom" ]
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
index 61911ecd..ca64a2c2 100644
--- a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
@@ -10,6 +10,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "components/login/localized_values_builder.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/devicetype_utils.h"
 
 namespace {
 
@@ -29,13 +30,20 @@
     // characters, so we must use base::ReplaceSubstrings* rather than
     // base::ReplaceChars.
     // TODO(alemate): Find a more elegant solution.
-    std::string sanitized_string =
-        base::UTF16ToUTF8(l10n_util::GetStringUTF16(id));
+    base::string16 raw_string;
+    if (id == IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME) {
+      raw_string = ui::SubstituteChromeOSDeviceType(
+          IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME);
+    } else {
+      raw_string = l10n_util::GetStringUTF16(id);
+    }
+    std::string sanitized_string = base::UTF16ToUTF8(raw_string);
     base::ReplaceSubstringsAfterOffset(&sanitized_string, 0,
                                        "\u00A0" /* NBSP */, "&nbsp;");
 
     known_strings[sanitized_string] = id;
   }
+
   // The strings returned by the WebUI are not free-form, they must belong into
   // a pre-determined set of strings (stored in |string_to_grd_id_map_|). As
   // this has privacy and legal implications, CHECK the integrity of the strings
@@ -101,6 +109,19 @@
   RememberLocalizedValue("syncConsentAcceptAndContinue",
                          IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE,
                          builder);
+
+  // SplitSettingsSync strings. The version of the dialog to show is chosen
+  // after the WebUI is loaded, so always supply both sets of strings.
+  RememberLocalizedValue("osSyncConsentTitle", IDS_LOGIN_OS_SYNC_CONSENT_TITLE,
+                         builder);
+  known_string_ids_.insert(IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME);
+  builder->AddF("osSyncConsentToggleName",
+                IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME,
+                ui::GetChromeOSDeviceName());
+  RememberLocalizedValue("osSyncConsentToggleDescription",
+                         IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION, builder);
+  RememberLocalizedValue("osSyncConsentContinue",
+                         IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE, builder);
 }
 
 void SyncConsentScreenHandler::Bind(SyncConsentScreen* screen) {
diff --git a/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn b/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
index 3adbd9c..770038b0 100644
--- a/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
+++ b/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "machine_learning_internals_page_handler.mojom",
-  ]
+  sources = [ "machine_learning_internals_page_handler.mojom" ]
 
-  deps = [
-    "//chromeos/services/machine_learning/public/mojom",
-  ]
+  deps = [ "//chromeos/services/machine_learning/public/mojom" ]
 }
diff --git a/chrome/browser/ui/webui/feed_internals/BUILD.gn b/chrome/browser/ui/webui/feed_internals/BUILD.gn
index 846c29a..a4633c3 100644
--- a/chrome/browser/ui/webui/feed_internals/BUILD.gn
+++ b/chrome/browser/ui/webui/feed_internals/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "feed_internals.mojom",
-  ]
+  sources = [ "feed_internals.mojom" ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/chrome/browser/ui/webui/management_ui.cc b/chrome/browser/ui/webui/management_ui.cc
index 8426606..64eb5c0 100644
--- a/chrome/browser/ui/webui/management_ui.cc
+++ b/chrome/browser/ui/webui/management_ui.cc
@@ -59,6 +59,9 @@
     {kManagementReportUsers, IDS_MANAGEMENT_REPORT_DEVICE_USERS},
     {kManagementPrinting, IDS_MANAGEMENT_REPORT_PRINTING},
     {kManagementCrostini, IDS_MANAGEMENT_CROSTINI},
+    {kManagementReportExtensions, IDS_MANAGEMENT_REPORT_EXTENSIONS},
+    {kManagementReportAndroidApplications,
+     IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS},
 #endif  // defined(OS_CHROMEOS)
     {"browserReporting", IDS_MANAGEMENT_BROWSER_REPORTING},
     {"browserReportingExplanation",
diff --git a/chrome/browser/ui/webui/management_ui_handler.cc b/chrome/browser/ui/webui/management_ui_handler.cc
index 7f4f048..c4e0345b 100644
--- a/chrome/browser/ui/webui/management_ui_handler.cc
+++ b/chrome/browser/ui/webui/management_ui_handler.cc
@@ -14,6 +14,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
+#include "base/feature_list.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -22,6 +23,7 @@
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
@@ -131,6 +133,9 @@
 const char kManagementReportNetworkInterfaces[] =
     "managementReportNetworkInterfaces";
 const char kManagementReportUsers[] = "managementReportUsers";
+const char kManagementReportExtensions[] = "managementReportExtensions";
+const char kManagementReportAndroidApplications[] =
+    "managementReportAndroidApplications";
 const char kManagementPrinting[] = "managementPrinting";
 const char kManagementCrostini[] = "managementCrostini";
 const char kAccountManagedInfo[] = "accountManagedInfo";
@@ -170,7 +175,10 @@
   kDevice,
   kLogs,
   kPrint,
-  kCrostini
+  kCrostini,
+  kUsername,
+  kExtensions,
+  kAndroidApplication
 };
 
 // Corresponds to DeviceReportingType in management_browser_proxy.js
@@ -190,6 +198,12 @@
       return "print";
     case DeviceReportingType::kCrostini:
       return "crostini";
+    case DeviceReportingType::kUsername:
+      return "username";
+    case DeviceReportingType::kExtensions:
+      return "extension";
+    case DeviceReportingType::kAndroidApplication:
+      return "android application";
     default:
       NOTREACHED() << "Unknown device reporting type";
       return "device";
@@ -257,6 +271,19 @@
     AddDeviceReportingElement(report_sources, kManagementCrostini,
                               DeviceReportingType::kCrostini);
   }
+
+  if (g_browser_process->local_state()->GetBoolean(
+          prefs::kCloudReportingEnabled) &&
+      base::FeatureList::IsEnabled(features::kEnterpriseReportingInChromeOS)) {
+    AddDeviceReportingElement(report_sources,
+                              kManagementExtensionReportUsername,
+                              DeviceReportingType::kUsername);
+    AddDeviceReportingElement(report_sources, kManagementReportExtensions,
+                              DeviceReportingType::kExtensions);
+    AddDeviceReportingElement(report_sources,
+                              kManagementReportAndroidApplications,
+                              DeviceReportingType::kAndroidApplication);
+  }
 }
 #endif  // defined(OS_CHROMEOS)
 
diff --git a/chrome/browser/ui/webui/management_ui_handler.h b/chrome/browser/ui/webui/management_ui_handler.h
index 1ee4cb30..555a7ec 100644
--- a/chrome/browser/ui/webui/management_ui_handler.h
+++ b/chrome/browser/ui/webui/management_ui_handler.h
@@ -34,6 +34,8 @@
 extern const char kManagementReportUsers[];
 extern const char kManagementPrinting[];
 extern const char kManagementCrostini[];
+extern const char kManagementReportExtensions[];
+extern const char kManagementReportAndroidApplications[];
 #endif  // defined(OS_CHROMEOS)
 
 extern const char kCloudReportingExtensionId[];
diff --git a/chrome/browser/ui/webui/omnibox/BUILD.gn b/chrome/browser/ui/webui/omnibox/BUILD.gn
index bf547a0..b58f3e4 100644
--- a/chrome/browser/ui/webui/omnibox/BUILD.gn
+++ b/chrome/browser/ui/webui/omnibox/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "omnibox.mojom",
-  ]
+  sources = [ "omnibox.mojom" ]
 }
diff --git a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
index 2a8a69eb..5c9d71f 100644
--- a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
+++ b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
@@ -39,6 +39,8 @@
 
 void FakePrintRenderFrame::SetPrintingEnabled(bool enabled) {}
 
+void FakePrintRenderFrame::PrintNodeUnderContextMenu() {}
+
 void FakePrintRenderFrame::BindPrintRenderFrameReceiver(
     mojo::ScopedInterfaceEndpointHandle handle) {
   receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::PrintRenderFrame>(
diff --git a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
index b45a498..fb66df20 100644
--- a/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
+++ b/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
@@ -34,6 +34,7 @@
   void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override;
   void PrintingDone(bool success) override;
   void SetPrintingEnabled(bool enabled) override;
+  void PrintNodeUnderContextMenu() override;
 
   void BindPrintRenderFrameReceiver(mojo::ScopedInterfaceEndpointHandle handle);
 
diff --git a/chrome/browser/ui/webui/reset_password/BUILD.gn b/chrome/browser/ui/webui/reset_password/BUILD.gn
index 46529aa..bd425a30 100644
--- a/chrome/browser/ui/webui/reset_password/BUILD.gn
+++ b/chrome/browser/ui/webui/reset_password/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "reset_password.mojom",
-  ]
+  sources = [ "reset_password.mojom" ]
 }
diff --git a/chrome/browser/ui/webui/sandbox/sandbox_handler.cc b/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
index 923e8e8..e8190bec 100644
--- a/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
+++ b/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
@@ -15,6 +15,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/sandbox_type.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/process_type.h"
 #include "services/service_manager/sandbox/win/sandbox_win.h"
@@ -25,6 +26,39 @@
 
 namespace sandbox_handler {
 namespace {
+
+// This only includes OS_WIN included SandboxType values.
+std::string GetSandboxTypeInEnglish(content::SandboxType sandbox_type) {
+  switch (sandbox_type) {
+    case content::SandboxType::kInvalid:
+      return "Invalid";
+    case content::SandboxType::kNoSandbox:
+      return "Unsandboxed";
+    case content::SandboxType::kNoSandboxAndElevatedPrivileges:
+      return "Unsandboxed (Elevated)";
+    case content::SandboxType::kXrCompositing:
+      return "XR Compositing";
+    case content::SandboxType::kRenderer:
+      return "Renderer";
+    case content::SandboxType::kUtility:
+      return "Utility";
+    case content::SandboxType::kGpu:
+      return "GPU";
+    case content::SandboxType::kPpapi:
+      return "PPAPI";
+    case content::SandboxType::kNetwork:
+      return "Network";
+    case content::SandboxType::kCdm:
+      return "CDM";
+    case content::SandboxType::kPrintCompositor:
+      return "Print Compositor";
+    case content::SandboxType::kAudio:
+      return "Audio";
+    case content::SandboxType::kSoda:
+      return "SODA";
+  }
+}
+
 base::Value FetchBrowserChildProcesses() {
   // The |BrowserChildProcessHostIterator| must only be used on the IO thread.
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -43,6 +77,9 @@
                      process_data.process_type)));
     proc.SetPath("name", base::Value(process_data.name));
     proc.SetPath("metricsName", base::Value(process_data.metrics_name));
+    proc.SetPath(
+        "sandboxType",
+        base::Value(GetSandboxTypeInEnglish(process_data.sandbox_type)));
     browser_processes.Append(std::move(proc));
   }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
new file mode 100644
index 0000000..a1486bb
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
@@ -0,0 +1,211 @@
+// 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/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_switches.h"
+#include "ui/accessibility/accessibility_switches.h"
+
+namespace chromeos {
+namespace settings {
+namespace {
+
+void AddA11yStrings(content::WebUIDataSource* html_source) {
+  ::settings::AddSharedA11yStrings(html_source);
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+      {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
+      {"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL},
+      {"largeMouseCursorSizeLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LABEL},
+      {"largeMouseCursorSizeDefaultLabel",
+       IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_DEFAULT_LABEL},
+      {"largeMouseCursorSizeLargeLabel",
+       IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LARGE_LABEL},
+      {"highContrastLabel", IDS_SETTINGS_HIGH_CONTRAST_LABEL},
+      {"stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL},
+      {"chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL},
+      {"chromeVoxOptionsLabel", IDS_SETTINGS_CHROMEVOX_OPTIONS_LABEL},
+      {"screenMagnifierLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL},
+      {"screenMagnifierZoomLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_LABEL},
+      {"dockedMagnifierLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_LABEL},
+      {"dockedMagnifierZoomLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_ZOOM_LABEL},
+      {"screenMagnifierZoom2x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_2_X},
+      {"screenMagnifierZoom4x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_4_X},
+      {"screenMagnifierZoom6x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_6_X},
+      {"screenMagnifierZoom8x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_8_X},
+      {"screenMagnifierZoom10x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_10_X},
+      {"screenMagnifierZoom12x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_12_X},
+      {"screenMagnifierZoom14x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_14_X},
+      {"screenMagnifierZoom16x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_16_X},
+      {"screenMagnifierZoom18x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_18_X},
+      {"screenMagnifierZoom20x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_20_X},
+      {"tapDraggingLabel", IDS_SETTINGS_TAP_DRAGGING_LABEL},
+      {"clickOnStopLabel", IDS_SETTINGS_CLICK_ON_STOP_LABEL},
+      {"delayBeforeClickLabel", IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL},
+      {"delayBeforeClickExtremelyShort",
+       IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT},
+      {"delayBeforeClickVeryShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT},
+      {"delayBeforeClickShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT},
+      {"delayBeforeClickLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG},
+      {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG},
+      {"autoclickRevertToLeftClick",
+       IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK},
+      {"autoclickStabilizeCursorPosition",
+       IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION},
+      {"autoclickMovementThresholdLabel",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL},
+      {"autoclickMovementThresholdExtraSmall",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_SMALL},
+      {"autoclickMovementThresholdSmall",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_SMALL},
+      {"autoclickMovementThresholdDefault",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_DEFAULT},
+      {"autoclickMovementThresholdLarge",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LARGE},
+      {"autoclickMovementThresholdExtraLarge",
+       IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_LARGE},
+      {"dictationDescription",
+       IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION},
+      {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL},
+      {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL},
+      {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL},
+      {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL},
+      {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION},
+      {"caretHighlightLabel",
+       IDS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION},
+      {"cursorHighlightLabel",
+       IDS_SETTINGS_ACCESSIBILITY_CURSOR_HIGHLIGHT_DESCRIPTION},
+      {"focusHighlightLabel",
+       IDS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION},
+      {"selectToSpeakTitle", IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE},
+      {"selectToSpeakDisabledDescription",
+       IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DISABLED_DESCRIPTION},
+      {"selectToSpeakDescription",
+       IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION},
+      {"selectToSpeakDescriptionWithoutKeyboard",
+       IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION_WITHOUT_KEYBOARD},
+      {"selectToSpeakOptionsLabel",
+       IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_OPTIONS_LABEL},
+      {"switchAccessLabel",
+       IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_DESCRIPTION},
+      {"switchAccessOptionsLabel",
+       IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_OPTIONS_LABEL},
+      {"manageSwitchAccessSettings",
+       IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS},
+      {"switchAssignmentHeading", IDS_SETTINGS_SWITCH_ASSIGNMENT_HEADING},
+      {"switchAssignOptionNone", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_NONE},
+      {"switchAssignOptionSpace", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_SPACE},
+      {"switchAssignOptionEnter", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_ENTER},
+      {"assignSelectSwitchLabel", IDS_SETTINGS_ASSIGN_SELECT_SWITCH_LABEL},
+      {"assignNextSwitchLabel", IDS_SETTINGS_ASSIGN_NEXT_SWITCH_LABEL},
+      {"assignPreviousSwitchLabel", IDS_SETTINGS_ASSIGN_PREVIOUS_SWITCH_LABEL},
+      {"switchAccessAutoScanHeading",
+       IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_HEADING},
+      {"switchAccessAutoScanLabel", IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_LABEL},
+      {"switchAccessAutoScanSpeedLabel",
+       IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_SPEED_LABEL},
+      {"switchAccessAutoScanKeyboardSpeedLabel",
+       IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_KEYBOARD_SPEED_LABEL},
+      {"durationInSeconds", IDS_SETTINGS_DURATION_IN_SECONDS},
+      {"manageAccessibilityFeatures",
+       IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
+      {"textToSpeechHeading",
+       IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_HEADING},
+      {"displayHeading", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_HEADING},
+      {"displaySettingsTitle",
+       IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_TITLE},
+      {"displaySettingsDescription",
+       IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_DESCRIPTION},
+      {"appearanceSettingsTitle",
+       IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_TITLE},
+      {"appearanceSettingsDescription",
+       IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_DESCRIPTION},
+      {"keyboardAndTextInputHeading",
+       IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_AND_TEXT_INPUT_HEADING},
+      {"keyboardSettingsTitle",
+       IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_TITLE},
+      {"keyboardSettingsDescription",
+       IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_DESCRIPTION},
+      {"mouseAndTouchpadHeading",
+       IDS_SETTINGS_ACCESSIBILITY_MOUSE_AND_TOUCHPAD_HEADING},
+      {"mouseSettingsTitle", IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_TITLE},
+      {"mouseSettingsDescription",
+       IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION},
+      {"audioAndCaptionsHeading",
+       IDS_SETTINGS_ACCESSIBILITY_AUDIO_AND_CAPTIONS_HEADING},
+      {"additionalFeaturesTitle",
+       IDS_SETTINGS_ACCESSIBILITY_ADDITIONAL_FEATURES_TITLE},
+      {"manageTtsSettings", IDS_SETTINGS_MANAGE_TTS_SETTINGS},
+      {"ttsSettingsLinkDescription", IDS_SETTINGS_TTS_LINK_DESCRIPTION},
+      {"textToSpeechVoices", IDS_SETTINGS_TEXT_TO_SPEECH_VOICES},
+      {"textToSpeechNoVoicesMessage",
+       IDS_SETTINGS_TEXT_TO_SPEECH_NO_VOICES_MESSAGE},
+      {"textToSpeechMoreLanguages", IDS_SETTINGS_TEXT_TO_SPEECH_MORE_LANGUAGES},
+      {"textToSpeechProperties", IDS_SETTINGS_TEXT_TO_SPEECH_PROPERTIES},
+      {"textToSpeechRate", IDS_SETTINGS_TEXT_TO_SPEECH_RATE},
+      {"textToSpeechRateMinimumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MINIMUM_LABEL},
+      {"textToSpeechRateMaximumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MAXIMUM_LABEL},
+      {"textToSpeechPitch", IDS_SETTINGS_TEXT_TO_SPEECH_PITCH},
+      {"textToSpeechPitchMinimumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MINIMUM_LABEL},
+      {"textToSpeechPitchMaximumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MAXIMUM_LABEL},
+      {"textToSpeechVolume", IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME},
+      {"textToSpeechVolumeMinimumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MINIMUM_LABEL},
+      {"textToSpeechVolumeMaximumLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MAXIMUM_LABEL},
+      {"percentage", IDS_SETTINGS_PERCENTAGE},
+      {"defaultPercentage", IDS_SETTINGS_DEFAULT_PERCENTAGE},
+      {"textToSpeechPreviewHeading",
+       IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_HEADING},
+      {"textToSpeechPreviewInputLabel",
+       IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT_LABEL},
+      {"textToSpeechPreviewInput", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT},
+      {"textToSpeechPreviewVoice", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_VOICE},
+      {"textToSpeechPreviewPlay", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_PLAY},
+      {"textToSpeechEngines", IDS_SETTINGS_TEXT_TO_SPEECH_ENGINES},
+  };
+  AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+  html_source->AddString("accountManagerLearnMoreUrl",
+                         chrome::kAccountManagerLearnMoreURL);
+  html_source->AddString("a11yLearnMoreUrl",
+                         chrome::kChromeAccessibilityHelpURL);
+
+  base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
+  html_source->AddBoolean(
+      "showExperimentalA11yFeatures",
+      cmd.HasSwitch(::switches::kEnableExperimentalAccessibilityFeatures));
+
+  html_source->AddBoolean(
+      "showExperimentalAccessibilitySwitchAccess",
+      cmd.HasSwitch(::switches::kEnableExperimentalAccessibilitySwitchAccess));
+
+  html_source->AddBoolean(
+      "showExperimentalAccessibilitySwitchAccessImprovedTextInput",
+      cmd.HasSwitch(
+          ::switches::kEnableExperimentalAccessibilitySwitchAccessText));
+}
+
+}  // namespace
+
+void AddOsLocalizedStrings(content::WebUIDataSource* html_source,
+                           Profile* profile,
+                           content::WebContents* web_contents) {
+  AddA11yStrings(html_source);
+}
+
+}  // namespace settings
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h
new file mode 100644
index 0000000..a393390
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h
@@ -0,0 +1,28 @@
+// 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_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+
+class Profile;
+
+namespace content {
+class WebUIDataSource;
+class WebContents;
+}  // namespace content
+
+namespace chromeos {
+namespace settings {
+
+// Adds the strings needed by the OS settings page to |html_source|
+// This function causes |html_source| to expose a strings.js file from its
+// source which contains a mapping from string's name to its translated value.
+void AddOsLocalizedStrings(content::WebUIDataSource* html_source,
+                           Profile* profile,
+                           content::WebContents* web_contents);
+
+}  // namespace settings
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
index 83fe890..291a8d8 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -58,6 +58,7 @@
 #include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h"
@@ -73,6 +74,7 @@
 #include "chrome/browser/ui/webui/settings/settings_cookies_view_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/tts_handler.h"
 #include "chrome/browser/web_applications/system_web_app_manager.h"
 #include "chrome/common/chrome_features.h"
@@ -204,8 +206,15 @@
   html_source->AddResourcePath("app-management/image_info.mojom-lite.js",
                                IDR_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS);
 
-  ::settings::AddLocalizedStrings(html_source, profile,
-                                  web_ui->GetWebContents());
+  ::chromeos::settings::AddOsLocalizedStrings(html_source, profile,
+                                              web_ui->GetWebContents());
+  ::settings::AddSharedLocalizedStrings(html_source, profile,
+                                        web_ui->GetWebContents());
+
+  // TODO(crbug/967888): Remove when all the needed keys have been added
+  // to os_localized_string_provider.
+  ::settings::AddBrowserLocalizedStrings(html_source, profile,
+                                         web_ui->GetWebContents());
 
   auto plural_string_handler = std::make_unique<PluralStringHandler>();
   plural_string_handler->AddLocalizedString("profileLabel",
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 912017f..a98a20a 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/webui/management_ui.h"
 #include "chrome/browser/ui/webui/policy_indicator_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
@@ -212,234 +213,16 @@
 
 void AddA11yStrings(content::WebUIDataSource* html_source) {
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
-    {"a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY},
-    {"a11yWebStore", IDS_SETTINGS_ACCESSIBILITY_WEB_STORE},
-    {"accessibleImageLabelsTitle", IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_TITLE},
-    {"accessibleImageLabelsSubtitle",
-     IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
     {"moreFeaturesLink", IDS_SETTINGS_MORE_FEATURES_LINK},
-    {"moreFeaturesLinkDescription",
-     IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
-    {"captionsTitle", IDS_SETTINGS_CAPTIONS},
-    {"captionsSettings", IDS_SETTINGS_CAPTIONS_SETTINGS},
-    {"captionsPreview", IDS_SETTINGS_CAPTIONS_PREVIEW},
-    {"captionsTextSize", IDS_SETTINGS_CAPTIONS_TEXT_SIZE},
-    {"captionsTextFont", IDS_SETTINGS_CAPTIONS_TEXT_FONT},
-    {"captionsTextColor", IDS_SETTINGS_CAPTIONS_TEXT_COLOR},
-    {"captionsTextOpacity", IDS_SETTINGS_CAPTIONS_TEXT_OPACITY},
-    {"captionsBackgroundOpacity", IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY},
-    {"captionsOpacityOpaque", IDS_SETTINGS_CAPTIONS_OPACITY_OPAQUE},
-    {"captionsOpacitySemiTransparent",
-     IDS_SETTINGS_CAPTIONS_OPACITY_SEMI_TRANSPARENT},
-    {"captionsOpacityTransparent", IDS_SETTINGS_CAPTIONS_OPACITY_TRANSPARENT},
-    {"captionsTextShadow", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW},
-    {"captionsTextShadowNone", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE},
-    {"captionsTextShadowRaised", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED},
-    {"captionsTextShadowDepressed",
-     IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED},
-    {"captionsTextShadowUniform", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM},
-    {"captionsTextShadowDropShadow",
-     IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW},
-    {"captionsBackgroundColor", IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR},
-    {"captionsColorBlack", IDS_SETTINGS_CAPTIONS_COLOR_BLACK},
-    {"captionsColorWhite", IDS_SETTINGS_CAPTIONS_COLOR_WHITE},
-    {"captionsColorRed", IDS_SETTINGS_CAPTIONS_COLOR_RED},
-    {"captionsColorGreen", IDS_SETTINGS_CAPTIONS_COLOR_GREEN},
-    {"captionsColorBlue", IDS_SETTINGS_CAPTIONS_COLOR_BLUE},
-    {"captionsColorYellow", IDS_SETTINGS_CAPTIONS_COLOR_YELLOW},
-    {"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN},
-    {"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA},
-    {"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING},
-    {"captionsEnableLiveCaption", IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION},
-    {"settingsSliderRoleDescription",
-     IDS_SETTINGS_SLIDER_MIN_MAX_ARIA_ROLE_DESCRIPTION},
-#if defined(OS_CHROMEOS)
-    {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
-    {"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL},
-    {"largeMouseCursorSizeLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LABEL},
-    {"largeMouseCursorSizeDefaultLabel",
-     IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_DEFAULT_LABEL},
-    {"largeMouseCursorSizeLargeLabel",
-     IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LARGE_LABEL},
-    {"highContrastLabel", IDS_SETTINGS_HIGH_CONTRAST_LABEL},
-    {"stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL},
-    {"chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL},
-    {"chromeVoxOptionsLabel", IDS_SETTINGS_CHROMEVOX_OPTIONS_LABEL},
-    {"screenMagnifierLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL},
-    {"screenMagnifierZoomLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_LABEL},
-    {"dockedMagnifierLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_LABEL},
-    {"dockedMagnifierZoomLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_ZOOM_LABEL},
-    {"screenMagnifierZoom2x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_2_X},
-    {"screenMagnifierZoom4x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_4_X},
-    {"screenMagnifierZoom6x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_6_X},
-    {"screenMagnifierZoom8x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_8_X},
-    {"screenMagnifierZoom10x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_10_X},
-    {"screenMagnifierZoom12x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_12_X},
-    {"screenMagnifierZoom14x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_14_X},
-    {"screenMagnifierZoom16x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_16_X},
-    {"screenMagnifierZoom18x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_18_X},
-    {"screenMagnifierZoom20x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_20_X},
-    {"tapDraggingLabel", IDS_SETTINGS_TAP_DRAGGING_LABEL},
-    {"clickOnStopLabel", IDS_SETTINGS_CLICK_ON_STOP_LABEL},
-    {"delayBeforeClickLabel", IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL},
-    {"delayBeforeClickExtremelyShort",
-     IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT},
-    {"delayBeforeClickVeryShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT},
-    {"delayBeforeClickShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT},
-    {"delayBeforeClickLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG},
-    {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG},
-    {"autoclickRevertToLeftClick", IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK},
-    {"autoclickStabilizeCursorPosition",
-     IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION},
-    {"autoclickMovementThresholdLabel",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL},
-    {"autoclickMovementThresholdExtraSmall",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_SMALL},
-    {"autoclickMovementThresholdSmall",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_SMALL},
-    {"autoclickMovementThresholdDefault",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_DEFAULT},
-    {"autoclickMovementThresholdLarge",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LARGE},
-    {"autoclickMovementThresholdExtraLarge",
-     IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_LARGE},
-    {"dictationDescription", IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION},
-    {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL},
-    {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL},
-    {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL},
-    {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL},
-    {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION},
-    {"caretHighlightLabel",
-     IDS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION},
-    {"cursorHighlightLabel",
-     IDS_SETTINGS_ACCESSIBILITY_CURSOR_HIGHLIGHT_DESCRIPTION},
-    {"focusHighlightLabel",
-     IDS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION},
-    {"selectToSpeakTitle", IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE},
-    {"selectToSpeakDisabledDescription",
-     IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DISABLED_DESCRIPTION},
-    {"selectToSpeakDescription",
-     IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION},
-    {"selectToSpeakDescriptionWithoutKeyboard",
-     IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION_WITHOUT_KEYBOARD},
-    {"selectToSpeakOptionsLabel",
-     IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_OPTIONS_LABEL},
-    {"switchAccessLabel", IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_DESCRIPTION},
-    {"switchAccessOptionsLabel",
-     IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_OPTIONS_LABEL},
-    {"manageSwitchAccessSettings", IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS},
-    {"switchAssignmentHeading", IDS_SETTINGS_SWITCH_ASSIGNMENT_HEADING},
-    {"switchAssignOptionNone", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_NONE},
-    {"switchAssignOptionSpace", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_SPACE},
-    {"switchAssignOptionEnter", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_ENTER},
-    {"assignSelectSwitchLabel", IDS_SETTINGS_ASSIGN_SELECT_SWITCH_LABEL},
-    {"assignNextSwitchLabel", IDS_SETTINGS_ASSIGN_NEXT_SWITCH_LABEL},
-    {"assignPreviousSwitchLabel", IDS_SETTINGS_ASSIGN_PREVIOUS_SWITCH_LABEL},
-    {"switchAccessAutoScanHeading",
-     IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_HEADING},
-    {"switchAccessAutoScanLabel", IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_LABEL},
-    {"switchAccessAutoScanSpeedLabel",
-     IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_SPEED_LABEL},
-    {"switchAccessAutoScanKeyboardSpeedLabel",
-     IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_KEYBOARD_SPEED_LABEL},
-    {"durationInSeconds", IDS_SETTINGS_DURATION_IN_SECONDS},
-    {"manageAccessibilityFeatures",
-     IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
-    {"textToSpeechHeading", IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_HEADING},
-    {"displayHeading", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_HEADING},
-    {"displaySettingsTitle", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_TITLE},
-    {"displaySettingsDescription",
-     IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_DESCRIPTION},
-    {"appearanceSettingsTitle",
-     IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_TITLE},
-    {"appearanceSettingsDescription",
-     IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_DESCRIPTION},
-    {"keyboardAndTextInputHeading",
-     IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_AND_TEXT_INPUT_HEADING},
-    {"keyboardSettingsTitle",
-     IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_TITLE},
-    {"keyboardSettingsDescription",
-     IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_DESCRIPTION},
-    {"mouseAndTouchpadHeading",
-     IDS_SETTINGS_ACCESSIBILITY_MOUSE_AND_TOUCHPAD_HEADING},
-    {"mouseSettingsTitle", IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_TITLE},
-    {"mouseSettingsDescription",
-     IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION},
-    {"audioAndCaptionsHeading",
-     IDS_SETTINGS_ACCESSIBILITY_AUDIO_AND_CAPTIONS_HEADING},
-    {"additionalFeaturesTitle",
-     IDS_SETTINGS_ACCESSIBILITY_ADDITIONAL_FEATURES_TITLE},
-    {"manageTtsSettings", IDS_SETTINGS_MANAGE_TTS_SETTINGS},
-    {"ttsSettingsLinkDescription", IDS_SETTINGS_TTS_LINK_DESCRIPTION},
-    {"textToSpeechVoices", IDS_SETTINGS_TEXT_TO_SPEECH_VOICES},
-    {"textToSpeechNoVoicesMessage",
-     IDS_SETTINGS_TEXT_TO_SPEECH_NO_VOICES_MESSAGE},
-    {"textToSpeechMoreLanguages", IDS_SETTINGS_TEXT_TO_SPEECH_MORE_LANGUAGES},
-    {"textToSpeechProperties", IDS_SETTINGS_TEXT_TO_SPEECH_PROPERTIES},
-    {"textToSpeechRate", IDS_SETTINGS_TEXT_TO_SPEECH_RATE},
-    {"textToSpeechRateMinimumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MINIMUM_LABEL},
-    {"textToSpeechRateMaximumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MAXIMUM_LABEL},
-    {"textToSpeechPitch", IDS_SETTINGS_TEXT_TO_SPEECH_PITCH},
-    {"textToSpeechPitchMinimumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MINIMUM_LABEL},
-    {"textToSpeechPitchMaximumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MAXIMUM_LABEL},
-    {"textToSpeechVolume", IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME},
-    {"textToSpeechVolumeMinimumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MINIMUM_LABEL},
-    {"textToSpeechVolumeMaximumLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MAXIMUM_LABEL},
-    {"percentage", IDS_SETTINGS_PERCENTAGE},
-    {"defaultPercentage", IDS_SETTINGS_DEFAULT_PERCENTAGE},
-    {"textToSpeechPreviewHeading", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_HEADING},
-    {"textToSpeechPreviewInputLabel",
-     IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT_LABEL},
-    {"textToSpeechPreviewInput", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT},
-    {"textToSpeechPreviewVoice", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_VOICE},
-    {"textToSpeechPreviewPlay", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_PLAY},
-    {"textToSpeechEngines", IDS_SETTINGS_TEXT_TO_SPEECH_ENGINES},
-#endif
   };
   AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
-  html_source->AddBoolean(
-      "showExperimentalA11yLabels",
-      base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels));
-
-  html_source->AddBoolean(
-      "enableCaptionSettings",
-      base::FeatureList::IsEnabled(features::kCaptionSettings));
-
-  html_source->AddBoolean("enableLiveCaption",
-                          base::FeatureList::IsEnabled(media::kLiveCaption));
-
+#if !defined(OS_CHROMEOS)
+  AddSharedA11yStrings(html_source);
+#endif
 #if defined(OS_WIN)
   html_source->AddBoolean("isWindows10OrNewer",
                           base::win::GetVersion() >= base::win::Version::WIN10);
 #endif
-
-#if defined(OS_CHROMEOS)
-  html_source->AddString("accountManagerLearnMoreUrl",
-                         chrome::kAccountManagerLearnMoreURL);
-  html_source->AddString("a11yLearnMoreUrl",
-                         chrome::kChromeAccessibilityHelpURL);
-
-  base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
-  html_source->AddBoolean(
-      "showExperimentalA11yFeatures",
-      cmd.HasSwitch(::switches::kEnableExperimentalAccessibilityFeatures));
-
-  html_source->AddBoolean(
-      "showExperimentalAccessibilitySwitchAccess",
-      cmd.HasSwitch(::switches::kEnableExperimentalAccessibilitySwitchAccess));
-
-  html_source->AddBoolean(
-      "showExperimentalAccessibilitySwitchAccessImprovedTextInput",
-      cmd.HasSwitch(
-          ::switches::kEnableExperimentalAccessibilitySwitchAccessText));
-#endif
 }
 
 void AddAboutStrings(content::WebUIDataSource* html_source) {
@@ -3437,6 +3220,10 @@
        IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL},
       {"securityKeysBioEnrollmentEnrollingLabel",
        IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL},
+      {"securityKeysBioEnrollmentEnrollingFailedLabel",
+       IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_FAILED_LABEL},
+      {"securityKeysBioEnrollmentTryAgainLabel",
+       IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_TRY_AGAIN_LABEL},
       {"securityKeysBioEnrollmentEnrollmentsLabel",
        IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLMENTS_LABEL},
       {"securityKeysBioEnrollmentNoEnrollmentsLabel",
@@ -3532,9 +3319,9 @@
 
 }  // namespace
 
-void AddLocalizedStrings(content::WebUIDataSource* html_source,
-                         Profile* profile,
-                         content::WebContents* web_contents) {
+void AddBrowserLocalizedStrings(content::WebUIDataSource* html_source,
+                                Profile* profile,
+                                content::WebContents* web_contents) {
   AddA11yStrings(html_source);
   AddAboutStrings(html_source);
   AddAutofillStrings(html_source, profile, web_contents);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
index a72290f4..0940dc5 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
@@ -14,12 +14,14 @@
 
 namespace settings {
 
-// Adds the strings needed by the settings page to |html_source|. This function
-// causes |html_source| to expose a strings.js file from its source which
-// contains a mapping from string's name to its translated value.
-void AddLocalizedStrings(content::WebUIDataSource* html_source,
-                         Profile* profile,
-                         content::WebContents* web_contents);
+// Adds the strings needed by the browser settings page to |html_source|
+// This function causes |html_source| to expose a strings.js file from its
+// source which contains a mapping from string's name to its translated value.
+// TODO(crbug/967888): This still contains OS Settings strings. Strings specific
+// to OS settings should be moved to os_settings_localized_strings_provider.cc.
+void AddBrowserLocalizedStrings(content::WebUIDataSource* html_source,
+                                Profile* profile,
+                                content::WebContents* web_contents);
 
 }  // namespace settings
 
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 32a7cdae..c518821 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -47,6 +47,7 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_security_key_handler.h"
 #include "chrome/browser/ui/webui/settings/settings_startup_pages_handler.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/settings/site_settings_handler.h"
 #include "chrome/browser/web_applications/components/app_registrar.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -281,7 +282,8 @@
   html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML);
 #endif
 
-  AddLocalizedStrings(html_source, profile, web_ui->GetWebContents());
+  AddSharedLocalizedStrings(html_source, profile, web_ui->GetWebContents());
+  AddBrowserLocalizedStrings(html_source, profile, web_ui->GetWebContents());
 
   ManagedUIHandler::Initialize(web_ui, html_source);
 
@@ -313,6 +315,9 @@
             account_manager, IdentityManagerFactory::GetForProfile(profile)));
   }
 
+  // MultideviceHandler is required in browser settings to show a special note
+  // under the notification permission that is auto-granted for Android Messages
+  // integration in ChromeOS.
   if (!profile->IsGuestSession()) {
     chromeos::android_sms::AndroidSmsService* android_sms_service =
         chromeos::android_sms::AndroidSmsServiceFactory::GetForBrowserContext(
diff --git a/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc
new file mode 100644
index 0000000..940f9833
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc
@@ -0,0 +1,94 @@
+// 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/ui/webui/settings/shared_settings_localized_strings_provider.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_features.h"
+#include "media/base/media_switches.h"
+
+namespace settings {
+namespace {
+
+void AddA11yStrings(content::WebUIDataSource* html_source) {
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+    {"a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY},
+    {"a11yWebStore", IDS_SETTINGS_ACCESSIBILITY_WEB_STORE},
+    {"moreFeaturesLinkDescription",
+     IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
+    {"accessibleImageLabelsTitle", IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_TITLE},
+    {"accessibleImageLabelsSubtitle",
+     IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
+    {"settingsSliderRoleDescription",
+     IDS_SETTINGS_SLIDER_MIN_MAX_ARIA_ROLE_DESCRIPTION},
+#if defined(OS_CHROMEOS)
+    {"manageAccessibilityFeatures",
+     IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
+#endif  // defined(OS_CHROMEOS)
+  };
+  AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+  html_source->AddBoolean(
+      "showExperimentalA11yLabels",
+      base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels));
+
+  html_source->AddBoolean(
+      "enableCaptionSettings",
+      base::FeatureList::IsEnabled(features::kCaptionSettings));
+
+  html_source->AddBoolean("enableLiveCaption",
+                          base::FeatureList::IsEnabled(media::kLiveCaption));
+}
+
+}  // namespace
+
+void AddSharedLocalizedStrings(content::WebUIDataSource* html_source,
+                               Profile* profile,
+                               content::WebContents* web_contents) {
+  AddA11yStrings(html_source);
+}
+
+void AddSharedA11yStrings(content::WebUIDataSource* html_source) {
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+      {"captionsTitle", IDS_SETTINGS_CAPTIONS},
+      {"captionsSettings", IDS_SETTINGS_CAPTIONS_SETTINGS},
+      {"captionsPreview", IDS_SETTINGS_CAPTIONS_PREVIEW},
+      {"captionsTextSize", IDS_SETTINGS_CAPTIONS_TEXT_SIZE},
+      {"captionsTextFont", IDS_SETTINGS_CAPTIONS_TEXT_FONT},
+      {"captionsTextColor", IDS_SETTINGS_CAPTIONS_TEXT_COLOR},
+      {"captionsTextOpacity", IDS_SETTINGS_CAPTIONS_TEXT_OPACITY},
+      {"captionsBackgroundOpacity", IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY},
+      {"captionsOpacityOpaque", IDS_SETTINGS_CAPTIONS_OPACITY_OPAQUE},
+      {"captionsOpacitySemiTransparent",
+       IDS_SETTINGS_CAPTIONS_OPACITY_SEMI_TRANSPARENT},
+      {"captionsOpacityTransparent", IDS_SETTINGS_CAPTIONS_OPACITY_TRANSPARENT},
+      {"captionsTextShadow", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW},
+      {"captionsTextShadowNone", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE},
+      {"captionsTextShadowRaised", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED},
+      {"captionsTextShadowDepressed",
+       IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED},
+      {"captionsTextShadowUniform", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM},
+      {"captionsTextShadowDropShadow",
+       IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW},
+      {"captionsBackgroundColor", IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR},
+      {"captionsColorBlack", IDS_SETTINGS_CAPTIONS_COLOR_BLACK},
+      {"captionsColorWhite", IDS_SETTINGS_CAPTIONS_COLOR_WHITE},
+      {"captionsColorRed", IDS_SETTINGS_CAPTIONS_COLOR_RED},
+      {"captionsColorGreen", IDS_SETTINGS_CAPTIONS_COLOR_GREEN},
+      {"captionsColorBlue", IDS_SETTINGS_CAPTIONS_COLOR_BLUE},
+      {"captionsColorYellow", IDS_SETTINGS_CAPTIONS_COLOR_YELLOW},
+      {"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN},
+      {"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA},
+      {"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING},
+      {"captionsEnableLiveCaption", IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION},
+  };
+  AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+}  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h
new file mode 100644
index 0000000..c39e49e
--- /dev/null
+++ b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+
+class Profile;
+
+namespace content {
+class WebUIDataSource;
+class WebContents;
+}  // namespace content
+
+namespace settings {
+
+// Adds the strings needed by OS and Browser settings page to |html_source|
+// This function causes |html_source| to expose a strings.js file from its
+// source which contains a mapping from string's name to its translated value.
+void AddSharedLocalizedStrings(content::WebUIDataSource* html_source,
+                               Profile* profile,
+                               content::WebContents* web_contents);
+
+// The set of strings used by the A11y subpage that manages accessibility
+// features, excluding the top-level settings rows which link to this section.
+void AddSharedA11yStrings(content::WebUIDataSource* html_source);
+
+}  // namespace settings
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator.cc b/chrome/browser/web_applications/components/web_app_icon_generator.cc
index 521679c..996e6e1 100644
--- a/chrome/browser/web_applications/components/web_app_icon_generator.cc
+++ b/chrome/browser/web_applications/components/web_app_icon_generator.cc
@@ -31,17 +31,17 @@
 namespace {
 
 // Generates a square container icon of |output_size| by drawing the given
-// |letter| into a rounded background of |color|.
+// |icon_letter| into a rounded background of |color|.
 class GeneratedIconImageSource : public gfx::CanvasImageSource {
  public:
-  explicit GeneratedIconImageSource(base::char16 letter,
+  explicit GeneratedIconImageSource(base::char16 icon_letter,
                                     SkColor color,
                                     SquareSizePx output_size)
       : gfx::CanvasImageSource(gfx::Size(output_size, output_size)),
-        letter_(letter),
+        icon_letter_(icon_letter),
         color_(color),
         output_size_(output_size) {}
-  ~GeneratedIconImageSource() override {}
+  ~GeneratedIconImageSource() override = default;
 
  private:
   // gfx::CanvasImageSource overrides:
@@ -69,13 +69,13 @@
     // The text rect's size needs to be odd to center the text correctly.
     gfx::Rect text_rect(icon_inset, icon_inset, icon_size + 1, icon_size + 1);
     canvas->DrawStringRectWithFlags(
-        base::string16(1, letter_),
+        base::string16(1, icon_letter_),
         gfx::FontList(gfx::Font(font_name, font_size)),
         color_utils::GetColorWithMaxContrast(color_), text_rect,
         gfx::Canvas::TEXT_ALIGN_CENTER);
   }
 
-  base::char16 letter_;
+  base::char16 icon_letter_;
 
   SkColor color_;
 
@@ -85,22 +85,22 @@
 };
 
 // Adds a square container icon of |output_size| and 2 * |output_size| pixels
-// to |bitmaps| by drawing the given |letter| into a rounded background of
+// to |bitmaps| by drawing the given |icon_letter| into a rounded background of
 // |color|. For each size, if an icon of the requested size already exists in
 // |bitmaps|, nothing will happen.
 void GenerateIcon(std::map<SquareSizePx, SkBitmap>* bitmaps,
                   SquareSizePx output_size,
                   SkColor color,
-                  base::char16 letter) {
+                  base::char16 icon_letter) {
   // Do nothing if there is already an icon of |output_size|.
   if (bitmaps->count(output_size))
     return;
 
-  (*bitmaps)[output_size] = GenerateBitmap(output_size, color, letter);
+  (*bitmaps)[output_size] = GenerateBitmap(output_size, color, icon_letter);
 }
 
 void GenerateIcons(std::set<SquareSizePx> generate_sizes,
-                   const GURL& app_url,
+                   base::char16 icon_letter,
                    SkColor generated_icon_color,
                    std::map<SquareSizePx, SkBitmap>* bitmap_map) {
   // If no color has been specified, use a dark gray so it will stand out on the
@@ -108,8 +108,6 @@
   if (generated_icon_color == SK_ColorTRANSPARENT)
     generated_icon_color = SK_ColorDKGRAY;
 
-  const base::char16 icon_letter = GenerateIconLetterFromUrl(app_url);
-
   for (SquareSizePx size : generate_sizes)
     GenerateIcon(bitmap_map, size, generated_icon_color, icon_letter);
 }
@@ -161,10 +159,10 @@
 
 SkBitmap GenerateBitmap(SquareSizePx output_size,
                         SkColor color,
-                        base::char16 letter) {
-  gfx::ImageSkia icon_image(
-      std::make_unique<GeneratedIconImageSource>(letter, color, output_size),
-      gfx::Size(output_size, output_size));
+                        base::char16 icon_letter) {
+  gfx::ImageSkia icon_image(std::make_unique<GeneratedIconImageSource>(
+                                icon_letter, color, output_size),
+                            gfx::Size(output_size, output_size));
   SkBitmap dst;
   if (dst.tryAllocPixels(icon_image.bitmap()->info())) {
     icon_image.bitmap()->readPixels(dst.info(), dst.getPixels(), dst.rowBytes(),
@@ -173,7 +171,6 @@
   return dst;
 }
 
-// Returns the letter that will be painted on the generated icon.
 base::char16 GenerateIconLetterFromUrl(const GURL& app_url) {
   std::string app_url_part = " ";
   const std::string domain_and_registry =
@@ -195,10 +192,15 @@
   return icon_letter;
 }
 
+base::char16 GenerateIconLetterFromAppName(const base::string16& app_name) {
+  CHECK(!app_name.empty());
+  return base::i18n::ToUpper(app_name)[0];
+}
+
 std::map<SquareSizePx, SkBitmap> ResizeIconsAndGenerateMissing(
     const std::vector<SkBitmap>& icons,
     const std::set<SquareSizePx>& sizes_to_generate,
-    const GURL& app_url,
+    base::char16 icon_letter,
     SkColor* generated_icon_color) {
   DCHECK(generated_icon_color);
 
@@ -228,7 +230,7 @@
     if (resized_bitmaps.find(size) == resized_bitmaps.end())
       generate_sizes.insert(size);
   }
-  GenerateIcons(generate_sizes, app_url, *generated_icon_color,
+  GenerateIcons(generate_sizes, icon_letter, *generated_icon_color,
                 &resized_bitmaps);
 
   return resized_bitmaps;
@@ -237,14 +239,12 @@
 std::map<SquareSizePx, SkBitmap> GenerateIcons(const std::string& app_name,
                                                SkColor background_icon_color) {
   const base::string16 app_name_utf16 = base::UTF8ToUTF16(app_name);
-  CHECK(!app_name_utf16.empty());
-  const base::char16 first_app_name_letter =
-      base::i18n::ToUpper(app_name_utf16)[0];
+  const base::char16 icon_letter =
+      GenerateIconLetterFromAppName(app_name_utf16);
 
   std::map<SquareSizePx, SkBitmap> icons;
   for (SquareSizePx size : SizesToGenerate()) {
-    icons[size] =
-        GenerateBitmap(size, background_icon_color, first_app_name_letter);
+    icons[size] = GenerateBitmap(size, background_icon_color, icon_letter);
   }
   return icons;
 }
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator.h b/chrome/browser/web_applications/components/web_app_icon_generator.h
index cd845aca9..4832fe86 100644
--- a/chrome/browser/web_applications/components/web_app_icon_generator.h
+++ b/chrome/browser/web_applications/components/web_app_icon_generator.h
@@ -49,22 +49,28 @@
     const std::set<SquareSizePx>& sizes);
 
 // Generates a square container icon of |output_size| by drawing the given
-// |letter| into a rounded background of |color|.
+// |icon_letter| into a rounded background of |color|.
 SkBitmap GenerateBitmap(SquareSizePx output_size,
                         SkColor color,
-                        base::char16 letter);
+                        base::char16 icon_letter);
 
-// Returns the letter that will be painted on the generated icon.
+// Returns the first letter from |app_url| that will be painted on the generated
+// icon.
 base::char16 GenerateIconLetterFromUrl(const GURL& app_url);
 
+// Returns the first letter from |app_name| that will be painted on the
+// generated icon.
+base::char16 GenerateIconLetterFromAppName(const base::string16& app_name);
+
 // Resize icons to the accepted sizes, and generate any that are missing.
-// Note that |app_url| is the launch URL for the app.
+// Note that |icon_letter| is the first letter of app name if available
+// otherwise the first letter of app url.
 // Output: |generated_icon_color| is the color to use if an icon needs to be
 // generated for the web app.
 std::map<SquareSizePx, SkBitmap> ResizeIconsAndGenerateMissing(
     const std::vector<SkBitmap>& icons,
     const std::set<SquareSizePx>& sizes_to_generate,
-    const GURL& app_url,
+    base::char16 icon_letter,
     SkColor* generated_icon_color);
 
 // Generate icons for default sizes, using the first letter of the application
diff --git a/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
index 9b38631b..8f8eba1 100644
--- a/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_icon_generator_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "build/build_config.h"
 #include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
@@ -29,7 +30,9 @@
 
 std::set<int> TestSizesToGenerate() {
   const int kIconSizesToGenerate[] = {
-      icon_size::k32, icon_size::k48, icon_size::k128,
+      icon_size::k32,
+      icon_size::k48,
+      icon_size::k128,
   };
   return std::set<int>(kIconSizesToGenerate,
                        kIconSizesToGenerate + base::size(kIconSizesToGenerate));
@@ -151,7 +154,9 @@
   // Now run the resizing/generation and validation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   auto size_map = ResizeIconsAndGenerateMissing(
-      downloaded, TestSizesToGenerate(), GURL(), &generated_icon_color);
+      downloaded, TestSizesToGenerate(),
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
 
   ValidateIconsGeneratedAndResizedCorrectly(
       downloaded, size_map, TestSizesToGenerate(), expected_generated,
@@ -236,7 +241,9 @@
   // Now run the resizing and generation into a new web icons info.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   std::map<int, SkBitmap> size_map = ResizeIconsAndGenerateMissing(
-      downloaded, sizes, GURL(), &generated_icon_color);
+      downloaded, sizes,
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
   EXPECT_EQ(sizes.size(), size_map.size());
 
   // Now check that the linked app icons are matching.
@@ -258,7 +265,9 @@
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   std::map<int, SkBitmap> size_map = ResizeIconsAndGenerateMissing(
-      downloaded, TestSizesToGenerate(), GURL(), &generated_icon_color);
+      downloaded, TestSizesToGenerate(),
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
 
   // No icons should be generated. The LARGE and MEDIUM sizes should be resized.
   ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map,
@@ -276,7 +285,9 @@
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   std::map<int, SkBitmap> size_map = ResizeIconsAndGenerateMissing(
-      downloaded, TestSizesToGenerate(), GURL(), &generated_icon_color);
+      downloaded, TestSizesToGenerate(),
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
 
   // Expect icon for MEDIUM and LARGE to be resized from the gigantor icon
   // as it was not downloaded.
@@ -291,7 +302,9 @@
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   std::map<int, SkBitmap> size_map = ResizeIconsAndGenerateMissing(
-      downloaded, TestSizesToGenerate(), GURL(), &generated_icon_color);
+      downloaded, TestSizesToGenerate(),
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
 
   // Expect all icons to be generated.
   ValidateIconsGeneratedAndResizedCorrectly(downloaded, size_map,
@@ -308,7 +321,9 @@
   // Now run the resizing and generation.
   SkColor generated_icon_color = SK_ColorTRANSPARENT;
   std::map<int, SkBitmap> size_map = ResizeIconsAndGenerateMissing(
-      downloaded, TestSizesToGenerate(), GURL(), &generated_icon_color);
+      downloaded, TestSizesToGenerate(),
+      GenerateIconLetterFromAppName(base::UTF8ToUTF16("Test")),
+      &generated_icon_color);
 
   // Expect no icons to be generated, but the LARGE and SMALL icons to be
   // resized from the MEDIUM icon.
@@ -343,6 +358,17 @@
             GenerateIconLetterFromUrl(GURL("http://xn--mgbh0fb.example/")));
 }
 
+TEST_F(WebAppIconGeneratorTest, GenerateIconLetterFromAppName) {
+  // ASCII Encoding
+  EXPECT_EQ('T',
+            GenerateIconLetterFromAppName(base::ASCIIToUTF16("test app name")));
+  EXPECT_EQ('T',
+            GenerateIconLetterFromAppName(base::ASCIIToUTF16("Test app name")));
+  // UTF16 encoding:
+  const base::char16 russian_name[] = {0x0438, 0x043c, 0x044f, 0x0};
+  EXPECT_EQ(0x0418, GenerateIconLetterFromAppName(russian_name));
+}
+
 TEST_F(WebAppIconGeneratorTest, GenerateIcons) {
   std::set<int> sizes = SizesToGenerate();
   const SkColor bg_color = SK_ColorCYAN;
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 54f59ce..029967a 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -153,11 +153,15 @@
       sizes_to_generate.insert(icon.square_size_px);
   }
 
+  base::char16 icon_letter =
+      web_app_info->title.empty()
+          ? GenerateIconLetterFromUrl(web_app_info->app_url)
+          : GenerateIconLetterFromAppName(web_app_info->title);
   web_app_info->generated_icon_color = SK_ColorTRANSPARENT;
   // TODO(https://crbug.com/1029223): Don't resize before writing to disk, it's
   // not necessary and would simplify this code path to remove.
   std::map<SquareSizePx, SkBitmap> size_to_icon = ResizeIconsAndGenerateMissing(
-      square_icons, sizes_to_generate, web_app_info->app_url,
+      square_icons, sizes_to_generate, icon_letter,
       &web_app_info->generated_icon_color);
 
   for (std::pair<const SquareSizePx, SkBitmap>& item : size_to_icon) {
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn
index 53d47ea..095a764 100644
--- a/chrome/chrome_cleaner/BUILD.gn
+++ b/chrome/chrome_cleaner/BUILD.gn
@@ -20,9 +20,7 @@
 
 group("engine_definitions") {
   if (is_internal_chrome_cleaner_build) {
-    deps = [
-      "${chrome_cleaner_internal_root}:engine_definitions",
-    ]
+    deps = [ "${chrome_cleaner_internal_root}:engine_definitions" ]
   } else {
     deps = [
       "//chrome/chrome_cleaner/engines/common:dummy_engine_resources",
@@ -33,9 +31,7 @@
 
 group("engine_target_factory") {
   if (is_internal_chrome_cleaner_build) {
-    deps = [
-      "${chrome_cleaner_internal_root}:engine_target_factory",
-    ]
+    deps = [ "${chrome_cleaner_internal_root}:engine_target_factory" ]
   } else {
     deps = [
       "//chrome/chrome_cleaner/engines/target:dummy_engine_delegate_factory",
@@ -64,9 +60,7 @@
 }
 
 test("chrome_cleaner_unittests") {
-  sources = [
-    "//chrome/chrome_cleaner/test/test_main.cc",
-  ]
+  sources = [ "//chrome/chrome_cleaner/test/test_main.cc" ]
 
   deps = [
     # Dependencies of the test harness.
diff --git a/chrome/chrome_cleaner/chrome_utils/BUILD.gn b/chrome/chrome_cleaner/chrome_utils/BUILD.gn
index 2b8d5ab..dc6d5e6 100644
--- a/chrome/chrome_cleaner/chrome_utils/BUILD.gn
+++ b/chrome/chrome_cleaner/chrome_utils/BUILD.gn
@@ -42,13 +42,9 @@
     "force_installed_extension.h",
   ]
 
-  deps = [
-    ":extension_id",
-  ]
+  deps = [ ":extension_id" ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:shared_data_proto" ]
 
   all_dependent_configs = [ "//third_party/protobuf:using_proto" ]
 }
@@ -91,7 +87,5 @@
     "extension_id.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/chrome/chrome_cleaner/constants/BUILD.gn b/chrome/chrome_cleaner/constants/BUILD.gn
index 77a3969..66660ef 100644
--- a/chrome/chrome_cleaner/constants/BUILD.gn
+++ b/chrome/chrome_cleaner/constants/BUILD.gn
@@ -19,9 +19,7 @@
 }
 
 process_version("chrome_cleanup_tool_branding_header") {
-  sources = [
-    cleaner_branding_path,
-  ]
+  sources = [ cleaner_branding_path ]
 
   template_file = "branding.h.in"
 
@@ -29,9 +27,7 @@
 }
 
 process_version("software_reporter_tool_branding_header") {
-  sources = [
-    reporter_branding_path,
-  ]
+  sources = [ reporter_branding_path ]
 
   template_file = "branding.h.in"
 
@@ -70,15 +66,11 @@
     "common_registry_names.h",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner:buildflags",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner:buildflags" ]
 }
 
 source_set("uws_id") {
-  sources = [
-    "uws_id.h",
-  ]
+  sources = [ "uws_id.h" ]
 }
 
 source_set("quarantine_constants") {
diff --git a/chrome/chrome_cleaner/engines/broker/BUILD.gn b/chrome/chrome_cleaner/engines/broker/BUILD.gn
index bb01b7c..4ecde9e 100644
--- a/chrome/chrome_cleaner/engines/broker/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/broker/BUILD.gn
@@ -63,9 +63,7 @@
 }
 
 source_set("disabled_cleaner_sandbox_interface") {
-  sources = [
-    "noop_cleaner_engine_requests_impl.cc",
-  ]
+  sources = [ "noop_cleaner_engine_requests_impl.cc" ]
 
   deps = [
     ":common",
@@ -112,9 +110,7 @@
 }
 
 source_set("interface_metadata_observer") {
-  sources = [
-    "interface_metadata_observer.h",
-  ]
+  sources = [ "interface_metadata_observer.h" ]
 }
 
 source_set("noop_interface_metadata_observer") {
@@ -141,9 +137,8 @@
     "//chrome/chrome_cleaner/os:common_os",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:interface_logger_proto",
-  ]
+  public_deps =
+      [ "//chrome/chrome_cleaner/logging/proto:interface_logger_proto" ]
 
   all_dependent_configs = [ "//third_party/protobuf:using_proto" ]
 }
diff --git a/chrome/chrome_cleaner/engines/common/BUILD.gn b/chrome/chrome_cleaner/engines/common/BUILD.gn
index a4fd208..089a258 100644
--- a/chrome/chrome_cleaner/engines/common/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/common/BUILD.gn
@@ -25,23 +25,15 @@
 }
 
 source_set("resources_header") {
-  sources = [
-    "engine_resources.h",
-  ]
+  sources = [ "engine_resources.h" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:shared_data_proto" ]
 }
 
 source_set("dummy_engine_resources") {
-  sources = [
-    "dummy_engine_resources.cc",
-  ]
+  sources = [ "dummy_engine_resources.cc" ]
 
   deps = [
     ":resources_header",
@@ -53,9 +45,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "registry_util_unittest.cc",
-  ]
+  sources = [ "registry_util_unittest.cc" ]
 
   deps = [
     ":common",
diff --git a/chrome/chrome_cleaner/engines/controllers/BUILD.gn b/chrome/chrome_cleaner/engines/controllers/BUILD.gn
index d2052d0a..ddbbd47 100644
--- a/chrome/chrome_cleaner/engines/controllers/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/controllers/BUILD.gn
@@ -94,9 +94,7 @@
 }
 
 source_set("facade_interface_header") {
-  sources = [
-    "engine_facade_interface.h",
-  ]
+  sources = [ "engine_facade_interface.h" ]
 
   deps = [
     "//base",
diff --git a/chrome/chrome_cleaner/engines/target/BUILD.gn b/chrome/chrome_cleaner/engines/target/BUILD.gn
index 905752e..31d0134 100644
--- a/chrome/chrome_cleaner/engines/target/BUILD.gn
+++ b/chrome/chrome_cleaner/engines/target/BUILD.gn
@@ -46,30 +46,22 @@
     "//sandbox/win:sandbox",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:shared_data_proto" ]
 }
 
 source_set("engine_delegate_factory_header") {
-  sources = [
-    "engine_delegate_factory.h",
-  ]
+  sources = [ "engine_delegate_factory.h" ]
 
   deps = [
     ":common",
     "//base",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:shared_data_proto" ]
 }
 
 source_set("dummy_engine_delegate_factory") {
-  sources = [
-    "dummy_engine_delegate_factory.cc",
-  ]
+  sources = [ "dummy_engine_delegate_factory.cc" ]
 
   deps = [
     ":engine_delegate_factory_header",
diff --git a/chrome/chrome_cleaner/executables/BUILD.gn b/chrome/chrome_cleaner/executables/BUILD.gn
index c3812b3f..7768734 100644
--- a/chrome/chrome_cleaner/executables/BUILD.gn
+++ b/chrome/chrome_cleaner/executables/BUILD.gn
@@ -9,9 +9,7 @@
 
 group("engine_target_factory") {
   if (is_internal_chrome_cleaner_build) {
-    deps = [
-      "${chrome_cleaner_internal_root}:engine_target_factory",
-    ]
+    deps = [ "${chrome_cleaner_internal_root}:engine_target_factory" ]
   } else {
     deps = [
       "//chrome/chrome_cleaner/engines/target:dummy_engine_delegate_factory",
@@ -96,9 +94,7 @@
 }
 
 chrome_cleaner_executable("chrome_cleanup_tool") {
-  sources = [
-    "chrome_cleaner_main.cc",
-  ]
+  sources = [ "chrome_cleaner_main.cc" ]
 
   libs = [ "comctl32.lib" ]
 
@@ -123,9 +119,7 @@
 }
 
 chrome_cleaner_executable("software_reporter_tool") {
-  sources = [
-    "chrome_reporter_main.cc",
-  ]
+  sources = [ "chrome_reporter_main.cc" ]
 
   deps = [
     "//chrome/chrome_cleaner/constants:reporter_version_resource",
diff --git a/chrome/chrome_cleaner/http/BUILD.gn b/chrome/chrome_cleaner/http/BUILD.gn
index 2dc8b69..bd84eed 100644
--- a/chrome/chrome_cleaner/http/BUILD.gn
+++ b/chrome/chrome_cleaner/http/BUILD.gn
@@ -6,9 +6,7 @@
 visibility = [ "//chrome/chrome_cleaner/*" ]
 
 source_set("http_status_codes") {
-  sources = [
-    "http_status_codes.h",
-  ]
+  sources = [ "http_status_codes.h" ]
 }
 
 source_set("http") {
diff --git a/chrome/chrome_cleaner/logging/BUILD.gn b/chrome/chrome_cleaner/logging/BUILD.gn
index 42471a4..218a1de 100644
--- a/chrome/chrome_cleaner/logging/BUILD.gn
+++ b/chrome/chrome_cleaner/logging/BUILD.gn
@@ -13,9 +13,7 @@
     "scoped_timed_task_logger.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("common") {
@@ -67,17 +65,13 @@
 }
 
 source_set("logging_definitions") {
-  sources = [
-    "logging_definitions.h",
-  ]
+  sources = [ "logging_definitions.h" ]
 }
 
 # Logging definitions that must only by linked into the cleaner executable.
 # This is separate from cleaner_logging, which is also linked with unit tests.
 source_set("cleaner_logging_definitions") {
-  sources = [
-    "cleaner_logging_definitions.cc",
-  ]
+  sources = [ "cleaner_logging_definitions.cc" ]
 
   deps = [
     ":cleaner_logging",
@@ -88,9 +82,7 @@
 # Logging definitions that must only by linked into the reporter executable.
 # This is separate from reporter_logging, which is also linked with unit tests.
 source_set("reporter_logging_definitions") {
-  sources = [
-    "reporter_logging_definitions.cc",
-  ]
+  sources = [ "reporter_logging_definitions.cc" ]
 
   deps = [
     ":logging_definitions",
@@ -102,9 +94,7 @@
 
 # Logging definitions that are linked into all other executables.
 source_set("other_logging_definitions") {
-  sources = [
-    "other_logging_definitions.cc",
-  ]
+  sources = [ "other_logging_definitions.cc" ]
 
   deps = [
     ":logging_definitions",
@@ -113,30 +103,20 @@
 }
 
 source_set("api_keys_header") {
-  sources = [
-    "api_keys.h",
-  ]
+  sources = [ "api_keys.h" ]
 }
 
 source_set("dummy_api_keys") {
-  sources = [
-    "dummy_api_keys.cc",
-  ]
+  sources = [ "dummy_api_keys.cc" ]
 
-  deps = [
-    ":api_keys_header",
-  ]
+  deps = [ ":api_keys_header" ]
 }
 
 group("api_keys") {
   if (is_internal_chrome_cleaner_build) {
-    deps = [
-      "${chrome_cleaner_internal_root}/logging:api_keys",
-    ]
+    deps = [ "${chrome_cleaner_internal_root}/logging:api_keys" ]
   } else {
-    deps = [
-      ":dummy_api_keys",
-    ]
+    deps = [ ":dummy_api_keys" ]
   }
 }
 
diff --git a/chrome/chrome_cleaner/logging/proto/BUILD.gn b/chrome/chrome_cleaner/logging/proto/BUILD.gn
index 5b65130..c6106ad4 100644
--- a/chrome/chrome_cleaner/logging/proto/BUILD.gn
+++ b/chrome/chrome_cleaner/logging/proto/BUILD.gn
@@ -8,39 +8,29 @@
 visibility = [ "//chrome/chrome_cleaner/*" ]
 
 proto_library("shared_data_proto") {
-  sources = [
-    "shared_data.proto",
-  ]
+  sources = [ "shared_data.proto" ]
 
   link_deps = [ ":removal_status_proto" ]
 }
 
 proto_library("chrome_cleaner_report_proto") {
-  sources = [
-    "chrome_cleaner_report.proto",
-  ]
+  sources = [ "chrome_cleaner_report.proto" ]
 
   link_deps = [ ":shared_data_proto" ]
 }
 
 proto_library("removal_status_proto") {
-  sources = [
-    "removal_status.proto",
-  ]
+  sources = [ "removal_status.proto" ]
 }
 
 proto_library("reporter_logs_proto") {
-  sources = [
-    "reporter_logs.proto",
-  ]
+  sources = [ "reporter_logs.proto" ]
 
   link_deps = [ ":shared_data_proto" ]
 }
 
 proto_library("interface_logger_proto") {
-  sources = [
-    "interface_logger.proto",
-  ]
+  sources = [ "interface_logger.proto" ]
 }
 
 # A target that depends on all the protos and protobuf libs imported directly
diff --git a/chrome/chrome_cleaner/mojom/BUILD.gn b/chrome/chrome_cleaner/mojom/BUILD.gn
index 680e1ed0..d571f9b 100644
--- a/chrome/chrome_cleaner/mojom/BUILD.gn
+++ b/chrome/chrome_cleaner/mojom/BUILD.gn
@@ -19,13 +19,9 @@
 }
 
 chrome_cleaner_mojom("chrome_prompt_interface") {
-  sources = [
-    "chrome_prompt.mojom",
-  ]
+  sources = [ "chrome_prompt.mojom" ]
 
-  deps = [
-    ":footprints_interface",
-  ]
+  deps = [ ":footprints_interface" ]
 
   # NOTE: We avoid scrambling message IDs here because these messages cross an
   # IPC boundary to an external program built from a different source tree.
@@ -33,9 +29,7 @@
 }
 
 chrome_cleaner_mojom("footprints_interface") {
-  sources = [
-    "footprints.mojom",
-  ]
+  sources = [ "footprints.mojom" ]
 }
 
 chrome_cleaner_mojom("engine_sandbox_interface") {
@@ -55,18 +49,12 @@
 }
 
 chrome_cleaner_mojom("parser_interface") {
-  sources = [
-    "parser_interface.mojom",
-  ]
-  deps = [
-    "//mojo/public/mojom/base",
-  ]
+  sources = [ "parser_interface.mojom" ]
+  deps = [ "//mojo/public/mojom/base" ]
 }
 
 chrome_cleaner_mojom("zip_archiver_interface") {
-  sources = [
-    "zip_archiver.mojom",
-  ]
+  sources = [ "zip_archiver.mojom" ]
 }
 
 chrome_cleaner_mojom("engine_sandbox_test_interface") {
@@ -77,15 +65,11 @@
     "test_string16_embedded_nulls.mojom",
   ]
 
-  deps = [
-    ":engine_sandbox_interface",
-  ]
+  deps = [ ":engine_sandbox_interface" ]
 }
 
 chrome_cleaner_mojom("mojo_sandbox_hooks_test_interface") {
   testonly = true
 
-  sources = [
-    "test_mojo_sandbox_hooks.mojom",
-  ]
+  sources = [ "test_mojo_sandbox_hooks.mojom" ]
 }
diff --git a/chrome/chrome_cleaner/os/BUILD.gn b/chrome/chrome_cleaner/os/BUILD.gn
index c71cbc2..95d5d45 100644
--- a/chrome/chrome_cleaner/os/BUILD.gn
+++ b/chrome/chrome_cleaner/os/BUILD.gn
@@ -80,9 +80,7 @@
 }
 
 source_set("file_remover_api") {
-  sources = [
-    "file_remover_api.h",
-  ]
+  sources = [ "file_remover_api.h" ]
 
   deps = [
     "//base",
@@ -118,9 +116,7 @@
     "//sandbox/win:sandbox",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:removal_status_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:removal_status_proto" ]
 }
 
 source_set("unittest_sources") {
diff --git a/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn b/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn
index e161c430..3b03691 100644
--- a/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn
+++ b/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn
@@ -11,9 +11,7 @@
     "json_splicer.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 static_library("json_parser") {
@@ -43,9 +41,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "json_splicer_unittest.cc",
-  ]
+  sources = [ "json_splicer_unittest.cc" ]
 
   deps = [
     ":json_parser",
diff --git a/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn b/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn
index 9264319..a7550359d 100644
--- a/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn
+++ b/chrome/chrome_cleaner/parsers/parser_utils/BUILD.gn
@@ -11,9 +11,7 @@
     "parse_tasks_remaining_counter.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 static_library("command_line_arguments_sanitizer") {
@@ -31,9 +29,7 @@
 
 source_set("unittest_sources") {
   testonly = true
-  sources = [
-    "command_line_arguments_sanitizer_unittest.cc",
-  ]
+  sources = [ "command_line_arguments_sanitizer_unittest.cc" ]
   deps = [
     ":command_line_arguments_sanitizer",
     "//base",
diff --git a/chrome/chrome_cleaner/parsers/shortcut_parser/broker/BUILD.gn b/chrome/chrome_cleaner/parsers/shortcut_parser/broker/BUILD.gn
index 09ed07b..428f1cf 100644
--- a/chrome/chrome_cleaner/parsers/shortcut_parser/broker/BUILD.gn
+++ b/chrome/chrome_cleaner/parsers/shortcut_parser/broker/BUILD.gn
@@ -51,9 +51,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "sandboxed_shortcut_parser_unittest.cc",
-  ]
+  sources = [ "sandboxed_shortcut_parser_unittest.cc" ]
   deps = [
     ":sandboxed_shortcut_parser",
     "//base",
diff --git a/chrome/chrome_cleaner/parsers/shortcut_parser/target/BUILD.gn b/chrome/chrome_cleaner/parsers/shortcut_parser/target/BUILD.gn
index eb10aee..05ff0a6 100644
--- a/chrome/chrome_cleaner/parsers/shortcut_parser/target/BUILD.gn
+++ b/chrome/chrome_cleaner/parsers/shortcut_parser/target/BUILD.gn
@@ -19,9 +19,7 @@
 }
 
 fuzzer_test("lnk_parser_fuzzer") {
-  sources = [
-    "lnk_parser_fuzzer.cc",
-  ]
+  sources = [ "lnk_parser_fuzzer.cc" ]
 
   deps = [
     ":lnk_parser",
@@ -35,9 +33,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "lnk_parser_unittest.cc",
-  ]
+  sources = [ "lnk_parser_unittest.cc" ]
 
   deps = [
     ":lnk_parser",
diff --git a/chrome/chrome_cleaner/parsers/target/BUILD.gn b/chrome/chrome_cleaner/parsers/target/BUILD.gn
index 02c1dc4..8f671f5 100644
--- a/chrome/chrome_cleaner/parsers/target/BUILD.gn
+++ b/chrome/chrome_cleaner/parsers/target/BUILD.gn
@@ -31,9 +31,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "parser_impl_unittest.cc",
-  ]
+  sources = [ "parser_impl_unittest.cc" ]
   deps = [
     ":parser_sandbox_target",
     "//base",
diff --git a/chrome/chrome_cleaner/proto/BUILD.gn b/chrome/chrome_cleaner/proto/BUILD.gn
index 11cdf9e..b6ac1049 100644
--- a/chrome/chrome_cleaner/proto/BUILD.gn
+++ b/chrome/chrome_cleaner/proto/BUILD.gn
@@ -8,29 +8,21 @@
 visibility = [ "//chrome/chrome_cleaner/*" ]
 
 proto_library("uwe_matcher_proto") {
-  sources = [
-    "uwe_matcher.proto",
-  ]
+  sources = [ "uwe_matcher.proto" ]
 
   link_deps = [ ":uws_spec_by_version_proto" ]
 }
 
 proto_library("file_digest_proto") {
-  sources = [
-    "file_digest.proto",
-  ]
+  sources = [ "file_digest.proto" ]
 }
 
 proto_library("shared_pup_enums_proto") {
-  sources = [
-    "shared_pup_enums.proto",
-  ]
+  sources = [ "shared_pup_enums.proto" ]
 }
 
 proto_library("uws_spec_by_version_proto") {
-  sources = [
-    "uws_spec_by_version.proto",
-  ]
+  sources = [ "uws_spec_by_version.proto" ]
 
   link_deps = [ ":shared_pup_enums_proto" ]
 }
diff --git a/chrome/chrome_cleaner/pup_data/BUILD.gn b/chrome/chrome_cleaner/pup_data/BUILD.gn
index c0b924b3..37d4a6e6 100644
--- a/chrome/chrome_cleaner/pup_data/BUILD.gn
+++ b/chrome/chrome_cleaner/pup_data/BUILD.gn
@@ -43,9 +43,7 @@
     "//chrome/chrome_cleaner/os:common_os",
   ]
 
-  public_deps = [
-    "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
-  ]
+  public_deps = [ "//chrome/chrome_cleaner/logging/proto:shared_data_proto" ]
 }
 
 source_set("dynamic_pup") {
@@ -54,9 +52,7 @@
     "dynamic_pup.h",
   ]
 
-  deps = [
-    ":pup_data_base",
-  ]
+  deps = [ ":pup_data_base" ]
 }
 
 source_set("test_uws") {
@@ -67,9 +63,7 @@
     "test_uws.h",
   ]
 
-  deps = [
-    "//chrome/chrome_cleaner/constants:uws_id",
-  ]
+  deps = [ "//chrome/chrome_cleaner/constants:uws_id" ]
 }
 
 source_set("unittest_sources") {
diff --git a/chrome/chrome_cleaner/scanner/BUILD.gn b/chrome/chrome_cleaner/scanner/BUILD.gn
index f837a525..3691530 100644
--- a/chrome/chrome_cleaner/scanner/BUILD.gn
+++ b/chrome/chrome_cleaner/scanner/BUILD.gn
@@ -6,13 +6,9 @@
 visibility = [ "//chrome/chrome_cleaner/*" ]
 
 source_set("signature_matcher_api") {
-  sources = [
-    "signature_matcher_api.h",
-  ]
+  sources = [ "signature_matcher_api.h" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("matcher_util") {
@@ -46,9 +42,7 @@
 }
 
 source_set("scanner_api") {
-  sources = [
-    "scanner.h",
-  ]
+  sources = [ "scanner.h" ]
 
   deps = [
     "//base",
@@ -122,9 +116,7 @@
 }
 
 source_set("force_installed_extension_scanner_api") {
-  sources = [
-    "force_installed_extension_scanner.h",
-  ]
+  sources = [ "force_installed_extension_scanner.h" ]
 
   deps = [
     "//chrome/chrome_cleaner/chrome_utils:force_installed_extension",
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn
index c49f48c5..eaf8ba3 100644
--- a/chrome/chrome_cleaner/settings/BUILD.gn
+++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -6,9 +6,7 @@
 visibility = [ "//chrome/chrome_cleaner/*" ]
 
 source_set("engine_settings_header") {
-  sources = [
-    "engine_settings.h",
-  ]
+  sources = [ "engine_settings.h" ]
 
   public_deps = [
     "//chrome/chrome_cleaner/logging/proto:shared_data_proto",
@@ -17,19 +15,13 @@
 }
 
 source_set("dummy_engine_settings") {
-  sources = [
-    "dummy_engine_settings.cc",
-  ]
+  sources = [ "dummy_engine_settings.cc" ]
 
-  deps = [
-    ":engine_settings_header",
-  ]
+  deps = [ ":engine_settings_header" ]
 }
 
 source_set("settings_types") {
-  sources = [
-    "settings_types.h",
-  ]
+  sources = [ "settings_types.h" ]
 }
 
 source_set("settings") {
@@ -55,42 +47,28 @@
 }
 
 source_set("settings_definitions") {
-  sources = [
-    "settings_definitions.h",
-  ]
+  sources = [ "settings_definitions.h" ]
 }
 
 # Settings definitions that must only by linked into the cleaner executable.
 source_set("cleaner_settings_definitions") {
-  sources = [
-    "cleaner_settings_definitions.cc",
-  ]
+  sources = [ "cleaner_settings_definitions.cc" ]
 
-  deps = [
-    ":settings_definitions",
-  ]
+  deps = [ ":settings_definitions" ]
 }
 
 # Settings definitions that must only by linked into the reporter executable.
 source_set("reporter_settings_definitions") {
-  sources = [
-    "reporter_settings_definitions.cc",
-  ]
+  sources = [ "reporter_settings_definitions.cc" ]
 
-  deps = [
-    ":settings_definitions",
-  ]
+  deps = [ ":settings_definitions" ]
 }
 
 # Settings definitions that are linked into all other executables.
 source_set("other_settings_definitions") {
-  sources = [
-    "other_settings_definitions.cc",
-  ]
+  sources = [ "other_settings_definitions.cc" ]
 
-  deps = [
-    ":settings_definitions",
-  ]
+  deps = [ ":settings_definitions" ]
 }
 
 source_set("matching_options") {
@@ -106,13 +84,9 @@
     "default_matching_options.h",
   ]
 
-  deps = [
-    ":settings",
-  ]
+  deps = [ ":settings" ]
 
-  public_deps = [
-    ":matching_options",
-  ]
+  public_deps = [ ":matching_options" ]
 }
 
 source_set("unittest_sources") {
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn
index 5ac0b89..e0dab77d 100644
--- a/chrome/chrome_cleaner/test/BUILD.gn
+++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -8,9 +8,7 @@
 # Targets used by tests.
 
 shared_library("empty_dll") {
-  sources = [
-    "empty_dll.cc",
-  ]
+  sources = [ "empty_dll.cc" ]
 
   configs += [
     # This is required to prevent this target from having to be rebuilt every
@@ -25,17 +23,13 @@
     "scoped_file.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_branding_header") {
   testonly = true
 
-  sources = [
-    "test_branding.h",
-  ]
+  sources = [ "test_branding.h" ]
 }
 
 source_set("test_component") {
@@ -275,9 +269,7 @@
 executable("test_process") {
   testonly = true
 
-  sources = [
-    "test_process_main.cc",
-  ]
+  sources = [ "test_process_main.cc" ]
 
   deps = [
     ":test_strings",
@@ -294,9 +286,7 @@
 executable("test_service") {
   testonly = true
 
-  sources = [
-    "test_service_main.cc",
-  ]
+  sources = [ "test_service_main.cc" ]
 
   deps = [
     ":test_strings",
diff --git a/chrome/chrome_cleaner/test/resources/BUILD.gn b/chrome/chrome_cleaner/test/resources/BUILD.gn
index 8b6a9cf6..bfeb69d 100644
--- a/chrome/chrome_cleaner/test/resources/BUILD.gn
+++ b/chrome/chrome_cleaner/test/resources/BUILD.gn
@@ -21,13 +21,9 @@
     "//third_party/protobuf:py_proto",
   ]
 
-  inputs = [
-    sample_dll_file,
-  ]
+  inputs = [ sample_dll_file ]
 
-  outputs = [
-    sample_dll_digest_pb_file,
-  ]
+  outputs = [ sample_dll_digest_pb_file ]
 
   args = [
     "--output",
@@ -53,17 +49,11 @@
     "generated_resources_dir=" + rebase_path(target_gen_dir, root_build_dir),
   ]
 
-  deps = [
-    ":compute_sample_dll_digest",
-  ]
+  deps = [ ":compute_sample_dll_digest" ]
 }
 
 copy("signed_empty_dll") {
-  sources = [
-    "signed_dll/signed_empty_dll.dll",
-  ]
+  sources = [ "signed_dll/signed_empty_dll.dll" ]
 
-  outputs = [
-    "$root_out_dir/signed_empty_dll.dll",
-  ]
+  outputs = [ "$root_out_dir/signed_empty_dll.dll" ]
 }
diff --git a/chrome/chrome_cleaner/tools/BUILD.gn b/chrome/chrome_cleaner/tools/BUILD.gn
index 4c5da25..290c412e 100644
--- a/chrome/chrome_cleaner/tools/BUILD.gn
+++ b/chrome/chrome_cleaner/tools/BUILD.gn
@@ -8,9 +8,7 @@
 # We need at least one non-executable to prevent an "unused visibility
 # declaration" warning.
 source_set("generate_test_uws_src") {
-  sources = [
-    "generate_test_uws.cc",
-  ]
+  sources = [ "generate_test_uws.cc" ]
 
   deps = [
     "//base:base",
diff --git a/chrome/chrome_cleaner/zip_archiver/BUILD.gn b/chrome/chrome_cleaner/zip_archiver/BUILD.gn
index ee41a43..9c010824 100644
--- a/chrome/chrome_cleaner/zip_archiver/BUILD.gn
+++ b/chrome/chrome_cleaner/zip_archiver/BUILD.gn
@@ -41,9 +41,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "sandboxed_zip_archiver_unittest.cc",
-  ]
+  sources = [ "sandboxed_zip_archiver_unittest.cc" ]
 
   deps = [
     "//base/test:test_support",
diff --git a/chrome/chrome_cleaner/zip_archiver/broker/BUILD.gn b/chrome/chrome_cleaner/zip_archiver/broker/BUILD.gn
index 4b62ea7f..ccf34cb 100644
--- a/chrome/chrome_cleaner/zip_archiver/broker/BUILD.gn
+++ b/chrome/chrome_cleaner/zip_archiver/broker/BUILD.gn
@@ -27,9 +27,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "sandbox_setup_unittest.cc",
-  ]
+  sources = [ "sandbox_setup_unittest.cc" ]
 
   deps = [
     ":common",
diff --git a/chrome/chrome_cleaner/zip_archiver/target/BUILD.gn b/chrome/chrome_cleaner/zip_archiver/target/BUILD.gn
index 0ab2bb7d..371c6715 100644
--- a/chrome/chrome_cleaner/zip_archiver/target/BUILD.gn
+++ b/chrome/chrome_cleaner/zip_archiver/target/BUILD.gn
@@ -32,9 +32,7 @@
 source_set("unittest_sources") {
   testonly = true
 
-  sources = [
-    "zip_archiver_impl_unittest.cc",
-  ]
+  sources = [ "zip_archiver_impl_unittest.cc" ]
 
   deps = [
     ":common",
diff --git a/chrome/chrome_proxy/BUILD.gn b/chrome/chrome_proxy/BUILD.gn
index b5181a5..2153c4b 100644
--- a/chrome/chrome_proxy/BUILD.gn
+++ b/chrome/chrome_proxy/BUILD.gn
@@ -7,9 +7,7 @@
 import("//chrome/process_version_rc_template.gni")
 
 process_version_rc_template("chrome_proxy_version") {
-  sources = [
-    "chrome_proxy.ver",
-  ]
+  sources = [ "chrome_proxy.ver" ]
   output = "$target_gen_dir/chrome_proxy_version.rc"
 }
 
@@ -20,13 +18,9 @@
     "//chrome/app/version_assembly:chrome_exe_manifest",
   ]
 
-  data_deps = [
-    "//chrome/app/version_assembly:version_assembly_manifest",
-  ]
+  data_deps = [ "//chrome/app/version_assembly:version_assembly_manifest" ]
 
-  sources = [
-    "chrome_proxy_main_win.cc",
-  ]
+  sources = [ "chrome_proxy_main_win.cc" ]
 
   configs -= [ "//build/config/win:console" ]
   configs += [ "//build/config/win:windowed" ]
diff --git a/chrome/common/apps/platform_apps/api/BUILD.gn b/chrome/common/apps/platform_apps/api/BUILD.gn
index 027709b3..1d856e5 100644
--- a/chrome/common/apps/platform_apps/api/BUILD.gn
+++ b/chrome/common/apps/platform_apps/api/BUILD.gn
@@ -55,17 +55,13 @@
 json_features("api_features") {
   feature_type = "APIFeature"
   method_name = "AddChromeAppsAPIFeatures"
-  sources = [
-    "_api_features.json",
-  ]
+  sources = [ "_api_features.json" ]
   visibility = [ ":apps_features" ]
 }
 
 json_features("permission_features") {
   feature_type = "PermissionFeature"
   method_name = "AddChromeAppsPermissionFeatures"
-  sources = [
-    "_permission_features.json",
-  ]
+  sources = [ "_permission_features.json" ]
   visibility = [ ":apps_features" ]
 }
diff --git a/chrome/common/search/BUILD.gn b/chrome/common/search/BUILD.gn
index fd46cd0..d1a55b6 100644
--- a/chrome/common/search/BUILD.gn
+++ b/chrome/common/search/BUILD.gn
@@ -23,8 +23,6 @@
 
 compiled_action("generate_chrome_colors_info") {
   tool = ":generate_colors_info"
-  outputs = [
-    "$target_gen_dir/generated_colors_info.h",
-  ]
+  outputs = [ "$target_gen_dir/generated_colors_info.h" ]
   args = rebase_path(outputs, root_build_dir)
 }
diff --git a/chrome/elevation_service/BUILD.gn b/chrome/elevation_service/BUILD.gn
index 2fd4ce2..1c9fa30 100644
--- a/chrome/elevation_service/BUILD.gn
+++ b/chrome/elevation_service/BUILD.gn
@@ -8,9 +8,7 @@
 import("//testing/test.gni")
 
 midl("elevation_service_idl") {
-  sources = [
-    "elevation_service_idl.idl",
-  ]
+  sources = [ "elevation_service_idl.idl" ]
 
   writes_tlb = true
 }
@@ -80,15 +78,11 @@
     "//base",
   ]
 
-  deps = [
-    "//chrome/install_static:install_static_util",
-  ]
+  deps = [ "//chrome/install_static:install_static_util" ]
 }
 
 process_version_rc_template("version_resources") {
-  sources = [
-    "elevation_service_exe.ver",
-  ]
+  sources = [ "elevation_service_exe.ver" ]
   output = "$target_gen_dir/elevation_service_exe.rc"
 }
 
@@ -98,9 +92,7 @@
     "//components/test/data/crx_file/valid_publisher.crx3",
     "//components/test/data/update_client/ChromeRecovery.crx3",
   ]
-  outputs = [
-    "$root_out_dir/elevated_recovery_unittest/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/elevated_recovery_unittest/{{source_file_part}}" ]
 }
 
 test("elevation_service_unittests") {
diff --git a/chrome/installer/BUILD.gn b/chrome/installer/BUILD.gn
index e39f2a0..2e2717a 100644
--- a/chrome/installer/BUILD.gn
+++ b/chrome/installer/BUILD.gn
@@ -14,14 +14,10 @@
 # Meta-target that forwards to the installer of the correct type (if any).
 group("installer") {
   if (enable_linux_installer) {
-    deps = [
-      "//chrome/installer/linux",
-    ]
+    deps = [ "//chrome/installer/linux" ]
   }
 
   if (is_mac) {
-    deps = [
-      "//chrome/installer/mac",
-    ]
+    deps = [ "//chrome/installer/mac" ]
   }
 }
diff --git a/chrome/installer/gcapi/BUILD.gn b/chrome/installer/gcapi/BUILD.gn
index 9dc8945f9..b26cbb486 100644
--- a/chrome/installer/gcapi/BUILD.gn
+++ b/chrome/installer/gcapi/BUILD.gn
@@ -24,12 +24,8 @@
 }
 
 copy("copy_gcapi_header") {
-  sources = [
-    "gcapi.h",
-  ]
-  outputs = [
-    "$root_out_dir/{{source_file_part}}",
-  ]
+  sources = [ "gcapi.h" ]
+  outputs = [ "$root_out_dir/{{source_file_part}}" ]
 }
 
 process_version_rc_template("gcapi_dll_version") {
@@ -76,7 +72,5 @@
     "//testing/gtest",
   ]
 
-  data_deps = [
-    ":gcapi",  # Runtime dependency on this DLL.
-  ]
+  data_deps = [ ":gcapi" ]  # Runtime dependency on this DLL.
 }
diff --git a/chrome/installer/gcapi_mac/BUILD.gn b/chrome/installer/gcapi_mac/BUILD.gn
index 67d30d4..83583a2 100644
--- a/chrome/installer/gcapi_mac/BUILD.gn
+++ b/chrome/installer/gcapi_mac/BUILD.gn
@@ -37,13 +37,9 @@
 }
 
 executable("gcapi_example") {
-  sources = [
-    "gcapi_example_client.mm",
-  ]
+  sources = [ "gcapi_example_client.mm" ]
 
-  deps = [
-    ":gcapi_lib",
-  ]
+  deps = [ ":gcapi_lib" ]
 
   # Don't use runtime_library, to be able to pick a custom mmacosx-version-min.
   configs -= [ "//build/config/compiler:runtime_library" ]
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index 46eaeb4..d219794 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -67,9 +67,7 @@
                   ]
 
 action_foreach("calculate_deb_dependencies") {
-  deps = [
-    ":installer_deps",
-  ]
+  deps = [ ":installer_deps" ]
   script = "debian/calculate_package_deps.py"
   sources = packaging_files_binaries
   inputs = [
@@ -78,9 +76,7 @@
     "debian/package_version_interval.py",
     "//third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl",
   ]
-  outputs = [
-    "$root_out_dir/deb_{{source_name_part}}.deps",
-  ]
+  outputs = [ "$root_out_dir/deb_{{source_name_part}}.deps" ]
   args = [
     "{{source}}",
     rebase_path(sysroot, root_build_dir),
@@ -93,9 +89,7 @@
 }
 
 action("merge_deb_dependencies") {
-  deps = [
-    ":calculate_deb_dependencies",
-  ]
+  deps = [ ":calculate_deb_dependencies" ]
   script = "debian/merge_package_versions.py"
   additional_deps = "debian/additional_deps"
   inputs = [
@@ -103,9 +97,7 @@
     "debian/deb_version.py",
     "debian/package_version_interval.py",
   ]
-  outputs = [
-    "$root_out_dir/deb_common.deps",
-  ]
+  outputs = [ "$root_out_dir/deb_common.deps" ]
   args = [
     "deb_common.deps",
     rebase_path(additional_deps, root_build_dir),
@@ -115,17 +107,11 @@
 }
 
 action_foreach("calculate_rpm_dependencies") {
-  deps = [
-    ":installer_deps",
-  ]
+  deps = [ ":installer_deps" ]
   script = "rpm/calculate_package_deps.py"
   sources = packaging_files_binaries
-  inputs = [
-    "rpm/dist_package_provides.json",
-  ]
-  outputs = [
-    "$root_out_dir/rpm_{{source_name_part}}.deps",
-  ]
+  inputs = [ "rpm/dist_package_provides.json" ]
+  outputs = [ "$root_out_dir/rpm_{{source_name_part}}.deps" ]
   args = [
     "{{source}}",
     "rpm_{{source_name_part}}.deps",
@@ -137,17 +123,11 @@
 }
 
 action("merge_rpm_dependencies") {
-  deps = [
-    ":calculate_rpm_dependencies",
-  ]
+  deps = [ ":calculate_rpm_dependencies" ]
   script = "rpm/merge_package_deps.py"
   additional_deps = "rpm/additional_deps"
-  inputs = [
-    additional_deps,
-  ]
-  outputs = [
-    "$root_out_dir/rpm_common.deps",
-  ]
+  inputs = [ additional_deps ]
+  outputs = [ "$root_out_dir/rpm_common.deps" ]
   args = [
     "rpm_common.deps",
     rebase_path(additional_deps, root_build_dir),
@@ -160,9 +140,7 @@
   prog_name = "$root_out_dir/chrome"
   debug_file = prog_name + ".debug"
   stripped_file = prog_name + ".stripped"
-  deps = [
-    "//chrome",
-  ]
+  deps = [ "//chrome" ]
   script = "//build/gn_run_binary.py"
   sources = [
     "//buildtools/third_party/eu-strip/bin/eu-strip",
@@ -196,6 +174,12 @@
 #
 # TO BUILD LINUX INSTALLER PACKAGES
 #
+# Use the following GN args:
+#
+#   is_component_build = false
+#
+# and the "chrome/installer/linux" target.
+#
 # The packages list the exact versions of each library used. The versions used
 # on the bots are likely different than those on your workstation, so you'll
 # get a stream of errors like:
@@ -253,9 +237,7 @@
 
   sources += [ "//buildtools/third_party/eu-strip/bin/eu-strip" ]
 
-  outputs = [
-    "$root_out_dir/installer/common/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/installer/common/{{source_file_part}}" ]
 }
 
 copy("deb_packaging_files") {
@@ -270,9 +252,7 @@
     "debian/postrm",
     "debian/prerm",
   ]
-  outputs = [
-    "$root_out_dir/installer/debian/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/installer/debian/{{source_file_part}}" ]
 }
 
 copy("theme_files") {
@@ -308,9 +288,7 @@
       "$branding_dir_100/product_logo_32_dev.png",
     ]
   }
-  outputs = [
-    "$root_out_dir/installer/theme/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/installer/theme/{{source_file_part}}" ]
 }
 
 if (!is_chromeos) {
@@ -320,9 +298,7 @@
       "rpm/build.sh",
       "rpm/chrome.spec.template",
     ]
-    outputs = [
-      "$root_out_dir/installer/rpm/{{source_file_part}}",
-    ]
+    outputs = [ "$root_out_dir/installer/rpm/{{source_file_part}}" ]
   }
 }
 
@@ -416,9 +392,7 @@
     } else {
       package = "chromium-browser"
     }
-    outputs = [
-      "$root_out_dir/${package}-${channel}_${chrome_version_full}-1_${deb_arch}.deb",
-    ]
+    outputs = [ "$root_out_dir/${package}-${channel}_${chrome_version_full}-1_${deb_arch}.deb" ]
 
     args = [
       rebase_path("$root_out_dir/installer/debian/build.sh", root_build_dir),
@@ -474,9 +448,7 @@
       } else {
         package = "chromium-browser"
       }
-      outputs = [
-        "$root_out_dir/${package}-${channel}-${chrome_version_full}-1.${rpm_arch}.rpm",
-      ]
+      outputs = [ "$root_out_dir/${package}-${channel}-${chrome_version_full}-1.${rpm_arch}.rpm" ]
 
       args = [
         rebase_path("$root_out_dir/installer/rpm/build.sh", root_build_dir),
@@ -504,9 +476,7 @@
   }
 
   group(target_name) {
-    deps = [
-      ":$deb_target_name",
-    ]
+    deps = [ ":$deb_target_name" ]
     if (!is_chromeos) {
       deps += [ ":$rpm_target_name" ]
     }
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index ef35915..68c686ad 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -10,9 +10,7 @@
 import("mac_signing_sources.gni")
 
 group("mac") {
-  public_deps = [
-    ":copies",
-  ]
+  public_deps = [ ":copies" ]
 }
 
 _packaging_dir = "$root_out_dir/$chrome_product_full_name Packaging"
@@ -38,9 +36,7 @@
 copy("copy_signing") {
   visibility = [ ":copies" ]
 
-  deps = [
-    ":sign_config",
-  ]
+  deps = [ ":sign_config" ]
 
   sources = mac_signing_sources
 
@@ -48,9 +44,7 @@
     sources += [ "internal/internal_config.py" ]
   }
 
-  outputs = [
-    "$_packaging_dir/signing/{{source_file_part}}",
-  ]
+  outputs = [ "$_packaging_dir/signing/{{source_file_part}}" ]
 }
 
 copy("copies") {
@@ -103,9 +97,7 @@
     ]
   }
 
-  outputs = [
-    "$_packaging_dir/{{source_file_part}}",
-  ]
+  outputs = [ "$_packaging_dir/{{source_file_part}}" ]
 }
 
 group("mac_signing_tests") {
diff --git a/chrome/installer/mac/third_party/bsdiff/BUILD.gn b/chrome/installer/mac/third_party/bsdiff/BUILD.gn
index c9162ce..d8974f6a 100644
--- a/chrome/installer/mac/third_party/bsdiff/BUILD.gn
+++ b/chrome/installer/mac/third_party/bsdiff/BUILD.gn
@@ -16,15 +16,11 @@
     "sha1_adapter.h",
   ]
 
-  deps = [
-    "//base:logging_buildflags",  # Needed by sha1.cc
-  ]
+  deps = [ "//base:logging_buildflags" ]  # Needed by sha1.cc
 }
 
 executable("goobsdiff") {
-  sources = [
-    "goobsdiff.c",
-  ]
+  sources = [ "goobsdiff.c" ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
@@ -43,9 +39,7 @@
 }
 
 executable("goobspatch") {
-  sources = [
-    "goobspatch.c",
-  ]
+  sources = [ "goobspatch.c" ]
 
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [ "//build/config/compiler:no_chromium_code" ]
diff --git a/chrome/installer/mac/third_party/xz/BUILD.gn b/chrome/installer/mac/third_party/xz/BUILD.gn
index 34dad67..827ff2a4 100644
--- a/chrome/installer/mac/third_party/xz/BUILD.gn
+++ b/chrome/installer/mac/third_party/xz/BUILD.gn
@@ -369,9 +369,7 @@
     "xz/src/xz/util.c",
   ]
 
-  deps = [
-    ":lzma",
-  ]
+  deps = [ ":lzma" ]
 
   include_dirs = [
     "config/$host_os",
@@ -391,9 +389,7 @@
     "xz/src/xzdec/xzdec.c",
   ]
 
-  deps = [
-    ":lzma_decompress",
-  ]
+  deps = [ ":lzma_decompress" ]
 
   include_dirs = [
     "config/$host_os",
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn
index 239f4393..7d83518 100644
--- a/chrome/installer/mini_installer/BUILD.gn
+++ b/chrome/installer/mini_installer/BUILD.gn
@@ -47,9 +47,7 @@
     "regkey.h",
   ]
 
-  deps = [
-    "//build:branding_buildflags",
-  ]
+  deps = [ "//build:branding_buildflags" ]
 
   if (skip_archive_compression) {
     defines = [ "SKIP_ARCHIVE_COMPRESSION" ]
@@ -75,9 +73,7 @@
     "mini_string_test.cc",
   ]
 
-  public_deps = [
-    ":lib",
-  ]
+  public_deps = [ ":lib" ]
   deps = [
     "//base",
     "//base/test:test_support",
@@ -103,9 +99,7 @@
 
 group("setup_runtime_deps") {
   write_runtime_deps = setup_runtime_deps
-  data_deps = [
-    "//chrome/installer/setup",
-  ]
+  data_deps = [ "//chrome/installer/setup" ]
 }
 
 # Generates a mini installer.
@@ -330,9 +324,7 @@
       "$root_out_dir/" + alternate_version_generator_rel_path,
       "$root_out_dir/mini_installer.exe",
     ]
-    outputs = [
-      "$root_out_dir/$target_name.exe",
-    ]
+    outputs = [ "$root_out_dir/$target_name.exe" ]
     args = [
       "--alternate_version_generator",
       alternate_version_generator_rel_path,
diff --git a/chrome/installer/test/BUILD.gn b/chrome/installer/test/BUILD.gn
index b2dd42e2..31d9c4b0 100644
--- a/chrome/installer/test/BUILD.gn
+++ b/chrome/installer/test/BUILD.gn
@@ -8,9 +8,7 @@
 
 executable("alternate_version_generator") {
   testonly = true
-  sources = [
-    "alternate_version_generator_main.cc",
-  ]
+  sources = [ "alternate_version_generator_main.cc" ]
 
   deps = [
     ":alternate_version_generator_lib",
@@ -56,7 +54,5 @@
     "//chrome/installer/util:with_rc_strings",
     "//testing/gtest",
   ]
-  data_deps = [
-    "//chrome/installer/mini_installer",
-  ]
+  data_deps = [ "//chrome/installer/mini_installer" ]
 }
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn
index 2ff68fe..0f5e97d 100644
--- a/chrome/installer/util/BUILD.gn
+++ b/chrome/installer/util/BUILD.gn
@@ -40,9 +40,7 @@
 # we would still need the variant with no strings for when chrome.dll replaces
 # all strings with its own versions.
 static_library("with_no_strings") {
-  public_deps = [
-    ":constants",
-  ]
+  public_deps = [ ":constants" ]
 
   deps = [
     "//base",
@@ -192,9 +190,7 @@
 # Use this version of installer_util to link to the generated strings in .rc
 # format.
 group("with_rc_strings") {
-  public_deps = [
-    ":with_no_strings",
-  ]
+  public_deps = [ ":with_no_strings" ]
   if (is_win) {
     public_deps += [ ":strings" ]
   }
@@ -230,19 +226,13 @@
 # Compile the generated .rc file.
 source_set("strings") {
   sources = get_target_outputs(":generate_strings")
-  public_deps = [
-    ":generate_strings",
-  ]
+  public_deps = [ ":generate_strings" ]
 }
 
 source_set("constants") {
-  public = [
-    "master_preferences_constants.h",
-  ]
+  public = [ "master_preferences_constants.h" ]
 
-  sources = [
-    "master_preferences_constants.cc",
-  ]
+  sources = [ "master_preferences_constants.cc" ]
 
   if (is_win) {
     public += [
@@ -255,21 +245,15 @@
       "util_constants.cc",
     ]
 
-    public_deps = [
-      "//base",
-    ]
+    public_deps = [ "//base" ]
   }
 }
 
 if (is_win) {
   source_set("did_run_support") {
-    public = [
-      "update_did_run_state.h",
-    ]
+    public = [ "update_did_run_state.h" ]
 
-    sources = [
-      "update_did_run_state.cc",
-    ]
+    sources = [ "update_did_run_state.cc" ]
 
     deps = [
       ":constants",
diff --git a/chrome/lib/lifecycle/public/android/BUILD.gn b/chrome/lib/lifecycle/public/android/BUILD.gn
index b5bc078e..77d9199 100644
--- a/chrome/lib/lifecycle/public/android/BUILD.gn
+++ b/chrome/lib/lifecycle/public/android/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  deps = [
-    "//third_party/android_deps:androidx_annotation_annotation_java",
-  ]
+  deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
   sources = [
     "java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java",
     "java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java",
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 32d2163..8c9457a 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -190,9 +190,7 @@
     "//v8",
   ]
 
-  data_deps = [
-    "//tools/v8_context_snapshot",
-  ]
+  data_deps = [ "//tools/v8_context_snapshot" ]
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
@@ -347,9 +345,7 @@
       "//media/cast:sender",
       "//services/network/public/cpp",
     ]
-    public_deps = [
-      "//ipc",
-    ]
+    public_deps = [ "//ipc" ]
   }
   if (enable_extensions) {
     sources += [
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index 7e1aad3..5df32ef 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -69,11 +69,6 @@
 #include "chrome/common/mhtml_page_notifier.mojom.h"
 #endif
 
-#if BUILDFLAG(ENABLE_PRINTING)
-#include "components/printing/common/print_messages.h"
-#include "components/printing/renderer/print_render_frame_helper.h"
-#endif
-
 using blink::WebDocumentLoader;
 using blink::WebElement;
 using blink::WebFrameContentDumper;
@@ -180,6 +175,8 @@
 bool ChromeRenderFrameObserver::OnMessageReceived(const IPC::Message& message) {
   // Filter only.
   bool handled = true;
+  // Messages in this message map have multiple handlers. Please do not add more
+  // messages here.
   IPC_BEGIN_MESSAGE_MAP(ChromeRenderFrameObserver, message)
     IPC_MESSAGE_HANDLER(PrerenderMsg_SetIsPrerendering, OnSetIsPrerendering)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -187,11 +184,10 @@
   if (handled)
     return false;
 
+  // Normal message handlers. Legacy IPC is deprecated, but leaving this as a
+  // placeholder in case new messages are added before legacy IPC handling is
+  // wholly removed from this class.
   IPC_BEGIN_MESSAGE_MAP(ChromeRenderFrameObserver, message)
-#if BUILDFLAG(ENABLE_PRINTING)
-    IPC_MESSAGE_HANDLER(PrintMsg_PrintNodeUnderContextMenu,
-                        OnPrintNodeUnderContextMenu)
-#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -270,15 +266,6 @@
   std::move(callback).Run(thumbnail_data, original_size);
 }
 
-void ChromeRenderFrameObserver::OnPrintNodeUnderContextMenu() {
-#if BUILDFLAG(ENABLE_PRINTING)
-  printing::PrintRenderFrameHelper* helper =
-      printing::PrintRenderFrameHelper::Get(render_frame());
-  if (helper)
-    helper->PrintNode(render_frame()->GetWebFrame()->ContextMenuNode());
-#endif
-}
-
 void ChromeRenderFrameObserver::GetWebApplicationInfo(
     GetWebApplicationInfoCallback callback) {
   WebLocalFrame* frame = render_frame()->GetWebFrame();
diff --git a/chrome/renderer/chrome_render_frame_observer.h b/chrome/renderer/chrome_render_frame_observer.h
index 98ea5b6..60c4104 100644
--- a/chrome/renderer/chrome_render_frame_observer.h
+++ b/chrome/renderer/chrome_render_frame_observer.h
@@ -74,7 +74,6 @@
       int thumbnail_min_area_pixels,
       const gfx::Size& thumbnail_max_size_pixels,
       int callback_id);
-  void OnPrintNodeUnderContextMenu();
   void OnSetClientSidePhishingDetection(bool enable_phishing_detection);
 
   // chrome::mojom::ChromeRenderFrame:
diff --git a/chrome/services/file_util/public/cpp/BUILD.gn b/chrome/services/file_util/public/cpp/BUILD.gn
index 66f8577..973c2e5 100644
--- a/chrome/services/file_util/public/cpp/BUILD.gn
+++ b/chrome/services/file_util/public/cpp/BUILD.gn
@@ -6,9 +6,7 @@
 import("//components/safe_browsing/buildflags.gni")
 
 source_set("cpp") {
-  public_deps = [
-    "//chrome/services/file_util/public/mojom",
-  ]
+  public_deps = [ "//chrome/services/file_util/public/mojom" ]
 
   if (safe_browsing_mode == 1) {
     sources = [
@@ -56,9 +54,7 @@
   source_set("browser_tests") {
     testonly = true
 
-    sources = [
-      "zip_file_creator_browsertest.cc",
-    ]
+    sources = [ "zip_file_creator_browsertest.cc" ]
     defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
     deps = [
diff --git a/chrome/services/file_util/public/mojom/BUILD.gn b/chrome/services/file_util/public/mojom/BUILD.gn
index 10d8410c..cf5ab6dbd 100644
--- a/chrome/services/file_util/public/mojom/BUILD.gn
+++ b/chrome/services/file_util/public/mojom/BUILD.gn
@@ -7,18 +7,14 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "file_util_service.mojom",
-  ]
+  sources = [ "file_util_service.mojom" ]
 
   if (safe_browsing_mode == 1) {
     sources += [ "safe_archive_analyzer.mojom" ]
     enabled_features = [ "full_safe_browsing" ]
   }
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 
   if (is_chromeos) {
     sources += [ "zip_file_creator.mojom" ]
diff --git a/chrome/services/ipp_parser/public/cpp/BUILD.gn b/chrome/services/ipp_parser/public/cpp/BUILD.gn
index aa72f71..695f579 100644
--- a/chrome/services/ipp_parser/public/cpp/BUILD.gn
+++ b/chrome/services/ipp_parser/public/cpp/BUILD.gn
@@ -12,9 +12,7 @@
       "ipp_converter.h",
     ]
 
-    public_deps = [
-      "//chrome/services/ipp_parser/public/mojom",
-    ]
+    public_deps = [ "//chrome/services/ipp_parser/public/mojom" ]
 
     deps = [
       "//base",
@@ -29,12 +27,8 @@
   # TODO(crbug.com/831914): Enable this fuzzer once its running on CrOS only.
   if (false) {  # use_fuzzing_engine && is_chromeos
     fuzzer_test("ipp_message_parser_fuzzer") {
-      sources = [
-        "ipp_message_parser_fuzzer.cc",
-      ]
-      deps = [
-        ":cpp",
-      ]
+      sources = [ "ipp_message_parser_fuzzer.cc" ]
+      deps = [ ":cpp" ]
 
       dict = "ipp_message_parser_fuzzer.dict"
     }
diff --git a/chrome/services/ipp_parser/public/mojom/BUILD.gn b/chrome/services/ipp_parser/public/mojom/BUILD.gn
index 426c63c..3bf2289 100644
--- a/chrome/services/ipp_parser/public/mojom/BUILD.gn
+++ b/chrome/services/ipp_parser/public/mojom/BUILD.gn
@@ -6,11 +6,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "ipp_parser.mojom",
-  ]
+  sources = [ "ipp_parser.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chrome/services/keymaster/public/mojom/BUILD.gn b/chrome/services/keymaster/public/mojom/BUILD.gn
index d49f4c27..a00b943 100644
--- a/chrome/services/keymaster/public/mojom/BUILD.gn
+++ b/chrome/services/keymaster/public/mojom/BUILD.gn
@@ -7,11 +7,7 @@
 assert(is_chromeos)
 
 mojom("mojom") {
-  sources = [
-    "cert_store.mojom",
-  ]
+  sources = [ "cert_store.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chrome/services/printing/public/mojom/BUILD.gn b/chrome/services/printing/public/mojom/BUILD.gn
index d74f7d6..498906e 100644
--- a/chrome/services/printing/public/mojom/BUILD.gn
+++ b/chrome/services/printing/public/mojom/BUILD.gn
@@ -12,9 +12,7 @@
     "printing_service.mojom",
   ]
 
-  deps = [
-    "//ui/gfx/geometry/mojom",
-  ]
+  deps = [ "//ui/gfx/geometry/mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/chrome/services/removable_storage_writer/public/mojom/BUILD.gn b/chrome/services/removable_storage_writer/public/mojom/BUILD.gn
index e0659789..c852d707 100644
--- a/chrome/services/removable_storage_writer/public/mojom/BUILD.gn
+++ b/chrome/services/removable_storage_writer/public/mojom/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "removable_storage_writer.mojom",
-  ]
+  sources = [ "removable_storage_writer.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b88e75f9..e87367a9 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1495,6 +1495,7 @@
         "../browser/policy/accessibility_policy_browsertest.cc",
         "../browser/policy/arc_policy_browsertest.cc",
         "../browser/policy/assistant_policy_browsertest.cc",
+        "../browser/renderer_context_menu/quick_answers_menu_observer_browsertest.cc",
       ]
     }
 
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 62498bd..c4c88495 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -81,9 +81,7 @@
   apk_name = "ChromePageControllerCodelab"
   apk_under_test = "//chrome/android:chrome_public_apk"
   android_manifest = "javatests/src/org/chromium/chrome/test/pagecontroller/tests/AndroidManifest.xml"
-  sources = [
-    "javatests/src/org/chromium/chrome/test/pagecontroller/tests/codelab/SettingsForCodelabTest.java",
-  ]
+  sources = [ "javatests/src/org/chromium/chrome/test/pagecontroller/tests/codelab/SettingsForCodelabTest.java" ]
   deps = [
     ":chrome_java_test_pagecontroller",
     "//third_party/junit",
diff --git a/chrome/test/data/nacl/BUILD.gn b/chrome/test/data/nacl/BUILD.gn
index de440f5..9769883 100644
--- a/chrome/test/data/nacl/BUILD.gn
+++ b/chrome/test/data/nacl/BUILD.gn
@@ -124,9 +124,7 @@
       "progress_event_listener.js",
       "simple_cc.js",
     ]
-    outputs = [
-      "${root_build_dir}/nacl_test_data/${nacl_toolchain_variant}/{{source_file_part}}",
-    ]
+    outputs = [ "${root_build_dir}/nacl_test_data/${nacl_toolchain_variant}/{{source_file_part}}" ]
   }
 
   source_set("ppapi_test_lib") {
@@ -149,12 +147,8 @@
   }
 
   nacl_test_data("irt_manifest_file") {
-    sources = [
-      "manifest_file/irt_manifest_file_test.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "manifest_file/irt_manifest_file_test.cc" ]
+    deps = [ "//ppapi/cpp" ]
     nmfflags = [
       "-xtest_file:test_file.txt",
       "-xnmf says hello world:test_file.txt",
@@ -168,12 +162,8 @@
   }
 
   nacl_test_data("irt_exception_test") {
-    sources = [
-      "irt_exception/irt_exception_test.cc",
-    ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    sources = [ "irt_exception/irt_exception_test.cc" ]
+    deps = [ ":ppapi_test_lib" ]
     libs = [ "nacl_exception" ]
     destination_dir = "nacl_test_data"
     test_files = [ "irt_exception/irt_exception_test.html" ]
@@ -183,35 +173,23 @@
 if (is_nacl && !is_nacl_nonsfi) {
   nacl_test_data("simple_test") {
     output_name = "simple"
-    sources = [
-      "simple.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "simple.cc" ]
+    deps = [ "//ppapi/cpp" ]
     destination_dir = "nacl_test_data"
     test_files = [ "nacl_load_test.html" ]
   }
 
   nacl_test_data("exit_status_test") {
     output_name = "pm_exit_status_test"
-    sources = [
-      "exit_status/pm_exit_status_test.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "exit_status/pm_exit_status_test.cc" ]
+    deps = [ "//ppapi/cpp" ]
     destination_dir = "nacl_test_data"
     test_files = [ "exit_status/pm_exit_status_test.html" ]
   }
 
   nacl_test_data("extension_validation_cache") {
-    sources = [
-      "simple.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "simple.cc" ]
+    deps = [ "//ppapi/cpp" ]
 
     # Need a new directory to not clash with with other extension
     # tests's files (e.g., manifest.json).
@@ -233,130 +211,84 @@
   }
 
   nacl_test_data("sysconf_nprocessors_onln_test") {
-    sources = [
-      "sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc" ]
+    deps = [ "//ppapi/cpp" ]
     destination_dir = "nacl_test_data"
     test_files =
         [ "sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html" ]
   }
 
   nacl_test_data("ppapi_progress_events") {
-    sources = [
-      "progress_events/ppapi_progress_events.cc",
-    ]
+    sources = [ "progress_events/ppapi_progress_events.cc" ]
     destination_dir = "nacl_test_data"
     test_files = [ "progress_events/ppapi_progress_events.html" ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_bad_ppp_initialize") {
-    sources = [
-      "bad/ppapi_bad_ppp_initialize.cc",
-    ]
+    sources = [ "bad/ppapi_bad_ppp_initialize.cc" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_bad_ppp_initialize_crash") {
-    sources = [
-      "bad/ppapi_bad_ppp_initialize_crash.cc",
-    ]
+    sources = [ "bad/ppapi_bad_ppp_initialize_crash.cc" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_bad_no_ppp_instance") {
-    sources = [
-      "bad/ppapi_bad_no_ppp_instance.cc",
-    ]
-    deps = [
-      "//native_client/src/shared/platform",
-    ]
+    sources = [ "bad/ppapi_bad_no_ppp_instance.cc" ]
+    deps = [ "//native_client/src/shared/platform" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_bad_get_ppp_instance_crash") {
-    sources = [
-      "bad/ppapi_bad_get_ppp_instance_crash.cc",
-    ]
+    sources = [ "bad/ppapi_bad_get_ppp_instance_crash.cc" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_bad_ppp_instance_didcreate") {
-    sources = [
-      "bad/ppapi_bad_ppp_instance_didcreate.cc",
-    ]
+    sources = [ "bad/ppapi_bad_ppp_instance_didcreate.cc" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_bad_ppp_instance_didcreate_crash") {
-    sources = [
-      "bad/ppapi_bad_ppp_instance_didcreate_crash.cc",
-    ]
+    sources = [ "bad/ppapi_bad_ppp_instance_didcreate_crash.cc" ]
     destination_dir = "nacl_test_data"
   }
 
   nacl_test_data("ppapi_crash_via_check_failure") {
-    sources = [
-      "crash/ppapi_crash_via_check_failure.cc",
-    ]
+    sources = [ "crash/ppapi_crash_via_check_failure.cc" ]
     destination_dir = "nacl_test_data"
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_crash_via_exit_call") {
-    sources = [
-      "crash/ppapi_crash_via_exit_call.cc",
-    ]
+    sources = [ "crash/ppapi_crash_via_exit_call.cc" ]
     destination_dir = "nacl_test_data"
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_crash_in_callback") {
-    sources = [
-      "crash/ppapi_crash_in_callback.cc",
-    ]
+    sources = [ "crash/ppapi_crash_in_callback.cc" ]
     destination_dir = "nacl_test_data"
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_crash_off_main_thread") {
-    sources = [
-      "crash/ppapi_crash_off_main_thread.cc",
-    ]
+    sources = [ "crash/ppapi_crash_off_main_thread.cc" ]
     destination_dir = "nacl_test_data"
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_crash_ppapi_off_main_thread") {
-    sources = [
-      "crash/ppapi_crash_ppapi_off_main_thread.cc",
-    ]
+    sources = [ "crash/ppapi_crash_ppapi_off_main_thread.cc" ]
     destination_dir = "nacl_test_data"
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    deps = [ ":ppapi_test_lib" ]
   }
 
   nacl_test_data("ppapi_extension_mime_handler") {
-    sources = [
-      "extension_mime_handler/ppapi_extension_mime_handler.cc",
-    ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    sources = [ "extension_mime_handler/ppapi_extension_mime_handler.cc" ]
+    deps = [ ":ppapi_test_lib" ]
     destination_dir = "nacl_test_data"
     test_files = [
       "extension_mime_handler/ppapi_extension_mime_handler.html",
@@ -373,12 +305,8 @@
 
   nacl_test_data("pnacl_debug_url_test") {
     output_name = "pnacl_debug_url"
-    sources = [
-      "simple.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "simple.cc" ]
+    deps = [ "//ppapi/cpp" ]
     generate_nmf = false
     if (current_cpu == "pnacl") {
       debug_pexe = true
@@ -394,12 +322,8 @@
 
   nacl_test_data("pnacl_error_handling_test") {
     output_name = "pnacl_errors"
-    sources = [
-      "simple.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "simple.cc" ]
+    deps = [ "//ppapi/cpp" ]
     generate_nmf = false
     if (current_cpu == "pnacl") {
       nonstable_pexe = true
@@ -417,22 +341,14 @@
   }
 
   copy("pnacl_mime_type_test") {
-    sources = [
-      "pnacl_mime_type/pnacl_mime_type.html",
-    ]
-    outputs = [
-      "${root_build_dir}/nacl_test_data/${nacl_toolchain_variant}/{{source_file_part}}",
-    ]
+    sources = [ "pnacl_mime_type/pnacl_mime_type.html" ]
+    outputs = [ "${root_build_dir}/nacl_test_data/${nacl_toolchain_variant}/{{source_file_part}}" ]
   }
 
   nacl_test_data("pnacl_options_test") {
     output_name = "pnacl_options"
-    sources = [
-      "simple.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "simple.cc" ]
+    deps = [ "//ppapi/cpp" ]
     generate_nmf = false
     destination_dir = "nacl_test_data"
     test_files = [
@@ -445,12 +361,8 @@
 
   nacl_test_data("pnacl_url_loader_test") {
     output_name = "pnacl_url_loader"
-    sources = [
-      "pnacl_url_loader/pnacl_url_loader.cc",
-    ]
-    deps = [
-      "//ppapi/cpp",
-    ]
+    sources = [ "pnacl_url_loader/pnacl_url_loader.cc" ]
+    deps = [ "//ppapi/cpp" ]
     generate_nmf = true
     destination_dir = "nacl_test_data"
     test_files = [ "pnacl_url_loader/pnacl_url_loader.html" ]
@@ -458,9 +370,8 @@
 
   nacl_test_data("pnacl_dyncode_syscall_disabled_test") {
     output_name = "pnacl_dyncode_syscall_disabled"
-    sources = [
-      "pnacl_dyncode_syscall_disabled/pnacl_dyncode_syscall_disabled.cc",
-    ]
+    sources =
+        [ "pnacl_dyncode_syscall_disabled/pnacl_dyncode_syscall_disabled.cc" ]
     deps = [
       ":ppapi_test_lib",
       "//native_client/src/untrusted/nacl:nacl_dyncode_private",
@@ -472,9 +383,7 @@
 
   nacl_test_data("pnacl_hw_eh_disabled_test") {
     output_name = "pnacl_hw_eh_disabled"
-    sources = [
-      "pnacl_hw_eh_disabled/pnacl_hw_eh_disabled.cc",
-    ]
+    sources = [ "pnacl_hw_eh_disabled/pnacl_hw_eh_disabled.cc" ]
     deps = [
       ":ppapi_test_lib",
       "//native_client/src/untrusted/nacl:nacl_exception_private",
@@ -485,34 +394,22 @@
 
   # Legacy NaCl PPAPI interface tests being here.
   nacl_test_data("ppapi_ppb_core") {
-    sources = [
-      "ppapi/ppb_core/ppapi_ppb_core.cc",
-    ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    sources = [ "ppapi/ppb_core/ppapi_ppb_core.cc" ]
+    deps = [ ":ppapi_test_lib" ]
     destination_dir = "nacl_test_data"
     test_files = [ "ppapi/ppb_core/ppapi_ppb_core.html" ]
   }
 
   nacl_test_data("ppapi_ppb_instance") {
-    sources = [
-      "ppapi/ppb_instance/ppapi_ppb_instance.cc",
-    ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    sources = [ "ppapi/ppb_instance/ppapi_ppb_instance.cc" ]
+    deps = [ ":ppapi_test_lib" ]
     destination_dir = "nacl_test_data"
     test_files = [ "ppapi/ppb_instance/ppapi_ppb_instance.html" ]
   }
 
   nacl_test_data("ppapi_ppp_instance") {
-    sources = [
-      "ppapi/ppp_instance/ppapi_ppp_instance.cc",
-    ]
-    deps = [
-      ":ppapi_test_lib",
-    ]
+    sources = [ "ppapi/ppp_instance/ppapi_ppp_instance.cc" ]
+    deps = [ ":ppapi_test_lib" ]
     destination_dir = "nacl_test_data"
     test_files = [
       "ppapi/ppp_instance/ppapi_ppp_instance.html",
@@ -523,9 +420,7 @@
   if (target_cpu != "arm") {
     # Source file does not have asm for ARM.
     nacl_test_data("partly_invalid") {
-      sources = [
-        "//native_client/tests/stubout_mode/partly_invalid.c",
-      ]
+      sources = [ "//native_client/tests/stubout_mode/partly_invalid.c" ]
       destination_dir = "nacl_test_data"
     }
   }
@@ -579,9 +474,7 @@
   executable("nonsfi_libc_free_nexe") {
     output_name = "libc_free_$arch"
     output_extension = "nexe"
-    sources = [
-      "nonsfi/libc_free.c",
-    ]
+    sources = [ "nonsfi/libc_free.c" ]
 
     no_default_deps = true
 
@@ -632,11 +525,8 @@
       "nonsfi/libc_free.html",
       "nonsfi/libc_free.nmf",
     ]
-    outputs = [
-      "${root_build_dir}/nacl_test_data/libc-free/{{source_file_part}}",
-    ]
-    deps = [
-      ":nonsfi_libc_free_nexe",
-    ]
+    outputs =
+        [ "${root_build_dir}/nacl_test_data/libc-free/{{source_file_part}}" ]
+    deps = [ ":nonsfi_libc_free_nexe" ]
   }
 }
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 04d44b6..a5cc6e6 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -227,9 +227,7 @@
     "usb_internals_browsertest.js",
   ]
 
-  deps = [
-    "//chrome/browser/ui",
-  ]
+  deps = [ "//chrome/browser/ui" ]
 
   if (is_win || is_mac || is_desktop_linux || is_chromeos) {
     sources += [ "discards/discards_browsertest.js" ]
diff --git a/chrome/test/data/webui/cr_elements/BUILD.gn b/chrome/test/data/webui/cr_elements/BUILD.gn
index a958a7d..39a6317 100644
--- a/chrome/test/data/webui/cr_elements/BUILD.gn
+++ b/chrome/test/data/webui/cr_elements/BUILD.gn
@@ -22,7 +22,6 @@
     "cr_radio_button_test.js",
     "cr_radio_group_test.js",
     "cr_search_field_tests.js",
-    "cr_splitter_test.js",
     "cr_toolbar_search_field_tests.js",
     "cr_tabs_test.js",
     "cr_toast_test.js",
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 9e78d76a8..0beb124c 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -404,28 +404,6 @@
  * @constructor
  * @extends {CrElementsBrowserTest}
  */
-function CrElementsSplitterTest() {}
-
-CrElementsSplitterTest.prototype = {
-  __proto__: CrElementsBrowserTest.prototype,
-
-  /** @override */
-  browsePreload: 'chrome://resources/cr_elements/cr_splitter/cr_splitter.html',
-
-  /** @override */
-  extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([
-    'cr_splitter_test.js',
-  ]),
-};
-
-TEST_F('CrElementsSplitterTest', 'All', function() {
-  mocha.run();
-});
-
-/**
- * @constructor
- * @extends {CrElementsBrowserTest}
- */
 function CrElementsToastTest() {}
 
 CrElementsToastTest.prototype = {
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
index da4c565..a153690f 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
@@ -188,7 +188,7 @@
 var CrElementsSplitterV3Test = class extends CrElementsV3BrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://test?module=cr_elements/cr_splitter_test.m.js';
+    return 'chrome://test?module=cr_elements/cr_splitter_test.js';
   }
 };
 
diff --git a/chrome/test/data/webui/cr_elements/cr_splitter_test.js b/chrome/test/data/webui/cr_elements/cr_splitter_test.js
index 332a728..7c8d7cd4 100644
--- a/chrome/test/data/webui/cr_elements/cr_splitter_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_splitter_test.js
@@ -2,9 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
-// #import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.m.js';
-// clang-format on
+import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js';
 
 suite('cr-splitter', function() {
   let crSplitter;
diff --git a/chrome/test/data/webui/print_preview/custom_margins_test.js b/chrome/test/data/webui/print_preview/custom_margins_test.js
index 78126d47..26bc71de 100644
--- a/chrome/test/data/webui/print_preview/custom_margins_test.js
+++ b/chrome/test/data/webui/print_preview/custom_margins_test.js
@@ -246,11 +246,11 @@
       container.setSetting(settingName, newValue);
       container.previewLoaded = false;
 
-      // Margins should be reset to default and custom margins values should
-      // be cleared.
-      expectEquals(MarginsType.DEFAULT, container.getSettingValue('margins'));
+      // Custom margins values should be cleared.
       expectEquals(
           '{}', JSON.stringify(container.getSettingValue('customMargins')));
+      // The margins-settings element will also set the margins type to DEFAULT.
+      model.set('settings.margins.value', MarginsType.DEFAULT);
 
       // When preview loads, custom margins should still be empty, since
       // custom margins are not selected. We do not want to set the sticky
diff --git a/chrome/test/data/webui/print_preview/margins_settings_test.js b/chrome/test/data/webui/print_preview/margins_settings_test.js
index 57337e1..e12d414 100644
--- a/chrome/test/data/webui/print_preview/margins_settings_test.js
+++ b/chrome/test/data/webui/print_preview/margins_settings_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {MarginsType} from 'chrome://print/print_preview.js';
+import {MarginsType, State} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {selectOption} from 'chrome://test/print_preview/print_preview_test_utils.js';
 import {eventToPromise, fakeDataBind} from 'chrome://test/test_util.m.js';
@@ -12,16 +12,19 @@
 
   let marginsTypeEnum = null;
 
+  let model = null;
+
   /** @override */
   setup(function() {
     PolymerTest.clearBody();
-    const model = document.createElement('print-preview-model');
+    model = document.createElement('print-preview-model');
     document.body.appendChild(model);
 
     marginsSection = document.createElement('print-preview-margins-settings');
     document.body.appendChild(marginsSection);
     marginsSection.settings = model.settings;
     marginsSection.disabled = false;
+    marginsSection.state = State.READY;
     fakeDataBind(model, marginsSection, 'settings');
     marginsTypeEnum = MarginsType;
   });
@@ -54,15 +57,53 @@
   });
 
   // This test verifies that changing pages per sheet to N > 1 disables the
-  // margins dropdown.
-  test('disabled by pages per sheet', function() {
+  // margins dropdown and changes the value to DEFAULT.
+  test('disabled by pages per sheet', async () => {
     const select = marginsSection.$$('select');
+    await selectOption(marginsSection, marginsTypeEnum.MINIMUM.toString());
+    assertEquals(
+        marginsTypeEnum.MINIMUM, marginsSection.getSettingValue('margins'));
     assertFalse(select.disabled);
 
-    marginsSection.setSetting('pagesPerSheet', 2);
+    model.set('settings.pagesPerSheet.value', 2);
+    await eventToPromise('process-select-change', marginsSection);
+    assertEquals(
+        marginsTypeEnum.DEFAULT, marginsSection.getSettingValue('margins'));
+    assertEquals(marginsTypeEnum.DEFAULT.toString(), select.value);
     assertTrue(select.disabled);
 
-    marginsSection.setSetting('pagesPerSheet', 1);
+    model.set('settings.pagesPerSheet.value', 1);
+    assertEquals(
+        marginsTypeEnum.DEFAULT, marginsSection.getSettingValue('margins'));
     assertFalse(select.disabled);
   });
+
+  // Test that changing the layout or media size setting clears a custom
+  // margins setting.
+  test('custom margins cleared by layout and media size', async () => {
+    const select = marginsSection.$$('select');
+    await selectOption(marginsSection, marginsTypeEnum.CUSTOM.toString());
+    assertEquals(
+        marginsTypeEnum.CUSTOM, marginsSection.getSettingValue('margins'));
+
+    // Changing layout clears custom margins.
+    model.set('settings.layout.value', true);
+    await eventToPromise('process-select-change', marginsSection);
+    assertEquals(
+        marginsTypeEnum.DEFAULT, marginsSection.getSettingValue('margins'));
+    assertEquals(marginsTypeEnum.DEFAULT.toString(), select.value);
+
+    await selectOption(marginsSection, marginsTypeEnum.CUSTOM.toString());
+    assertEquals(
+        marginsTypeEnum.CUSTOM, marginsSection.getSettingValue('margins'));
+
+    // Changing media size clears custom margins.
+    model.set(
+        'settings.mediaSize.value',
+        '{height_microns: 400, width_microns: 300}');
+    await eventToPromise('process-select-change', marginsSection);
+    assertEquals(
+        marginsTypeEnum.DEFAULT, marginsSection.getSettingValue('margins'));
+    assertEquals(marginsTypeEnum.DEFAULT.toString(), select.value);
+  });
 });
diff --git a/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js b/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js
index d7f624fe..0617e96 100644
--- a/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js
+++ b/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js
@@ -34,17 +34,6 @@
     assertEquals('4', select.value);
   });
 
-  // Tests that setting the pages per sheet setting resets margins to DEFAULT.
-  test('resets margins setting', async () => {
-    pagesPerSheetSection.setSetting('margins', MarginsType.NO_MARGINS);
-    assertEquals(1, pagesPerSheetSection.getSettingValue('pagesPerSheet'));
-    pagesPerSheetSection.setSetting('pagesPerSheet', 4);
-    await eventToPromise('process-select-change', pagesPerSheetSection);
-    assertEquals(4, pagesPerSheetSection.getSettingValue('pagesPerSheet'));
-    assertEquals(
-        MarginsType.DEFAULT, pagesPerSheetSection.getSettingValue('margins'));
-  });
-
   // Tests that selecting a new option in the dropdown updates the setting.
   test('select option', async () => {
     // Verify that the selected option and names are as expected.
diff --git a/chrome/test/data/webui/settings/security_keys_subpage_test.js b/chrome/test/data/webui/settings/security_keys_subpage_test.js
index 9606327..63aed64 100644
--- a/chrome/test/data/webui/settings/security_keys_subpage_test.js
+++ b/chrome/test/data/webui/settings/security_keys_subpage_test.js
@@ -828,11 +828,10 @@
     await uiReady;
 
     assertShown(allDivs, dialog, 'enroll');
-    uiReady =
-        test_util.eventToPromise('bio-enroll-dialog-ready-for-testing', dialog);
     cr.webUIListenerCallback(
-        'security-keys-bio-enroll-status', {status: 0, remaining: 1});
-    await uiReady;
+        'security-keys-bio-enroll-status',
+        {status: settings.SampleStatus.OK, remaining: 1});
+    Polymer.dom.flush();
     assertFalse(dialog.$.arc.isComplete());
     assertFalse(dialog.$.cancelButton.hidden);
     assert(dialog.$.confirmButton.hidden);
@@ -843,7 +842,6 @@
     const enrollmentName = 'New Fingerprint';
     enrollingResolver.resolve({
       code: 0,
-      remaining: 0,
       enrollment: {
         id: enrollmentId,
         name: enrollmentName,
@@ -918,4 +916,30 @@
     await uiReady;
     assertShown(allDivs, dialog, 'enrollments');
   });
+
+  test('EnrollError', async function() {
+    // Test that resolving the startEnrolling promise with a CTAP error brings
+    // up the error page.
+    const enrollResolver = new PromiseResolver;
+    browserProxy.setResponseFor('startEnrolling', enrollResolver.promise);
+
+    document.body.appendChild(dialog);
+    await browserProxy.whenCalled('startBioEnroll');
+
+    dialog.dialogPage_ = 'enrollments';
+
+    let uiReady =
+        test_util.eventToPromise('bio-enroll-dialog-ready-for-testing', dialog);
+    dialog.$.addButton.click();
+    await browserProxy.whenCalled('startEnrolling');
+    await uiReady;
+
+    uiReady =
+        test_util.eventToPromise('bio-enroll-dialog-ready-for-testing', dialog);
+
+    enrollResolver.resolve({code: settings.Ctap2Status.ERR_INVALID_OPTION});
+
+    await uiReady;
+    assertShown(allDivs, dialog, 'error');
+  });
 });
diff --git a/chrome/utility/safe_browsing/mac/BUILD.gn b/chrome/utility/safe_browsing/mac/BUILD.gn
index 58cb512..cb104a3 100644
--- a/chrome/utility/safe_browsing/mac/BUILD.gn
+++ b/chrome/utility/safe_browsing/mac/BUILD.gn
@@ -55,9 +55,7 @@
 }
 
 executable("crdmg") {
-  sources = [
-    "crdmg.cc",
-  ]
+  sources = [ "crdmg.cc" ]
 
   deps = [
     ":dmg_common",
@@ -67,9 +65,7 @@
 }
 
 fuzzer_test("safe_browsing_dmg_fuzzer") {
-  sources = [
-    "dmg_fuzzer.cc",
-  ]
+  sources = [ "dmg_fuzzer.cc" ]
 
   deps = [
     ":dmg_common",
@@ -78,9 +74,7 @@
 }
 
 fuzzer_test("safe_browsing_hfs_fuzzer") {
-  sources = [
-    "hfs_fuzzer.cc",
-  ]
+  sources = [ "hfs_fuzzer.cc" ]
 
   deps = [
     ":dmg_common",
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index 67752d67..00a770c 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -161,9 +161,9 @@
   surface_->SetEmbeddedSurfaceId(base::BindRepeating(
       &WebContentController::GetSurfaceId, base::Unretained(this)));
 
-  current_rfh_ = GetWebContents()->GetMainFrame();
-  if (current_rfh_) {
-    auto size = current_rfh_->GetFrameSize();
+  content::RenderFrameHost* rfh = GetWebContents()->GetMainFrame();
+  if (rfh) {
+    const base::Optional<gfx::Size>& size = rfh->GetFrameSize();
     if (size.has_value())
       surface_->SetEmbeddedSurfaceSize(*size);
   }
@@ -424,8 +424,11 @@
 void WebContentController::FrameSizeChanged(
     content::RenderFrameHost* render_frame_host,
     const gfx::Size& frame_size) {
-  if (render_frame_host == current_rfh_ && surface_)
+  content::RenderFrameHost* rfh = GetWebContents()->GetMainFrame();
+  if (render_frame_host == rfh && surface_) {
     surface_->SetEmbeddedSurfaceSize(frame_size);
+    surface_->Commit();
+  }
 }
 
 void WebContentController::RenderFrameCreated(
@@ -443,8 +446,6 @@
 void WebContentController::RenderFrameDeleted(
     content::RenderFrameHost* render_frame_host) {
   current_render_frame_set_.erase(render_frame_host);
-  if (render_frame_host == current_rfh_)
-    current_rfh_ = nullptr;
 }
 
 void WebContentController::RenderFrameHostChanged(
@@ -452,8 +453,8 @@
     content::RenderFrameHost* new_host) {
   // The surface ID may have changed, so trigger a new commit to re-issue the
   // draw quad.
-  current_rfh_ = new_host;
-  if (surface_) {
+  content::RenderFrameHost* rfh = GetWebContents()->GetMainFrame();
+  if (new_host == rfh && surface_) {
     if (new_host) {
       auto size = new_host->GetFrameSize();
       if (size.has_value())
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h
index 18b602eb..0a35c6f0 100644
--- a/chromecast/browser/webview/web_content_controller.h
+++ b/chromecast/browser/webview/web_content_controller.h
@@ -127,7 +127,6 @@
   std::deque<TouchData> touch_queue_;
 
   exo::Surface* surface_ = nullptr;
-  content::RenderFrameHost* current_rfh_ = nullptr;
 
   std::set<std::string> current_javascript_channel_set_;
   std::set<content::RenderFrameHost*> current_render_frame_set_;
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc
index c21f284..e1b49368 100644
--- a/chromecast/renderer/cast_content_renderer_client.cc
+++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -246,30 +246,34 @@
 
 bool CastContentRendererClient::IsSupportedAudioType(
     const ::media::AudioType& type) {
-  if (type.spatialRendering)
+  if (type.spatial_rendering)
     return false;
 
 #if defined(OS_ANDROID)
   // No ATV device we know of has (E)AC3 decoder, so it relies on the audio sink
   // device.
-  if (type.codec == ::media::kCodecEAC3)
+  if (type.codec == ::media::kCodecEAC3) {
     return kBitstreamAudioCodecEac3 &
            supported_bitstream_audio_codecs_info_.codecs;
-  if (type.codec == ::media::kCodecAC3)
+  }
+  if (type.codec == ::media::kCodecAC3) {
     return kBitstreamAudioCodecAc3 &
            supported_bitstream_audio_codecs_info_.codecs;
-  if (type.codec == ::media::kCodecMpegHAudio)
+  }
+  if (type.codec == ::media::kCodecMpegHAudio) {
     return kBitstreamAudioCodecMpegHAudio &
            supported_bitstream_audio_codecs_info_.codecs;
+  }
 
-  // TODO(sanfin): Implement this for Android.
-  return true;
+  return ::media::IsDefaultSupportedAudioType(type);
 #else
+  if (type.profile == ::media::AudioCodecProfile::kXHE_AAC)
+    return false;
+
   // If the HDMI sink supports bitstreaming the codec, then the vendor backend
   // does not need to support it.
-  if (IsSupportedBitstreamAudioCodec(type.codec)) {
+  if (IsSupportedBitstreamAudioCodec(type.codec))
     return true;
-  }
 
   media::AudioCodec codec = media::ToCastAudioCodec(type.codec);
   // Cast platform implements software decoding of Opus and FLAC, so only PCM
diff --git a/chromeos/components/quick_answers/quick_answers_client.h b/chromeos/components/quick_answers/quick_answers_client.h
index 77b373b..6adf2c5 100644
--- a/chromeos/components/quick_answers/quick_answers_client.h
+++ b/chromeos/components/quick_answers/quick_answers_client.h
@@ -65,8 +65,8 @@
   void OnAssistantContextEnabled(bool enabled) override;
   void OnLocaleChanged(const std::string& locale) override;
 
-  // Send a quick answer request.
-  void SendRequest(const QuickAnswersRequest& quick_answers_request);
+  // Send a quick answer request. Virtual for testing.
+  virtual void SendRequest(const QuickAnswersRequest& quick_answers_request);
 
  private:
   void OnQuickAnswerReceived(std::unique_ptr<QuickAnswer> quick_answer);
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt
index e9b22ed1..d59f7246 100644
--- a/chromeos/profiles/orderfile.newest.txt
+++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@
-chromeos-chrome-orderfile-field-81-3987.18-1578307131-benchmark-81.0.4019.0-r1.orderfile.xz
\ No newline at end of file
+chromeos-chrome-orderfile-field-81-3987.39-1578912426-benchmark-81.0.4019.0-r1.orderfile.xz
\ No newline at end of file
diff --git a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.cc b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.cc
index 5ed526e..140ce7ad 100644
--- a/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_feature_status_setter_impl.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "chromeos/components/multidevice/logging/logging.h"
 #include "chromeos/services/device_sync/async_execution_time_metrics_logger.h"
@@ -24,7 +25,7 @@
 
 namespace {
 
-// Timeout values for asynchronous operation.
+// Timeout values for asynchronous operations.
 // TODO(https://crbug.com/933656): Use async execution time metric to tune these
 // timeout values.
 constexpr base::TimeDelta kWaitingForClientAppMetadataTimeout =
@@ -34,14 +35,27 @@
 
 void RecordClientAppMetadataFetchMetrics(const base::TimeDelta& execution_time,
                                          CryptAuthAsyncTaskResult result) {
-  // TODO(https://crbug.com/933656, https://crbug.com/936273): Add metrics to
-  // track async execution times and failure rates due to async timeouts.
+  base::UmaHistogramCustomTimes(
+      "CryptAuth.DeviceSyncV2.FeatureStatusSetter.ExecutionTime."
+      "ClientAppMetadataFetch",
+      execution_time, base::TimeDelta::FromSeconds(1) /* min */,
+      kWaitingForClientAppMetadataTimeout /* max */, 100 /* buckets */);
+  LogCryptAuthAsyncTaskSuccessMetric(
+      "CryptAuth.DeviceSyncV2.FeatureStatusSetter.AsyncTaskResult."
+      "ClientAppMetadataFetch",
+      result);
 }
 
 void RecordBatchSetFeatureStatusesMetrics(const base::TimeDelta& execution_time,
                                           CryptAuthApiCallResult result) {
-  // TODO(https://crbug.com/933656, https://crbug.com/936273): Add metrics to
-  // track async execution times and failure rates due to async timeouts.
+  LogAsyncExecutionTimeMetric(
+      "CryptAuth.DeviceSyncV2.FeatureStatusSetter.ExecutionTime."
+      "SetFeatureStatuses",
+      execution_time);
+  LogCryptAuthApiCallSuccessMetric(
+      "CryptAuth.DeviceSyncV2.FeatureStatusSetter.ApiCallResult."
+      "SetFeatureStatuses",
+      result);
 }
 
 }  // namespace
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc
index 317c0b4..d1c39b4 100644
--- a/components/cronet/url_request_context_config.cc
+++ b/components/cronet/url_request_context_config.cc
@@ -227,6 +227,13 @@
       }
       ++it;
     }
+
+    for (const auto& supported_version : quic::AllSupportedVersions()) {
+      if (quic::AlpnForVersion(supported_version) == version) {
+        supported_versions.push_back(supported_version);
+        break;
+      }
+    }
   }
   return supported_versions;
 }
diff --git a/components/cronet/url_request_context_config_unittest.cc b/components/cronet/url_request_context_config_unittest.cc
index e1ae9b7..d49d02a 100644
--- a/components/cronet/url_request_context_config_unittest.cc
+++ b/components/cronet/url_request_context_config_unittest.cc
@@ -349,6 +349,57 @@
                                     quic::QUIC_VERSION_46));
 }
 
+TEST(URLRequestContextConfigTest, SetSupportedQuicVersionByAlpn) {
+  base::test::TaskEnvironment task_environment_(
+      base::test::TaskEnvironment::MainThreadType::IO);
+
+  URLRequestContextConfig config(
+      // Enable QUIC.
+      true,
+      // QUIC User Agent ID.
+      "Default QUIC User Agent ID",
+      // Enable SPDY.
+      true,
+      // Enable Brotli.
+      false,
+      // Type of http cache.
+      URLRequestContextConfig::HttpCacheType::DISK,
+      // Max size of http cache in bytes.
+      1024000,
+      // Disable caching for HTTP responses. Other information may be stored in
+      // the cache.
+      false,
+      // Storage path for http cache and cookie storage.
+      "/data/data/org.chromium.net/app_cronet_test/test_storage",
+      // Accept-Language request header field.
+      "foreign-language",
+      // User-Agent request header field.
+      "fake agent",
+      // JSON encoded experimental options.
+      "{\"QUIC\":{\"quic_version\":\"h3-T050\"}}",
+      // MockCertVerifier to use for testing purposes.
+      std::unique_ptr<net::CertVerifier>(),
+      // Enable network quality estimator.
+      false,
+      // Enable Public Key Pinning bypass for local trust anchors.
+      true,
+      // Optional network thread priority.
+      base::Optional<double>());
+
+  net::URLRequestContextBuilder builder;
+  config.ConfigureURLRequestContextBuilder(&builder);
+  // Set a ProxyConfigService to avoid DCHECK failure when building.
+  builder.set_proxy_config_service(
+      std::make_unique<net::ProxyConfigServiceFixed>(
+          net::ProxyConfigWithAnnotation::CreateDirect()));
+  std::unique_ptr<net::URLRequestContext> context(builder.Build());
+  const net::QuicParams* quic_params = context->quic_context()->params();
+  EXPECT_EQ(quic_params->supported_versions.size(), 1u);
+  EXPECT_EQ(
+      quic_params->supported_versions[0],
+      quic::ParsedQuicVersion(quic::PROTOCOL_TLS1_3, quic::QUIC_VERSION_50));
+}
+
 TEST(URLRequestContextConfigTest, SetUnsupportedQuicVersion) {
   base::test::TaskEnvironment task_environment_(
       base::test::TaskEnvironment::MainThreadType::IO);
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc
index e14561cd..91aaf01 100644
--- a/components/exo/client_controlled_shell_surface.cc
+++ b/components/exo/client_controlled_shell_surface.cc
@@ -1092,10 +1092,25 @@
   if (expected_orientation_ == orientation_)
     orientation_compositor_lock_.reset();
 
-  widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
-                                          pending_always_on_top_
-                                              ? ui::ZOrderLevel::kFloatingWindow
-                                              : ui::ZOrderLevel::kNormal);
+
+  ui::ZOrderLevel z_order_level = pending_always_on_top_
+                                   ? ui::ZOrderLevel::kFloatingWindow
+                                   : ui::ZOrderLevel::kNormal;
+  ash::WindowState* window_state = GetWindowState();
+  if (window_state->IsPip()) {
+    // CTS requires a PIP window to stay at the initial position that Android
+    // calculates. UpdatePipBounds() is triggered by setting the window always
+    // on top, and depending on the density, it's adjusted by one pixel, which
+    // makes CTS fail.
+    // TODO(takise): Remove this workaround once ARC P is gone. See b/147847272
+    // for more detail.
+    base::AutoReset<bool> resetter(&ignore_bounds_change_request_, true);
+    widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
+                                            z_order_level);
+  } else {
+    widget_->GetNativeWindow()->SetProperty(aura::client::kZOrderingKey,
+                                            z_order_level);
+  }
 }
 
 void ClientControlledShellSurface::OnSurfaceDestroying(Surface* surface) {
diff --git a/components/exo/touch.cc b/components/exo/touch.cc
index f68b336f..a6c5160 100644
--- a/components/exo/touch.cc
+++ b/components/exo/touch.cc
@@ -19,19 +19,6 @@
 namespace exo {
 namespace {
 
-// Helper function that returns an iterator to the first item in |vector|
-// with |value|.
-template <typename T, typename U>
-typename T::iterator FindVectorItem(T& vector, U value) {
-  return std::find(vector.begin(), vector.end(), value);
-}
-
-// Helper function that returns true if |vector| contains an item with |value|.
-template <typename T, typename U>
-bool VectorContainsItem(T& vector, U value) {
-  return FindVectorItem(vector, value) != vector.end();
-}
-
 gfx::PointF EventLocationInWindow(ui::TouchEvent* event, aura::Window* window) {
   ui::Layer* root = window->GetRootWindow()->layer();
   ui::Layer* target = window->layer();
@@ -57,8 +44,7 @@
   delegate_->OnTouchDestroying(this);
   if (HasStylusDelegate())
     stylus_delegate_->OnTouchDestroying(this);
-  if (focus_)
-    focus_->RemoveSurfaceObserver(this);
+  CancelAllTouches();
   WMHelper::GetInstance()->RemovePreTargetHandler(this);
 }
 
@@ -80,30 +66,33 @@
   switch (event->type()) {
     case ui::ET_TOUCH_PRESSED: {
       // Early out if event doesn't contain a valid target for touch device.
+      // TODO(b/147848270): Verify GetEffectiveTargetForEvent gets the correct
+      // surface when input is captured.
       Surface* target = GetEffectiveTargetForEvent(event);
       if (!target)
         return;
 
       TRACE_EXO_INPUT_EVENT(event);
+      DCHECK(touch_points_surface_map_.find(touch_pointer_id) ==
+             touch_points_surface_map_.end());
 
-      // If this is the first touch point then target becomes the focus surface
-      // until all touch points have been released.
-      if (touch_points_.empty()) {
-        DCHECK(!focus_);
-        focus_ = target;
-        focus_->AddSurfaceObserver(this);
+      touch_points_surface_map_.emplace(touch_pointer_id, target);
+
+      // Update the count of pointers on the target surface.
+      auto it = surface_touch_count_map_.find(target);
+      if (it == surface_touch_count_map_.end()) {
+        target->AddSurfaceObserver(this);
+        surface_touch_count_map_.emplace(target, 1);
+      } else {
+        it->second++;
       }
 
-      DCHECK(!VectorContainsItem(touch_points_, touch_pointer_id));
-      touch_points_.push_back(touch_pointer_id);
+      // Convert location to target surface coordinate space.
+      const gfx::PointF location =
+          EventLocationInWindow(event, target->window());
 
-      // Convert location to focus surface coordinate space.
-      DCHECK(focus_);
-      gfx::PointF location = EventLocationInWindow(event, focus_->window());
-
-      // Generate a touch down event for the focus surface. Note that this can
-      // be different from the target surface.
-      delegate_->OnTouchDown(focus_, event->time_stamp(), touch_pointer_id,
+      // Generate a touch down event for the target surface.
+      delegate_->OnTouchDown(target, event->time_stamp(), touch_pointer_id,
                              location);
       if (stylus_delegate_ && event->pointer_details().pointer_type !=
                                   ui::EventPointerType::POINTER_TYPE_TOUCH) {
@@ -113,51 +102,51 @@
       send_details = true;
     } break;
     case ui::ET_TOUCH_RELEASED: {
-      auto it = FindVectorItem(touch_points_, touch_pointer_id);
-      if (it == touch_points_.end())
+      auto it = touch_points_surface_map_.find(touch_pointer_id);
+      if (it == touch_points_surface_map_.end())
         return;
 
+      Surface* target = it->second;
+      DCHECK(target);
+
       TRACE_EXO_INPUT_EVENT(event);
 
-      touch_points_.erase(it);
+      touch_points_surface_map_.erase(it);
 
-      // Reset focus surface if this is the last touch point.
-      if (touch_points_.empty()) {
-        DCHECK(focus_);
-        focus_->RemoveSurfaceObserver(this);
-        focus_ = nullptr;
+      // Update the count of pointers on the target surface.
+      auto count_it = surface_touch_count_map_.find(target);
+      if (count_it == surface_touch_count_map_.end())
+        return;
+      if ((--count_it->second) <= 0) {
+        surface_touch_count_map_.erase(target);
+        target->RemoveSurfaceObserver(this);
       }
 
       delegate_->OnTouchUp(event->time_stamp(), touch_pointer_id);
       seat_->AbortPendingDragOperation();
     } break;
     case ui::ET_TOUCH_MOVED: {
-      auto it = FindVectorItem(touch_points_, touch_pointer_id);
-      if (it == touch_points_.end())
+      auto it = touch_points_surface_map_.find(touch_pointer_id);
+      if (it == touch_points_surface_map_.end())
         return;
 
+      Surface* target = it->second;
+      DCHECK(target);
+
       TRACE_EXO_INPUT_EVENT(event);
 
-      DCHECK(focus_);
       // Convert location to focus surface coordinate space.
-      gfx::PointF location = EventLocationInWindow(event, focus_->window());
+      gfx::PointF location = EventLocationInWindow(event, target->window());
       delegate_->OnTouchMotion(event->time_stamp(), touch_pointer_id, location);
       send_details = true;
     } break;
     case ui::ET_TOUCH_CANCELLED: {
-      auto it = FindVectorItem(touch_points_, touch_pointer_id);
-      if (it == touch_points_.end())
-        return;
-
       TRACE_EXO_INPUT_EVENT(event);
 
-      DCHECK(focus_);
-      focus_->RemoveSurfaceObserver(this);
-      focus_ = nullptr;
-
       // Cancel the full set of touch sequences as soon as one is canceled.
-      touch_points_.clear();
+      CancelAllTouches();
       delegate_->OnTouchCancel();
+
       seat_->AbortPendingDragOperation();
     } break;
     default:
@@ -194,13 +183,9 @@
 // SurfaceObserver overrides:
 
 void Touch::OnSurfaceDestroying(Surface* surface) {
-  DCHECK(surface == focus_);
-  focus_ = nullptr;
-  surface->RemoveSurfaceObserver(this);
-
-  // Cancel touch sequences.
-  DCHECK_NE(touch_points_.size(), 0u);
-  touch_points_.clear();
+  // TODO(b/147848407): Do not cancel touches on surfaces of different clients
+  // when this surface dies.
+  CancelAllTouches();
   delegate_->OnTouchCancel();
 }
 
@@ -216,4 +201,12 @@
   return delegate_->CanAcceptTouchEventsForSurface(target) ? target : nullptr;
 }
 
+void Touch::CancelAllTouches() {
+  std::for_each(surface_touch_count_map_.begin(),
+                surface_touch_count_map_.end(),
+                [this](auto& it) { it.first->RemoveSurfaceObserver(this); });
+  touch_points_surface_map_.clear();
+  surface_touch_count_map_.clear();
+}
+
 }  // namespace exo
diff --git a/components/exo/touch.h b/components/exo/touch.h
index 4177305..44da98e 100644
--- a/components/exo/touch.h
+++ b/components/exo/touch.h
@@ -5,8 +5,7 @@
 #ifndef COMPONENTS_EXO_TOUCH_H_
 #define COMPONENTS_EXO_TOUCH_H_
 
-#include <vector>
-
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "components/exo/surface_observer.h"
 #include "ui/events/event_handler.h"
@@ -45,6 +44,9 @@
   // Returns the effective target for |event|.
   Surface* GetEffectiveTargetForEvent(ui::LocatedEvent* event) const;
 
+  // Cancels touches on all the surfaces.
+  void CancelAllTouches();
+
   // The delegate instance that all events are dispatched to.
   TouchDelegate* const delegate_;
 
@@ -53,11 +55,11 @@
   // The delegate instance that all stylus related events are dispatched to.
   TouchStylusDelegate* stylus_delegate_ = nullptr;
 
-  // The current focus surface for the touch device.
-  Surface* focus_ = nullptr;
+  // Map of touch points to its focus surface.
+  base::flat_map<int, Surface*> touch_points_surface_map_;
 
-  // Vector of touch points in focus surface.
-  std::vector<int> touch_points_;
+  // Map of a touched surface to the count of touch pointers on that surface.
+  base::flat_map<Surface*, int> surface_touch_count_map_;
 
   DISALLOW_COPY_AND_ASSIGN(Touch);
 };
diff --git a/components/exo/touch_unittest.cc b/components/exo/touch_unittest.cc
index ce0df01..9489130 100644
--- a/components/exo/touch_unittest.cc
+++ b/components/exo/touch_unittest.cc
@@ -245,6 +245,79 @@
   touch.reset();
 }
 
+TEST_F(TouchTest, OnTouchCancelWhenSurfaceDestroying) {
+  auto surface = std::make_unique<Surface>();
+  auto shell_surface = std::make_unique<ShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  auto buffer = std::make_unique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  MockTouchDelegate delegate;
+  Seat seat;
+  auto touch = std::make_unique<Touch>(&delegate, &seat);
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
+      .Times(testing::AnyNumber());
+  EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(surface.get()))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(delegate,
+              OnTouchDown(surface.get(), testing::_, 1, gfx::PointF()));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  const gfx::Point origin = surface->window()->GetBoundsInScreen().origin();
+  generator.set_current_screen_location(origin);
+  generator.PressTouchId(1);
+
+  // Since there is an active touch pointer on the surface, destroying the
+  // surface should cancel touches.
+  EXPECT_CALL(delegate, OnTouchCancel());
+  EXPECT_CALL(delegate, OnTouchFrame());
+  surface.reset();
+
+  EXPECT_CALL(delegate, OnTouchDestroying(touch.get()));
+  touch.reset();
+}
+
+TEST_F(TouchTest, OnTouchCancelNotTriggeredAfterTouchReleased) {
+  auto surface = std::make_unique<Surface>();
+  auto shell_surface = std::make_unique<ShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  auto buffer = std::make_unique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  MockTouchDelegate delegate;
+  Seat seat;
+  auto touch = std::make_unique<Touch>(&delegate, &seat);
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
+      .Times(testing::AnyNumber());
+  EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(surface.get()))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(delegate,
+              OnTouchDown(surface.get(), testing::_, 1, gfx::PointF()));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  const gfx::Point origin = surface->window()->GetBoundsInScreen().origin();
+  generator.set_current_screen_location(origin);
+  generator.PressTouchId(1);
+
+  EXPECT_CALL(delegate, OnTouchUp(testing::_, 1));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  generator.ReleaseTouchId(1);
+
+  // Since the surface no longer has any active touch pointers, destroying the
+  // surface should not cancel any touches.
+  EXPECT_CALL(delegate, OnTouchCancel()).Times(0);
+  surface.reset();
+
+  EXPECT_CALL(delegate, OnTouchDestroying(touch.get()));
+  touch.reset();
+}
+
 TEST_F(TouchTest, IgnoreTouchEventDuringModal) {
   auto window = exo_test_helper()->CreateWindow(10, 10, false);
   auto modal = exo_test_helper()->CreateWindow(5, 5, true);
@@ -465,5 +538,77 @@
   touch.reset();
 }
 
+TEST_F(TouchTest, TouchMultipleSurfaces) {
+  auto surface = std::make_unique<Surface>();
+  auto shell_surface = std::make_unique<ShellSurface>(surface.get());
+  gfx::Size buffer_size(10, 10);
+  auto buffer = std::make_unique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size));
+  surface->Attach(buffer.get());
+  surface->Commit();
+
+  auto child_surface = std::make_unique<Surface>();
+  auto child_shell_surface = std::make_unique<ShellSurface>(
+      child_surface.get(), gfx::Point(), true, false,
+      ash::desks_util::GetActiveDeskContainerId());
+  child_shell_surface->DisableMovement();
+  child_shell_surface->SetParent(shell_surface.get());
+  gfx::Size child_buffer_size(15, 15);
+  auto child_buffer = std::make_unique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(child_buffer_size));
+  child_surface->Attach(child_buffer.get());
+  child_surface->Commit();
+
+  MockTouchDelegate delegate;
+  Seat seat;
+  auto touch = std::make_unique<Touch>(&delegate, &seat);
+  ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+  // Touch down on the two surfaces.
+  EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_))
+      .Times(testing::AnyNumber());
+  EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(surface.get()))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(delegate,
+              OnTouchDown(surface.get(), testing::_, 1, gfx::PointF()));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  const gfx::Point origin = surface->window()->GetBoundsInScreen().origin();
+  generator.set_current_screen_location(origin);
+  generator.PressTouchId(1);
+
+  EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(child_surface.get()))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(delegate,
+              OnTouchDown(child_surface.get(), testing::_, 2, gfx::PointF()));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  const gfx::Point child_origin =
+      child_surface->window()->GetBoundsInScreen().origin();
+  generator.set_current_screen_location(child_origin);
+  generator.PressTouchId(2);
+
+  // Move the two touch pointers.
+  for (int i = 1; i <= 10; i++) {
+    EXPECT_CALL(delegate, OnTouchMotion(testing::_, 1, gfx::PointF(i, i)));
+    EXPECT_CALL(delegate, OnTouchFrame());
+    generator.MoveTouchId(origin + gfx::Vector2d(i, i), 1);
+
+    EXPECT_CALL(delegate, OnTouchMotion(testing::_, 2, gfx::PointF(i, i)));
+    EXPECT_CALL(delegate, OnTouchFrame());
+    generator.MoveTouchId(child_origin + gfx::Vector2d(i, i), 2);
+  }
+
+  // Release the two touch pointers.
+  EXPECT_CALL(delegate, OnTouchUp(testing::_, 2));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  generator.ReleaseTouchId(2);
+
+  EXPECT_CALL(delegate, OnTouchUp(testing::_, 1));
+  EXPECT_CALL(delegate, OnTouchFrame());
+  generator.ReleaseTouchId(1);
+
+  EXPECT_CALL(delegate, OnTouchDestroying(touch.get()));
+  touch.reset();
+}
+
 }  // namespace
 }  // namespace exo
diff --git a/components/management_strings.grdp b/components/management_strings.grdp
index b496ab02..23fb73f 100644
--- a/components/management_strings.grdp
+++ b/components/management_strings.grdp
@@ -107,6 +107,12 @@
     <message name="IDS_MANAGEMENT_CROSTINI" desc="Message stating that administrators can see Crostini usage">
       Linux apps installed and when they were last used
     </message>
+    <message name="IDS_MANAGEMENT_REPORT_EXTENSIONS" desc="Message stating that administrators can see user's extensions.">
+      Which extensions you have installed
+    </message>
+    <message name="IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS" desc="Message stating that administrators can see user's installed Android applications.">
+      Which Android applications you have installed
+    </message>
   </if>
 
   <!-- Strings related to extension reporting section of the management page -->
@@ -146,7 +152,7 @@
     Version information about your device and browser
   </message>
   <message name="IDS_MANAGEMENT_EXTENSION_REPORT_EXTENSIONS_PLUGINS" desc="Message explaining that an extension currently reports the user's exensions and plugins">
-    Information about installed extensions and plugins
+    Which extensions and plugins you have installed
   </message>
   <message name="IDS_MANAGEMENT_EXTENSION_REPORT_SAFE_BROWSING_WARNINGS" desc="Message explaining that an extension currently reports the user's Safe Browsing warnings and ignored warnings">
     <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1"&gt;<ex>&lt;a target="_blank" href="https://example.com"&gt;</ex></ph>Safe Browsing<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph> warnings
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_EXTENSION_REPORT_EXTENSIONS_PLUGINS.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_EXTENSION_REPORT_EXTENSIONS_PLUGINS.png.sha1
new file mode 100644
index 0000000..5ecf731
--- /dev/null
+++ b/components/management_strings_grdp/IDS_MANAGEMENT_EXTENSION_REPORT_EXTENSIONS_PLUGINS.png.sha1
@@ -0,0 +1 @@
+bb0501833c51254d74f10991fa7c464cef62bf47
\ No newline at end of file
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS.png.sha1
new file mode 100644
index 0000000..37e3aea
--- /dev/null
+++ b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS.png.sha1
@@ -0,0 +1 @@
+480e3aeb02cf88728e502eb8dc4f9cad34fd317c
\ No newline at end of file
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_EXTENSIONS.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_EXTENSIONS.png.sha1
new file mode 100644
index 0000000..0e340d12
--- /dev/null
+++ b/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_EXTENSIONS.png.sha1
@@ -0,0 +1 @@
+277501a55fd6d254b16e098e3cf330423a821018
\ No newline at end of file
diff --git a/components/management_strings_grdp/OWNERS b/components/management_strings_grdp/OWNERS
new file mode 100644
index 0000000..a026d38
--- /dev/null
+++ b/components/management_strings_grdp/OWNERS
@@ -0,0 +1,2 @@
+file://docs/privacy/OWNERS
+# COMPONENT: Privacy
diff --git a/components/management_strings_grdp/README.md b/components/management_strings_grdp/README.md
new file mode 100644
index 0000000..119d8b9
--- /dev/null
+++ b/components/management_strings_grdp/README.md
@@ -0,0 +1,5 @@
+This directory of image SHA-1 hashes is used to improve translations of UI
+strings through context images for translators.
+
+See also: [Chrome Translation Screenshots - Instructions & FAQ
+](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn
index a8ed78b..55325f8 100644
--- a/components/metrics/BUILD.gn
+++ b/components/metrics/BUILD.gn
@@ -15,9 +15,7 @@
     "demographic_metrics_provider.h",
   ]
 
-  public_deps = [
-    "//third_party/metrics_proto",
-  ]
+  public_deps = [ "//third_party/metrics_proto" ]
 
   deps = [
     ":metrics",
@@ -56,6 +54,10 @@
     "drive_metrics_provider_win.cc",
     "enabled_state_provider.cc",
     "enabled_state_provider.h",
+    "entropy_state.cc",
+    "entropy_state.h",
+    "entropy_state_provider.cc",
+    "entropy_state_provider.h",
     "environment_recorder.cc",
     "environment_recorder.h",
     "expired_histogram_util.cc",
@@ -177,9 +179,7 @@
   java_cpp_strings("java_switches_srcjar") {
     # External code should depend on ":metrics_java" instead.
     visibility = [ ":*" ]
-    sources = [
-      "//components/metrics/metrics_switches.cc",
-    ]
+    sources = [ "//components/metrics/metrics_switches.cc" ]
     template =
         "//components/metrics/android/java_templates/MetricsSwitches.java.tmpl"
   }
@@ -200,9 +200,7 @@
     "component_metrics_provider.h",
   ]
 
-  public_deps = [
-    "//third_party/metrics_proto",
-  ]
+  public_deps = [ "//third_party/metrics_proto" ]
 
   deps = [
     ":metrics",
@@ -218,9 +216,7 @@
       "gpu/gpu_metrics_provider.h",
     ]
 
-    public_deps = [
-      ":metrics",
-    ]
+    public_deps = [ ":metrics" ]
     deps = [
       "//base",
       "//content/public/browser",
@@ -241,9 +237,7 @@
     "net/wifi_access_point_info_provider.h",
   ]
 
-  public_deps = [
-    ":metrics",
-  ]
+  public_deps = [ ":metrics" ]
   allow_circular_includes_from = [ ":metrics" ]
 
   deps = [
@@ -273,9 +267,7 @@
     "ui/screen_info_metrics_provider.h",
   ]
 
-  public_deps = [
-    ":metrics",
-  ]
+  public_deps = [ ":metrics" ]
   deps = [
     "//base",
     "//ui/display",
@@ -308,9 +300,7 @@
     "call_stack_profile_encoding.h",
     "call_stack_profile_params.h",
   ]
-  sources = [
-    "call_stack_profile_encoding.cc",
-  ]
+  sources = [ "call_stack_profile_encoding.cc" ]
 
   deps = [
     "//base:base",
@@ -330,9 +320,7 @@
     "call_stack_profile_metadata.cc",
     "child_call_stack_profile_collector.cc",
   ]
-  public_deps = [
-    ":call_stack_profile_params",
-  ]
+  public_deps = [ ":call_stack_profile_params" ]
   deps = [
     "//base",
     "//components/metrics/public/mojom:call_stack_mojo_bindings",
@@ -346,12 +334,8 @@
 
 # Dependency for browser process use of the CallStackProfileBuilder.
 source_set("call_stack_profile_builder") {
-  deps = [
-    ":metrics",
-  ]
-  public_deps = [
-    ":child_call_stack_profile_builder",
-  ]
+  deps = [ ":metrics" ]
+  public_deps = [ ":child_call_stack_profile_builder" ]
 }
 
 # The browser process mojo service for collecting profiles from child
@@ -381,12 +365,8 @@
     "test_metrics_service_client.h",
   ]
 
-  public_deps = [
-    ":metrics",
-  ]
-  deps = [
-    "//base",
-  ]
+  public_deps = [ ":metrics" ]
+  deps = [ "//base" ]
 }
 
 if (is_linux) {
@@ -397,9 +377,7 @@
       "serialization/serialization_utils.cc",
       "serialization/serialization_utils.h",
     ]
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
   }
 }
 
@@ -417,6 +395,8 @@
     "data_use_tracker_unittest.cc",
     "demographic_metrics_provider_unittest.cc",
     "drive_metrics_provider_unittest.cc",
+    "entropy_state_provider_unittest.cc",
+    "entropy_state_unittest.cc",
     "environment_recorder_unittest.cc",
     "expired_histograms_checker_unittest.cc",
     "field_trials_provider_unittest.cc",
@@ -497,9 +477,7 @@
 
 # Convenience testing target
 test("metrics_unittests") {
-  sources = [
-    "//components/test/run_all_unittests.cc",
-  ]
+  sources = [ "//components/test/run_all_unittests.cc" ]
   deps = [
     ":unit_tests",
     "//components/test:test_support",
diff --git a/components/metrics/entropy_state.cc b/components/metrics/entropy_state.cc
new file mode 100644
index 0000000..2e4603f
--- /dev/null
+++ b/components/metrics/entropy_state.cc
@@ -0,0 +1,148 @@
+// 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/metrics/entropy_state.h"
+
+#include "base/command_line.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/no_destructor.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/metrics_switches.h"
+#include "components/prefs/pref_service.h"
+
+namespace metrics {
+
+namespace {
+
+// The argument used to generate a non-identifying entropy source. We want no
+// more than 13 bits of entropy, so use this max to return a number in the range
+// [0, 7999] as the entropy source (12.97 bits of entropy).
+const int kMaxLowEntropySize = 8000;
+
+// Generates a new non-identifying entropy source used to seed persistent
+// activities. Using a NoDestructor so that the new low entropy source value
+// will only be generated on first access. And thus, even though we may write
+// the new low entropy source value to prefs multiple times, it stays the same
+// value.
+int GenerateLowEntropySource() {
+  static const base::NoDestructor<int> low_entropy_source(
+      [] { return base::RandInt(0, kMaxLowEntropySize - 1); }());
+  return *low_entropy_source;
+}
+
+}  // namespace
+
+EntropyState::EntropyState(PrefService* local_state)
+    : local_state_(local_state) {}
+
+// static
+constexpr int EntropyState::kLowEntropySourceNotSet;
+
+void EntropyState::ClearPrefs() {
+  DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_);
+  local_state_->ClearPref(prefs::kMetricsLowEntropySource);
+  local_state_->ClearPref(prefs::kMetricsOldLowEntropySource);
+}
+
+// static
+void EntropyState::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
+                                kLowEntropySourceNotSet);
+  registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource,
+                                kLowEntropySourceNotSet);
+}
+
+std::string EntropyState::GetHighEntropySource(
+    const std::string& client_id,
+    const std::string& provisional_client_id) {
+  // For metrics reporting-enabled users, we combine the client ID and low
+  // entropy source to get the final entropy source.
+  // This has two useful properties:
+  //  1) It makes the entropy source less identifiable for parties that do not
+  //     know the low entropy source.
+  //  2) It makes the final entropy source resettable.
+
+  // If this install has an old low entropy source, continue using it, to avoid
+  // changing the group assignments of studies using high entropy. New installs
+  // only have the new low entropy source. If the number of installs with old
+  // sources ever becomes small enough (see UMA.LowEntropySourceValue), we could
+  // remove it, and just use the new source here.
+  int low_entropy_source = GetOldLowEntropySource();
+  if (low_entropy_source == kLowEntropySourceNotSet)
+    low_entropy_source = GetLowEntropySource();
+
+  const std::string& client_id_to_use =
+      (client_id.empty() ? provisional_client_id : client_id);
+  return client_id_to_use + base::NumberToString(low_entropy_source);
+}
+
+int EntropyState::GetLowEntropySource() {
+  UpdateLowEntropySources();
+  return low_entropy_source_;
+}
+
+int EntropyState::GetOldLowEntropySource() {
+  UpdateLowEntropySources();
+  return old_low_entropy_source_;
+}
+
+void EntropyState::UpdateLowEntropySources() {
+  // The default value for |low_entropy_source_| and the default pref value are
+  // both |kLowEntropySourceNotSet|, which indicates the value has not been set.
+  if (low_entropy_source_ != kLowEntropySourceNotSet)
+    return;
+
+  const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
+  // Only try to load the value from prefs if the user did not request a reset.
+  // Otherwise, skip to generating a new value. We would have already returned
+  // if |low_entropy_source_| were set, ensuring we only do this reset on the
+  // first call to UpdateLowEntropySources().
+  if (!command_line->HasSwitch(switches::kResetVariationState)) {
+    int new_pref = local_state_->GetInteger(prefs::kMetricsLowEntropySource);
+    if (IsValidLowEntropySource(new_pref))
+      low_entropy_source_ = new_pref;
+    int old_pref = local_state_->GetInteger(prefs::kMetricsOldLowEntropySource);
+    if (IsValidLowEntropySource(old_pref))
+      old_low_entropy_source_ = old_pref;
+  }
+
+  // If the new source is missing or corrupt (or requested to be reset), then
+  // (re)create it. Don't bother recreating the old source if it's corrupt,
+  // because we only keep the old source around for consistency, and we can't
+  // maintain a consistent value if we recreate it.
+  if (low_entropy_source_ == kLowEntropySourceNotSet) {
+    low_entropy_source_ = GenerateLowEntropySource();
+    DCHECK(IsValidLowEntropySource(low_entropy_source_));
+    local_state_->SetInteger(prefs::kMetricsLowEntropySource,
+                             low_entropy_source_);
+  }
+
+  // If the old source was present but corrupt (or requested to be reset), then
+  // we'll never use it again, so delete it.
+  if (old_low_entropy_source_ == kLowEntropySourceNotSet &&
+      local_state_->HasPrefPath(prefs::kMetricsOldLowEntropySource)) {
+    local_state_->ClearPref(prefs::kMetricsOldLowEntropySource);
+  }
+
+  DCHECK_NE(low_entropy_source_, kLowEntropySourceNotSet);
+  // TODO(crbug/1041710): Currently, these metrics might be recorded multiple
+  // times but that shouldn't matter because we can workaround it by using count
+  // unique user mode. Also, once we verify that we can persist
+  // low_entropy_source to our system profile proto, These two metrics are
+  // longer needed and should be removed.
+  base::UmaHistogramSparse("UMA.LowEntropySource3Value", low_entropy_source_);
+  if (old_low_entropy_source_ != kLowEntropySourceNotSet) {
+    base::UmaHistogramSparse("UMA.LowEntropySourceValue",
+                             old_low_entropy_source_);
+  }
+}
+
+// static
+bool EntropyState::IsValidLowEntropySource(int value) {
+  return value >= 0 && value < kMaxLowEntropySize;
+}
+
+}  // namespace metrics
diff --git a/components/metrics/entropy_state.h b/components/metrics/entropy_state.h
new file mode 100644
index 0000000..da96bd1
--- /dev/null
+++ b/components/metrics/entropy_state.h
@@ -0,0 +1,85 @@
+// 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_METRICS_ENTROPY_STATE_H_
+#define COMPONENTS_METRICS_ENTROPY_STATE_H_
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "components/prefs/pref_registry_simple.h"
+
+class PrefService;
+
+namespace metrics {
+
+// A class to get entropy source values from the PrefService.
+class EntropyState final {
+ public:
+  // Creates the EntropyState with the given |local_state| to get
+  // the entropy source value from this helper class.
+  explicit EntropyState(PrefService* local_state);
+
+  EntropyState(const EntropyState&) = delete;
+  EntropyState& operator=(const EntropyState&) = delete;
+
+  // Clears low_entropy_source and old_low_entropy_source in the prefs.
+  void ClearPrefs();
+
+  // Registers low_entropy_source and old_low_entropy_source in the prefs.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  // Returns the high entropy source for this client, which is composed of a
+  // client ID and the low entropy source. This is intended to be unique for
+  // each install. UMA must be enabled (and |client_id_| must be set) or
+  // |provisional_client_id_| must be set before calling this.
+  std::string GetHighEntropySource(const std::string& client_id,
+                                   const std::string& provisional_client_id);
+
+  // Returns the low entropy source for this client. Generates a new value if
+  // there is none. See the |low_entropy_source_| comment for more info.
+  int GetLowEntropySource();
+
+  // Returns the old low entropy source for this client. Does not generate a new
+  // value, but instead returns |kLowEntropySourceNotSet|, if there is none. See
+  // the |old_low_entropy_source_| comment for more info.
+  int GetOldLowEntropySource();
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, LowEntropySource0NotReset);
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveNoLowEntropySource);
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyNewLowEntropySource);
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, HaveOnlyOldLowEntropySource);
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptNewLowEntropySources);
+  FRIEND_TEST_ALL_PREFIXES(EntropyStateTest, CorruptOldLowEntropySources);
+
+  // Default value for prefs::kMetricsLowEntropySource.
+  static constexpr int kLowEntropySourceNotSet = -1;
+
+  // Loads the low entropy source values from prefs. Creates the new source
+  // value if it doesn't exist, but doesn't create the old source value. After
+  // this function finishes, |low_entropy_source_| will be set, but
+  // |old_low_entropy_source_| may still be |kLowEntropySourceNotSet|.
+  void UpdateLowEntropySources();
+
+  // Checks whether a value is on the range of allowed low entropy source
+  // values.
+  static bool IsValidLowEntropySource(int value);
+
+  // The local state prefs store.
+  PrefService* const local_state_;
+
+  // The non-identifying low entropy source values. These values seed the
+  // pseudorandom generators which pick experimental groups. The "old" value is
+  // thought to be biased in the wild, and is no longer used for experiments
+  // requiring low entropy. Clients which already have an "old" value continue
+  // incorporating it into the high entropy source, to avoid changing those
+  // group assignments. New clients only have the new source.
+  int low_entropy_source_ = kLowEntropySourceNotSet;
+  int old_low_entropy_source_ = kLowEntropySourceNotSet;
+};
+
+}  // namespace metrics
+
+#endif  // COMPONENTS_METRICS_ENTROPY_STATE_H_
diff --git a/components/metrics/entropy_state_provider.cc b/components/metrics/entropy_state_provider.cc
new file mode 100644
index 0000000..0c1148c
--- /dev/null
+++ b/components/metrics/entropy_state_provider.cc
@@ -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.
+
+#include "components/metrics/entropy_state_provider.h"
+
+#include "third_party/metrics_proto/system_profile.pb.h"
+
+namespace metrics {
+
+EntropyStateProvider::EntropyStateProvider(PrefService* local_state)
+    : entropy_state_(local_state) {}
+
+EntropyStateProvider::~EntropyStateProvider() = default;
+
+void EntropyStateProvider::ProvideSystemProfileMetrics(
+    SystemProfileProto* system_profile) {
+  system_profile->set_low_entropy_source(entropy_state_.GetLowEntropySource());
+  system_profile->set_old_low_entropy_source(
+      entropy_state_.GetOldLowEntropySource());
+}
+
+}  // namespace metrics
diff --git a/components/metrics/entropy_state_provider.h b/components/metrics/entropy_state_provider.h
new file mode 100644
index 0000000..feef096b
--- /dev/null
+++ b/components/metrics/entropy_state_provider.h
@@ -0,0 +1,34 @@
+// 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_METRICS_ENTROPY_STATE_PROVIDER_H_
+#define COMPONENTS_METRICS_ENTROPY_STATE_PROVIDER_H_
+
+#include "components/metrics/entropy_state.h"
+#include "components/metrics/metrics_provider.h"
+
+class PrefService;
+
+namespace metrics {
+
+// EntropyStateProvider adds information about low entropy sources in the system
+// profile. This includes |low_entropy_source| and |old_low_entropy_source|.
+class EntropyStateProvider : public MetricsProvider {
+ public:
+  explicit EntropyStateProvider(PrefService* local_state);
+  ~EntropyStateProvider() override;
+
+  EntropyStateProvider(const EntropyStateProvider&) = delete;
+  EntropyStateProvider& operator=(const EntropyStateProvider&) = delete;
+
+  void ProvideSystemProfileMetrics(
+      SystemProfileProto* system_profile_proto) override;
+
+ private:
+  EntropyState entropy_state_;
+};
+
+}  // namespace metrics
+
+#endif  // COMPONENTS_METRICS_ENTROPY_STATE_PROVIDER_H_
diff --git a/components/metrics/entropy_state_provider_unittest.cc b/components/metrics/entropy_state_provider_unittest.cc
new file mode 100644
index 0000000..fbb3415
--- /dev/null
+++ b/components/metrics/entropy_state_provider_unittest.cc
@@ -0,0 +1,43 @@
+// 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/metrics/entropy_state_provider.h"
+
+#include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/metrics_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/metrics_proto/system_profile.pb.h"
+
+namespace metrics {
+
+class EntropyStateProviderTest : public testing::Test {
+ public:
+  EntropyStateProviderTest() {
+    MetricsService::RegisterPrefs(prefs_.registry());
+  }
+
+  EntropyStateProviderTest(const EntropyStateProviderTest&) = delete;
+  EntropyStateProviderTest& operator=(const EntropyStateProviderTest&) = delete;
+
+ protected:
+  TestingPrefServiceSimple prefs_;
+};
+
+TEST_F(EntropyStateProviderTest, PopulateBothLowEntropySource) {
+  const int new_low_source = 1234;
+  const int old_low_source = 5678;
+  prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
+  prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
+
+  EntropyStateProvider provider(&prefs_);
+  SystemProfileProto system_profile;
+
+  provider.ProvideSystemProfileMetrics(&system_profile);
+
+  EXPECT_EQ(new_low_source, system_profile.low_entropy_source());
+  EXPECT_EQ(old_low_source, system_profile.old_low_entropy_source());
+}
+
+}  // namespace metrics
diff --git a/components/metrics/entropy_state_unittest.cc b/components/metrics/entropy_state_unittest.cc
new file mode 100644
index 0000000..a80a670e
--- /dev/null
+++ b/components/metrics/entropy_state_unittest.cc
@@ -0,0 +1,148 @@
+// 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/metrics/entropy_state.h"
+
+#include <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/metrics_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+
+class EntropyStateTest : public testing::Test {
+ public:
+  EntropyStateTest() { MetricsService::RegisterPrefs(prefs_.registry()); }
+
+  EntropyStateTest(const EntropyStateTest&) = delete;
+  EntropyStateTest& operator=(const EntropyStateTest&) = delete;
+
+ protected:
+  TestingPrefServiceSimple prefs_;
+};
+
+TEST_F(EntropyStateTest, LowEntropySource0NotReset) {
+  EntropyState entropy_state(&prefs_);
+  // Get the low entropy source once, to initialize it.
+  entropy_state.GetLowEntropySource();
+
+  // Now, set it to 0 and ensure it doesn't get reset.
+  entropy_state.low_entropy_source_ = 0;
+  EXPECT_EQ(0, entropy_state.GetLowEntropySource());
+  // Call it another time, just to make sure.
+  EXPECT_EQ(0, entropy_state.GetLowEntropySource());
+}
+
+TEST_F(EntropyStateTest, HaveNoLowEntropySource) {
+  EntropyState entropy_state(&prefs_);
+  // If we have neither the new nor old low entropy sources in prefs, then the
+  // new source should be created...
+  int new_low_source = entropy_state.GetLowEntropySource();
+  EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
+      << new_low_source;
+  // ...but the old source should not...
+  EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
+            entropy_state.GetOldLowEntropySource());
+  // ...and the high entropy source should include the *new* low entropy source.
+  std::string high_source = entropy_state.GetHighEntropySource(
+      "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF", "");
+  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
+                             base::CompareCase::SENSITIVE))
+      << high_source;
+}
+
+TEST_F(EntropyStateTest, HaveOnlyNewLowEntropySource) {
+  // If we have the new low entropy sources in prefs, but not the old one...
+  const int new_low_source = 1234;
+  prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
+
+  EntropyState entropy_state(&prefs_);
+  // ...then the new source should be loaded...
+  EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
+  // ...but the old source should not be created...
+  EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
+            entropy_state.GetOldLowEntropySource());
+  // ...and the high entropy source should include the *new* low entropy source.
+  std::string high_source = entropy_state.GetHighEntropySource(
+      "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF", "");
+  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
+                             base::CompareCase::SENSITIVE))
+      << high_source;
+}
+
+TEST_F(EntropyStateTest, HaveOnlyOldLowEntropySource) {
+  // If we have the old low entropy sources in prefs, but not the new one...
+  const int old_low_source = 5678;
+  prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
+
+  // ...then the new source should be created...
+  EntropyState entropy_state(&prefs_);
+
+  int new_low_source = entropy_state.GetLowEntropySource();
+  EXPECT_TRUE(EntropyState::IsValidLowEntropySource(new_low_source))
+      << new_low_source;
+  // ...and the old source should be loaded...
+  EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
+  // ...and the high entropy source should include the *old* low entropy source.
+  std::string high_source = entropy_state.GetHighEntropySource(
+      "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF", "");
+  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
+                             base::CompareCase::SENSITIVE))
+      << high_source;
+}
+
+TEST_F(EntropyStateTest, HaveBothLowEntropySources) {
+  // If we have the new and old low entropy sources in prefs...
+  const int new_low_source = 1234;
+  const int old_low_source = 5678;
+  prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
+  prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
+
+  // ...then both should be loaded...
+  EntropyState entropy_state(&prefs_);
+
+  EXPECT_EQ(new_low_source, entropy_state.GetLowEntropySource());
+  EXPECT_EQ(old_low_source, entropy_state.GetOldLowEntropySource());
+  // ...and the high entropy source should include the *old* low entropy source.
+  std::string high_source = entropy_state.GetHighEntropySource(
+      "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF", "");
+  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
+                             base::CompareCase::SENSITIVE))
+      << high_source;
+}
+
+TEST_F(EntropyStateTest, CorruptNewLowEntropySources) {
+  EntropyState entropy_state(&prefs_);
+  const int corrupt_sources[] = {-12345, -1, 8000, 12345};
+  for (int corrupt_source : corrupt_sources) {
+    // If the new low entropy source has been corrupted...
+    EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
+        << corrupt_source;
+    prefs_.SetInteger(prefs::kMetricsLowEntropySource, corrupt_source);
+    // ...then a new source should be created.
+    int loaded_source = entropy_state.GetLowEntropySource();
+    EXPECT_TRUE(EntropyState::IsValidLowEntropySource(loaded_source))
+        << loaded_source;
+  }
+}
+
+TEST_F(EntropyStateTest, CorruptOldLowEntropySources) {
+  EntropyState entropy_state(&prefs_);
+  const int corrupt_sources[] = {-12345, -1, 8000, 12345};
+  for (int corrupt_source : corrupt_sources) {
+    // If the old low entropy source has been corrupted...
+    EXPECT_FALSE(EntropyState::IsValidLowEntropySource(corrupt_source))
+        << corrupt_source;
+    prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, corrupt_source);
+    // ...then it should be ignored.
+    EXPECT_EQ(EntropyState::kLowEntropySourceNotSet,
+              entropy_state.GetOldLowEntropySource());
+  }
+}
+
+}  // namespace metrics
diff --git a/components/metrics/metrics_log.h b/components/metrics/metrics_log.h
index fc3afba..2a109d0 100644
--- a/components/metrics/metrics_log.h
+++ b/components/metrics/metrics_log.h
@@ -30,7 +30,6 @@
 namespace metrics {
 
 class MetricsProvider;
-class MetricsServiceClient;
 class DelegatingProvider;
 
 namespace internal {
diff --git a/components/metrics/metrics_state_manager.cc b/components/metrics/metrics_state_manager.cc
index 11434e279..8bba6e5c 100644
--- a/components/metrics/metrics_state_manager.cc
+++ b/components/metrics/metrics_state_manager.cc
@@ -10,7 +10,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/command_line.h"
 #include "base/guid.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -22,6 +21,7 @@
 #include "build/build_config.h"
 #include "components/metrics/cloned_install_detector.h"
 #include "components/metrics/enabled_state_provider.h"
+#include "components/metrics/entropy_state.h"
 #include "components/metrics/machine_id_provider.h"
 #include "components/metrics/metrics_log.h"
 #include "components/metrics/metrics_pref_names.h"
@@ -43,12 +43,6 @@
 // [0, 7999] as the entropy source (12.97 bits of entropy).
 const int kMaxLowEntropySize = 8000;
 
-// Generates a new non-identifying entropy source used to seed persistent
-// activities.
-int GenerateLowEntropySource() {
-  return base::RandInt(0, kMaxLowEntropySize - 1);
-}
-
 int64_t ReadEnabledDate(PrefService* local_state) {
   return local_state->GetInt64(prefs::kMetricsReportingEnabledTimestamp);
 }
@@ -134,8 +128,7 @@
       store_client_info_(store_client_info),
       load_client_info_(retrieve_client_info),
       clean_exit_beacon_(backup_registry_key, local_state),
-      low_entropy_source_(kLowEntropySourceNotSet),
-      old_low_entropy_source_(kLowEntropySourceNotSet),
+      entropy_state_(local_state),
       entropy_source_returned_(ENTROPY_SOURCE_NONE),
       metrics_ids_were_reset_(false) {
   ResetMetricsIDsIfNecessary();
@@ -324,18 +317,12 @@
   registry->RegisterBooleanPref(prefs::kMetricsResetIds, false);
   registry->RegisterStringPref(prefs::kMetricsClientID, std::string());
   registry->RegisterInt64Pref(prefs::kMetricsReportingEnabledTimestamp, 0);
-  registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
-                                kLowEntropySourceNotSet);
-  registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource,
-                                kLowEntropySourceNotSet);
   registry->RegisterInt64Pref(prefs::kInstallDate, 0);
 
+  EntropyState::RegisterPrefs(registry);
   ClonedInstallDetector::RegisterPrefs(registry);
 }
 
-// static
-constexpr int MetricsStateManager::kLowEntropySourceNotSet;
-
 void MetricsStateManager::BackUpCurrentClientInfo() {
   ClientInfo client_info;
   client_info.client_id = client_id_;
@@ -363,82 +350,16 @@
   // constructor and calling this, because field trial setup happens at Chrome
   // initialization. Only one of these is expected to hold a value.
   DCHECK(client_id_.empty() != provisional_client_id_.empty());
-
-  // For metrics reporting-enabled users, we combine the client ID and low
-  // entropy source to get the final entropy source.
-  // This has two useful properties:
-  //  1) It makes the entropy source less identifiable for parties that do not
-  //     know the low entropy source.
-  //  2) It makes the final entropy source resettable.
-
-  // If this install has an old low entropy source, continue using it, to avoid
-  // changing the group assignments of studies using high entropy. New installs
-  // only have the new low entropy source. If the number of installs with old
-  // sources ever becomes small enough (see UMA.LowEntropySourceValue), we could
-  // remove it, and just use the new source here.
-  int low_entropy_source = GetOldLowEntropySource();
-  if (low_entropy_source == kLowEntropySourceNotSet)
-    low_entropy_source = GetLowEntropySource();
-
-  const std::string& client_id_to_use =
-      (client_id_.empty() ? provisional_client_id_ : client_id_);
-  return client_id_to_use + base::NumberToString(low_entropy_source);
+  return entropy_state_.GetHighEntropySource(client_id_,
+                                             provisional_client_id_);
 }
 
 int MetricsStateManager::GetLowEntropySource() {
-  UpdateLowEntropySources();
-  return low_entropy_source_;
+  return entropy_state_.GetLowEntropySource();
 }
 
 int MetricsStateManager::GetOldLowEntropySource() {
-  UpdateLowEntropySources();
-  return old_low_entropy_source_;
-}
-
-void MetricsStateManager::UpdateLowEntropySources() {
-  // The default value for |low_entropy_source_| and the default pref value are
-  // both |kLowEntropySourceNotSet|, which indicates the value has not been set.
-  if (low_entropy_source_ != kLowEntropySourceNotSet)
-    return;
-
-  const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess());
-  // Only try to load the value from prefs if the user did not request a reset.
-  // Otherwise, skip to generating a new value. We would have already returned
-  // if |low_entropy_source_| were set, ensuring we only do this reset on the
-  // first call to UpdateLowEntropySources().
-  if (!command_line->HasSwitch(switches::kResetVariationState)) {
-    int new_pref = local_state_->GetInteger(prefs::kMetricsLowEntropySource);
-    if (IsValidLowEntropySource(new_pref))
-      low_entropy_source_ = new_pref;
-    int old_pref = local_state_->GetInteger(prefs::kMetricsOldLowEntropySource);
-    if (IsValidLowEntropySource(old_pref))
-      old_low_entropy_source_ = old_pref;
-  }
-
-  // If the new source is missing or corrupt (or requested to be reset), then
-  // (re)create it. Don't bother recreating the old source if it's corrupt,
-  // because we only keep the old source around for consistency, and we can't
-  // maintain a consistent value if we recreate it.
-  if (low_entropy_source_ == kLowEntropySourceNotSet) {
-    low_entropy_source_ = GenerateLowEntropySource();
-    DCHECK(IsValidLowEntropySource(low_entropy_source_));
-    local_state_->SetInteger(prefs::kMetricsLowEntropySource,
-                             low_entropy_source_);
-  }
-
-  // If the old source was present but corrupt (or requested to be reset), then
-  // we'll never use it again, so delete it.
-  if (old_low_entropy_source_ == kLowEntropySourceNotSet &&
-      local_state_->HasPrefPath(prefs::kMetricsOldLowEntropySource)) {
-    local_state_->ClearPref(prefs::kMetricsOldLowEntropySource);
-  }
-
-  DCHECK_NE(low_entropy_source_, kLowEntropySourceNotSet);
-  base::UmaHistogramSparse("UMA.LowEntropySource3Value", low_entropy_source_);
-  if (old_low_entropy_source_ != kLowEntropySourceNotSet) {
-    base::UmaHistogramSparse("UMA.LowEntropySourceValue",
-                             old_low_entropy_source_);
-  }
+  return entropy_state_.GetOldLowEntropySource();
 }
 
 void MetricsStateManager::UpdateEntropySourceReturnedValue(
@@ -460,20 +381,13 @@
   UMA_HISTOGRAM_BOOLEAN("UMA.MetricsIDsReset", true);
 
   DCHECK(client_id_.empty());
-  DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_);
 
   local_state_->ClearPref(prefs::kMetricsClientID);
-  local_state_->ClearPref(prefs::kMetricsLowEntropySource);
-  local_state_->ClearPref(prefs::kMetricsOldLowEntropySource);
   local_state_->ClearPref(prefs::kMetricsResetIds);
+  entropy_state_.ClearPrefs();
 
   // Also clear the backed up client info.
   store_client_info_.Run(ClientInfo());
 }
 
-// static
-bool MetricsStateManager::IsValidLowEntropySource(int value) {
-  return value >= 0 && value < kMaxLowEntropySize;
-}
-
 }  // namespace metrics
diff --git a/components/metrics/metrics_state_manager.h b/components/metrics/metrics_state_manager.h
index 517e18a..bb184a42 100644
--- a/components/metrics/metrics_state_manager.h
+++ b/components/metrics/metrics_state_manager.h
@@ -15,6 +15,7 @@
 #include "base/strings/string16.h"
 #include "components/metrics/clean_exit_beacon.h"
 #include "components/metrics/client_info.h"
+#include "components/metrics/entropy_state.h"
 
 class PrefService;
 class PrefRegistrySimple;
@@ -108,17 +109,6 @@
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, CheckProviderResetIds);
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, EntropySourceUsed_Low);
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, EntropySourceUsed_High);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, LowEntropySource0NotReset);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, HaveNoLowEntropySource);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
-                           HaveOnlyNewLowEntropySource);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
-                           HaveOnlyOldLowEntropySource);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest, HaveBothLowEntropySources);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
-                           CorruptNewLowEntropySources);
-  FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
-                           CorruptOldLowEntropySources);
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
                            ProvisionalClientId_PromotedToClientId);
   FRIEND_TEST_ALL_PREFIXES(MetricsStateManagerTest,
@@ -136,9 +126,6 @@
     ENTROPY_SOURCE_ENUM_SIZE,
   };
 
-  // Default value for prefs::kMetricsLowEntropySource.
-  static constexpr int kLowEntropySourceNotSet = -1;
-
   // Creates the MetricsStateManager with the given |local_state|. Uses
   // |enabled_state_provider| to query whether there is consent for metrics
   // reporting, and if it is enabled. Clients should instead use Create(), which
@@ -163,21 +150,12 @@
   // |provisional_client_id_| must be set before calling this.
   std::string GetHighEntropySource();
 
-  // Returns the low entropy source for this client. Generates a new value if
-  // there is none. See the |low_entropy_source_| comment for more info.
+  // Returns the low entropy source for this client.
   int GetLowEntropySource();
 
-  // Returns the old low entropy source for this client. Does not generate a new
-  // value, but instead returns |kLowEntropySourceNotSet|, if there is none. See
-  // the |old_low_entropy_source_| comment for more info.
+  // Returns the old low entropy source for this client.
   int GetOldLowEntropySource();
 
-  // Loads the low entropy source values from prefs. Creates the new source
-  // value if it doesn't exist, but doesn't create the old source value. After
-  // this function finishes, |low_entropy_source_| will be set, but
-  // |old_low_entropy_source_| may still be |kLowEntropySourceNotSet|.
-  void UpdateLowEntropySources();
-
   // Updates |entropy_source_returned_| with |type| iff the current value is
   // ENTROPY_SOURCE_NONE and logs the new value in a histogram.
   void UpdateEntropySourceReturnedValue(EntropySourceType type);
@@ -193,10 +171,6 @@
   // pref is true.
   void ResetMetricsIDsIfNecessary();
 
-  // Checks whether a value is on the range of allowed low entropy source
-  // values.
-  static bool IsValidLowEntropySource(int value);
-
   // Whether an instance of this class exists. Used to enforce that there aren't
   // multiple instances of this class at a given time.
   static bool instance_exists_;
@@ -231,14 +205,8 @@
   // trials don't toggle state between first and second run.
   std::string provisional_client_id_;
 
-  // The non-identifying low entropy source values. These values seed the
-  // pseudorandom generators which pick experimental groups. The "old" value is
-  // thought to be biased in the wild, and is no longer used for experiments
-  // requiring low entropy. Clients which already have an "old" value continue
-  // incorporating it into the high entropy source, to avoid changing those
-  // group assignments. New clients only have the new source.
-  int low_entropy_source_;
-  int old_low_entropy_source_;
+  // An instance of EntropyState for getting the entropy source values.
+  EntropyState entropy_state_;
 
   // The last entropy source returned by this service, used for testing.
   EntropySourceType entropy_source_returned_;
diff --git a/components/metrics/metrics_state_manager_unittest.cc b/components/metrics/metrics_state_manager_unittest.cc
index 98eeefb..ffb75833 100644
--- a/components/metrics/metrics_state_manager_unittest.cc
+++ b/components/metrics/metrics_state_manager_unittest.cc
@@ -175,129 +175,6 @@
             state_manager->entropy_source_returned());
 }
 
-TEST_F(MetricsStateManagerTest, LowEntropySource0NotReset) {
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-
-  // Get the low entropy source once, to initialize it.
-  state_manager->GetLowEntropySource();
-
-  // Now, set it to 0 and ensure it doesn't get reset.
-  state_manager->low_entropy_source_ = 0;
-  EXPECT_EQ(0, state_manager->GetLowEntropySource());
-  // Call it another time, just to make sure.
-  EXPECT_EQ(0, state_manager->GetLowEntropySource());
-}
-
-TEST_F(MetricsStateManagerTest, HaveNoLowEntropySource) {
-  prefs_.SetString(prefs::kMetricsClientID,
-                   "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
-  EnableMetricsReporting();
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  // If we have neither the new nor old low entropy sources in prefs, then the
-  // new source should be created...
-  int new_low_source = state_manager->GetLowEntropySource();
-  EXPECT_TRUE(MetricsStateManager::IsValidLowEntropySource(new_low_source))
-      << new_low_source;
-  // ...but the old source should not...
-  EXPECT_EQ(MetricsStateManager::kLowEntropySourceNotSet,
-            state_manager->GetOldLowEntropySource());
-  // ...and the high entropy source should include the *new* low entropy source.
-  std::string high_source = state_manager->GetHighEntropySource();
-  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
-                             base::CompareCase::SENSITIVE))
-      << high_source;
-}
-
-TEST_F(MetricsStateManagerTest, HaveOnlyNewLowEntropySource) {
-  // If we have the new low entropy sources in prefs, but not the old one...
-  const int new_low_source = 1234;
-  prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
-  prefs_.SetString(prefs::kMetricsClientID,
-                   "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
-  EnableMetricsReporting();
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  // ...then the new source should be loaded...
-  EXPECT_EQ(new_low_source, state_manager->GetLowEntropySource());
-  // ...but the old source should not be created...
-  EXPECT_EQ(MetricsStateManager::kLowEntropySourceNotSet,
-            state_manager->GetOldLowEntropySource());
-  // ...and the high entropy source should include the *new* low entropy source.
-  std::string high_source = state_manager->GetHighEntropySource();
-  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(new_low_source),
-                             base::CompareCase::SENSITIVE))
-      << high_source;
-}
-
-TEST_F(MetricsStateManagerTest, HaveOnlyOldLowEntropySource) {
-  // If we have the old low entropy sources in prefs, but not the new one...
-  const int old_low_source = 5678;
-  prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
-  prefs_.SetString(prefs::kMetricsClientID,
-                   "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
-  EnableMetricsReporting();
-  // ...then the new source should be created...
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  int new_low_source = state_manager->GetLowEntropySource();
-  EXPECT_TRUE(MetricsStateManager::IsValidLowEntropySource(new_low_source))
-      << new_low_source;
-  // ...and the old source should be loaded...
-  EXPECT_EQ(old_low_source, state_manager->GetOldLowEntropySource());
-  // ...and the high entropy source should include the *old* low entropy source.
-  std::string high_source = state_manager->GetHighEntropySource();
-  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
-                             base::CompareCase::SENSITIVE))
-      << high_source;
-}
-
-TEST_F(MetricsStateManagerTest, HaveBothLowEntropySources) {
-  // If we have the new and old low entropy sources in prefs...
-  const int new_low_source = 1234;
-  const int old_low_source = 5678;
-  prefs_.SetInteger(prefs::kMetricsLowEntropySource, new_low_source);
-  prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, old_low_source);
-  prefs_.SetString(prefs::kMetricsClientID,
-                   "AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEF");
-  EnableMetricsReporting();
-  // ...then both should be loaded...
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  EXPECT_EQ(new_low_source, state_manager->GetLowEntropySource());
-  EXPECT_EQ(old_low_source, state_manager->GetOldLowEntropySource());
-  // ...and the high entropy source should include the *old* low entropy source.
-  std::string high_source = state_manager->GetHighEntropySource();
-  EXPECT_TRUE(base::EndsWith(high_source, base::NumberToString(old_low_source),
-                             base::CompareCase::SENSITIVE))
-      << high_source;
-}
-
-TEST_F(MetricsStateManagerTest, CorruptNewLowEntropySources) {
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  const int corrupt_sources[] = {-12345, -1, 8000, 12345};
-  for (int corrupt_source : corrupt_sources) {
-    // If the new low entropy source has been corrupted...
-    EXPECT_FALSE(MetricsStateManager::IsValidLowEntropySource(corrupt_source))
-        << corrupt_source;
-    prefs_.SetInteger(prefs::kMetricsLowEntropySource, corrupt_source);
-    // ...then a new source should be created.
-    int loaded_source = state_manager->GetLowEntropySource();
-    EXPECT_TRUE(MetricsStateManager::IsValidLowEntropySource(loaded_source))
-        << loaded_source;
-  }
-}
-
-TEST_F(MetricsStateManagerTest, CorruptOldLowEntropySources) {
-  std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
-  const int corrupt_sources[] = {-12345, -1, 8000, 12345};
-  for (int corrupt_source : corrupt_sources) {
-    // If the old low entropy source has been corrupted...
-    EXPECT_FALSE(MetricsStateManager::IsValidLowEntropySource(corrupt_source))
-        << corrupt_source;
-    prefs_.SetInteger(prefs::kMetricsOldLowEntropySource, corrupt_source);
-    // ...then it should be ignored.
-    EXPECT_EQ(MetricsStateManager::kLowEntropySourceNotSet,
-              state_manager->GetOldLowEntropySource());
-  }
-}
-
 // Check that setting the kMetricsResetIds pref to true causes the client id to
 // be reset. We do not check that the low entropy source is reset because we
 // cannot ensure that metrics state manager won't generate the same id again.
diff --git a/components/page_info_strings.grdp b/components/page_info_strings.grdp
index b503291..d28dbe9a 100644
--- a/components/page_info_strings.grdp
+++ b/components/page_info_strings.grdp
@@ -439,7 +439,7 @@
         You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
       </message>
       <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chrome user that they have reused their saved password on the current website and to change their password on three domains.">
-        You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
+        You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
       </message>
       <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
         Chrome can help you protect your Google Account and change your password.
@@ -468,7 +468,7 @@
         You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and other sites where you use this password and changing it now.
       </message>
       <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS" desc="A short paragraph explaining to a Chromium user that they have reused their saved password on the current website and to change their password on three domains.">
-        You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, and <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
+        You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1">$1<ex>www.google.com</ex></ph>, <ph name="WEBSITE_2">$2<ex>www.reddit.com</ex></ph>, <ph name="WEBSITE_3">$3<ex>www.amazon.com</ex></ph>, and other sites where you use this password and changing it now.
       </message>
       <message name="IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SYNC" desc="A short paragraph explaining to a Chrome sync user that they have reused their Google password on the current website.">
         Chromium can help you protect your Google Account and change your password.
diff --git a/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS.png.sha1 b/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS.png.sha1
index c1a60967..afb9e93 100644
--- a/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS.png.sha1
+++ b/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_2_DOMAINS.png.sha1
@@ -1 +1 @@
-08d5c55a859c199f77c01b9235109fd921e2c535
\ No newline at end of file
+6938cc3defe94b847fe471717add55a032b2b691
\ No newline at end of file
diff --git a/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS.png.sha1 b/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS.png.sha1
index e5b2bdb..de0a1e8 100644
--- a/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS.png.sha1
+++ b/components/page_info_strings_grdp/IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS_SAVED_3_DOMAINS.png.sha1
@@ -1 +1 @@
-07319414e3a0820ed860f77e9a6490bc185756eb
\ No newline at end of file
+103f3c14b26de5be2fe329bf1a81ceedb26b4c00
\ No newline at end of file
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index 7c92a67..0d5ada7 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -584,15 +584,15 @@
 
   if (in_foreground_) {
     if (committed_load_)
-      committed_load_->WebContentsShown();
+      committed_load_->PageShown();
     for (const auto& kv : provisional_loads_) {
-      kv.second->WebContentsShown();
+      kv.second->PageShown();
     }
   } else {
     if (committed_load_)
-      committed_load_->WebContentsHidden();
+      committed_load_->PageHidden();
     for (const auto& kv : provisional_loads_) {
-      kv.second->WebContentsHidden();
+      kv.second->PageHidden();
     }
   }
 }
diff --git a/components/page_load_metrics/browser/page_load_tracker.cc b/components/page_load_metrics/browser/page_load_tracker.cc
index cc0d15d..c5350a2c 100644
--- a/components/page_load_metrics/browser/page_load_tracker.cc
+++ b/components/page_load_metrics/browser/page_load_tracker.cc
@@ -298,7 +298,7 @@
   }
 }
 
-void PageLoadTracker::WebContentsHidden() {
+void PageLoadTracker::PageHidden() {
   // Only log the first time we background in a given page load.
   if (!first_background_time_.has_value()) {
     // Make sure we either started in the foreground and haven't been
@@ -316,7 +316,7 @@
                              metrics_update_dispatcher_.timing());
 }
 
-void PageLoadTracker::WebContentsShown() {
+void PageLoadTracker::PageShown() {
   // Only log the first time we foreground in a given page load.
   if (!first_foreground_time_.has_value()) {
     // Make sure we either started in the background and haven't been
diff --git a/components/page_load_metrics/browser/page_load_tracker.h b/components/page_load_metrics/browser/page_load_tracker.h
index b0ea1dde..fa0c09a 100644
--- a/components/page_load_metrics/browser/page_load_tracker.h
+++ b/components/page_load_metrics/browser/page_load_tracker.h
@@ -238,8 +238,8 @@
       content::NavigationHandle* navigation_handle);
   void FailedProvisionalLoad(content::NavigationHandle* navigation_handle,
                              base::TimeTicks failed_load_time);
-  void WebContentsHidden();
-  void WebContentsShown();
+  void PageHidden();
+  void PageShown();
   void FrameDeleted(content::RenderFrameHost* rfh);
 
   void OnInputEvent(const blink::WebInputEvent& event);
diff --git a/components/policy/core/common/policy_loader_mac.mm b/components/policy/core/common/policy_loader_mac.mm
index 7c95301..8e96bbd 100644
--- a/components/policy/core/common/policy_loader_mac.mm
+++ b/components/policy/core/common/policy_loader_mac.mm
@@ -72,17 +72,6 @@
                             managed_policy_file_exists);
   base::UmaHistogramBoolean("EnterpriseCheck.IsEnterpriseUser",
                             base::IsMachineExternallyManaged());
-
-  base::UmaHistogramEnumeration("EnterpriseCheck.Mac.IsDeviceMDMEnrolledOld",
-                                base::IsDeviceRegisteredWithManagementOld());
-  base::UmaHistogramEnumeration("EnterpriseCheck.Mac.IsDeviceMDMEnrolledNew",
-                                base::IsDeviceRegisteredWithManagementNew());
-  base::DeviceUserDomainJoinState state =
-      base::AreDeviceAndUserJoinedToDomain();
-  base::UmaHistogramBoolean("EnterpriseCheck.Mac.IsDeviceDomainJoined",
-                            state.device_joined);
-  base::UmaHistogramBoolean("EnterpriseCheck.Mac.IsCurrentUserDomainUser",
-                            state.user_joined);
 }
 
 std::unique_ptr<PolicyBundle> PolicyLoaderMac::Load() {
diff --git a/components/printing/common/print.mojom b/components/printing/common/print.mojom
index c4707f46..3695656 100644
--- a/components/printing/common/print.mojom
+++ b/components/printing/common/print.mojom
@@ -66,4 +66,8 @@
 
   // Tells the RenderFrame that printing is done so it can clean up.
   PrintingDone(bool success);
+
+  // Tells the RenderFrame to initiate printing or print preview for a
+  // particular node, depending on which mode the RenderFrame is in.
+  PrintNodeUnderContextMenu();
 };
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h
index 859514b..ad1b1a5 100644
--- a/components/printing/common/print_messages.h
+++ b/components/printing/common/print_messages.h
@@ -341,12 +341,6 @@
 IPC_STRUCT_END()
 
 
-// Messages sent from the browser to the renderer.
-
-// Tells the RenderFrame to initiate printing or print preview for a particular
-// node, depending on which mode the RenderFrame is in.
-IPC_MESSAGE_ROUTED0(PrintMsg_PrintNodeUnderContextMenu)
-
 // Messages sent from the renderer to the browser.
 
 // Tells the browser that the renderer is done calculating the number of
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 1af8977a..17c86537 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1347,6 +1347,11 @@
   is_printing_enabled_ = enabled;
 }
 
+void PrintRenderFrameHelper::PrintNodeUnderContextMenu() {
+  ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
+  PrintNode(render_frame()->GetWebFrame()->ContextMenuNode());
+}
+
 void PrintRenderFrameHelper::GetPageSizeAndContentAreaFromPageLayout(
     const PageSizeMargins& page_layout_in_points,
     gfx::Size* page_size,
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h
index 0778dee..51cfabd4d 100644
--- a/components/printing/renderer/print_render_frame_helper.h
+++ b/components/printing/renderer/print_render_frame_helper.h
@@ -234,6 +234,7 @@
   void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override;
   void PrintingDone(bool success) override;
   void SetPrintingEnabled(bool enabled) override;
+  void PrintNodeUnderContextMenu() override;
 
   // Get |page_size| and |content_area| information from
   // |page_layout_in_points|.
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index 54e8edcd..472541f 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -376,7 +376,7 @@
   // constraints explicitly disable serializing images using the transfer cache
   // and serialization of PaintRecords.
   cc::PaintOp::SerializeOptions options(nullptr, nullptr, nullptr, nullptr,
-                                        nullptr, nullptr, false, false, 0, 0.f,
+                                        nullptr, nullptr, false, false, 0,
                                         SkMatrix::I());
   cc::PaintOpWriter writer(buffer.data(), buffer.size(), options,
                            true /* enable_security_constraints */);
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 0bc3ed0..367b561 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1923,6 +1923,8 @@
     "webui/web_ui_url_loader_factory_internal.h",
     "worker_host/dedicated_worker_host.cc",
     "worker_host/dedicated_worker_host.h",
+    "worker_host/dedicated_worker_service_impl.cc",
+    "worker_host/dedicated_worker_service_impl.h",
     "worker_host/shared_worker_connector_impl.cc",
     "worker_host/shared_worker_connector_impl.h",
     "worker_host/shared_worker_content_settings_proxy_impl.cc",
diff --git a/content/browser/appcache/appcache_host.cc b/content/browser/appcache/appcache_host.cc
index 5309671..1a63f68 100644
--- a/content/browser/appcache/appcache_host.cc
+++ b/content/browser/appcache/appcache_host.cc
@@ -71,6 +71,12 @@
          !security_policy->HasSecurityState(process_id);  // process shutdown.
 }
 
+base::debug::CrashKeyString* GetDocumentUrlCrashKey() {
+  static auto* appcache_document_url_key = base::debug::AllocateCrashKeyString(
+      "appcache_document_url", base::debug::CrashKeySize::Size256);
+  return appcache_document_url_key;
+}
+
 }  // namespace
 
 AppCacheHost::AppCacheHost(
@@ -150,6 +156,8 @@
 
   DCHECK_NE(process_id_, ChildProcessHost::kInvalidUniqueID);
   if (!CanAccessDocumentURL(process_id_, document_url)) {
+    base::debug::SetCrashKeyString(GetDocumentUrlCrashKey(),
+                                   document_url.spec());
     mojo::ReportBadMessage("ACH_SELECT_CACHE_DOCUMENT_URL_ACCESS_NOT_ALLOWED");
     return;
   }
@@ -256,6 +264,8 @@
   }
 
   if (!CanAccessDocumentURL(process_id_, document_url)) {
+    base::debug::SetCrashKeyString(GetDocumentUrlCrashKey(),
+                                   document_url.spec());
     mojo::ReportBadMessage(
         "ACH_MARK_AS_FOREIGN_ENTRY_DOCUMENT_URL_ACCESS_NOT_ALLOWED");
     return;
diff --git a/content/browser/background_fetch/background_fetch_test_base.cc b/content/browser/background_fetch/background_fetch_test_base.cc
index 02e52ed9..b278795 100644
--- a/content/browser/background_fetch/background_fetch_test_base.cc
+++ b/content/browser/background_fetch/background_fetch_test_base.cc
@@ -130,7 +130,7 @@
 
   {
     base::RunLoop run_loop;
-    embedded_worker_test_helper_.context()->storage()->FindRegistrationForId(
+    embedded_worker_test_helper_.context()->registry()->FindRegistrationForId(
         service_worker_registration_id, origin.GetURL(),
         base::BindOnce(&DidFindServiceWorkerRegistration,
                        &service_worker_registration, run_loop.QuitClosure()));
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 8f0353a..55d77f9 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -248,6 +248,8 @@
   NC_SAME_DOCUMENT_POST_COMMIT_ERROR = 220,
   RFH_INVALID_WEB_UI_CONTROLLER = 221,
   RFPH_ADVANCE_FOCUS_INTO_PORTAL = 222,
+  RFH_UNEXPECTED_EMBEDDING_TOKEN = 223,
+  RFH_MISSING_EMBEDDING_TOKEN = 224,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index ab0cdc2..c71b329 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -351,6 +351,8 @@
   if (data_.metrics_name.empty())
     data_.metrics_name = GetProcessTypeNameInEnglish(data_.process_type);
 
+  data_.sandbox_type = delegate->GetSandboxType();
+
   notify_child_disconnected_ = true;
   child_process_.reset(new ChildProcessLauncher(
       std::move(delegate), std::move(cmd_line), data_.id, this,
diff --git a/content/browser/content_index/content_index_database_unittest.cc b/content/browser/content_index/content_index_database_unittest.cc
index 5e7f6530..ab1f4cb 100644
--- a/content/browser/content_index/content_index_database_unittest.cc
+++ b/content/browser/content_index/content_index_database_unittest.cc
@@ -257,7 +257,7 @@
 
     {
       base::RunLoop run_loop;
-      embedded_worker_test_helper_.context()->storage()->FindRegistrationForId(
+      embedded_worker_test_helper_.context()->registry()->FindRegistrationForId(
           service_worker_registration_id, origin_.GetURL(),
           base::BindOnce(&DidFindServiceWorkerRegistration,
                          &service_worker_registration_,
diff --git a/content/browser/devtools/devtools_background_services_context_impl_unittest.cc b/content/browser/devtools/devtools_background_services_context_impl_unittest.cc
index 26224c84..ef9621d 100644
--- a/content/browser/devtools/devtools_background_services_context_impl_unittest.cc
+++ b/content/browser/devtools/devtools_background_services_context_impl_unittest.cc
@@ -224,7 +224,7 @@
 
     {
       base::RunLoop run_loop;
-      embedded_worker_test_helper_.context()->storage()->FindRegistrationForId(
+      embedded_worker_test_helper_.context()->registry()->FindRegistrationForId(
           service_worker_registration_id, origin_.GetURL(),
           base::BindOnce(&DidFindServiceWorkerRegistration,
                          &service_worker_registration_,
diff --git a/content/browser/frame_host/embedding_token_browsertest.cc b/content/browser/frame_host/embedding_token_browsertest.cc
new file mode 100644
index 0000000..5d8f929
--- /dev/null
+++ b/content/browser/frame_host/embedding_token_browsertest.cc
@@ -0,0 +1,246 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/unguessable_token.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class EmbeddingTokenBrowserTest : public ContentBrowserTest {
+ public:
+  EmbeddingTokenBrowserTest() = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ContentBrowserTest::SetUpCommandLine(command_line);
+    IsolateAllSitesForTesting(command_line);
+  }
+
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+    SetupCrossSiteRedirector(embedded_test_server());
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+  EmbeddingTokenBrowserTest(const EmbeddingTokenBrowserTest&) = delete;
+  EmbeddingTokenBrowserTest& operator=(const EmbeddingTokenBrowserTest&) =
+      delete;
+
+ private:
+  FrameTreeVisualizer visualizer_;
+};
+
+IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest, NoEmbeddingTokenOnMainFrame) {
+  GURL a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
+  GURL b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
+  // Starts without an embedding token.
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  // Embedding tokens don't get added to the main frame.
+  EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
+  root = static_cast<WebContentsImpl*>(shell()->web_contents())
+             ->GetFrameTree()
+             ->root();
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
+  root = static_cast<WebContentsImpl*>(shell()->web_contents())
+             ->GetFrameTree()
+             ->root();
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+}
+
+IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
+                       EmbeddingTokensAddedToCrossSiteIFrames) {
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(
+                   "a.com", "/cross_site_iframe_factory.html?a(b(a),c,a)")));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  ASSERT_EQ(3U, root->child_count());
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  // Child 0 (b) should have an embedding token.
+  auto child_0_token = root->child_at(0)->GetEmbeddingToken();
+  ASSERT_TRUE(child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
+
+  // Child 0 (a) of Child 0 (b) should have an embedding token.
+  ASSERT_EQ(1U, root->child_at(0)->child_count());
+  auto child_0_0_token = root->child_at(0)->child_at(0)->GetEmbeddingToken();
+  ASSERT_TRUE(child_0_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_0_0_token);
+  EXPECT_NE(child_0_token, child_0_0_token);
+
+  // Child 1 (c) should have an embedding token.
+  auto child_1_token = root->child_at(1)->GetEmbeddingToken();
+  ASSERT_TRUE(child_1_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_1_token);
+  EXPECT_NE(child_0_token, child_1_token);
+  EXPECT_NE(child_0_0_token, child_1_token);
+
+  // Child 2 (a) shouldn't have an embedding token as it is same site.
+  EXPECT_FALSE(root->child_at(2)->GetEmbeddingToken().has_value());
+
+  // TODO(ckitagawa): Somehow assert that the parent and child have matching
+  // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
+}
+
+IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
+                       EmbeddingTokensSwapOnCrossSiteNavigations) {
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(
+                   "a.com", "/cross_site_iframe_factory.html?a(b)")));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  ASSERT_EQ(1U, root->child_count());
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  // Child 0 (b) should have an embedding token.
+  FrameTreeNode* target = root->child_at(0);
+  auto child_0_token = target->GetEmbeddingToken();
+  ASSERT_TRUE(child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
+
+  // Navigate child 0 (b) to another site (cross-process) the token should swap.
+  {
+    RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
+    NavigateIframeToURL(shell()->web_contents(), "child-0",
+                        embedded_test_server()
+                            ->GetURL("c.com", "/site_isolation/")
+                            .Resolve("blank.html"));
+    deleted_observer.WaitUntilDeleted();
+  }
+  auto new_child_0_token = root->child_at(0)->GetEmbeddingToken();
+  ASSERT_TRUE(new_child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
+  EXPECT_NE(child_0_token, new_child_0_token);
+
+  // TODO(ckitagawa): Somehow assert that the parent and child have matching
+  // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
+}
+
+IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
+                       EmbeddingTokensDoNotSwapOnSameSiteNavigations) {
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(
+                   "a.com", "/cross_site_iframe_factory.html?a(a)")));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  ASSERT_EQ(1U, root->child_count());
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+  auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
+  // Navigate child 0 to another site (cross-process) a token should be created.
+  {
+    RenderFrameDeletedObserver deleted_observer(
+        root->child_at(0)->current_frame_host());
+    NavigateIframeToURL(shell()->web_contents(), "child-0",
+                        b_url.Resolve("blank.html"));
+    deleted_observer.WaitUntilDeleted();
+  }
+
+  // Child 0 (b) should have an embedding token.
+  FrameTreeNode* target = root->child_at(0);
+  auto child_0_token = target->GetEmbeddingToken();
+  ASSERT_TRUE(child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
+
+  // Navigate child 0 (b) to same origin the token should not swap.
+  NavigateIframeToURL(shell()->web_contents(), "child-0",
+                      b_url.Resolve("valid.html"));
+  auto new_child_0_token = root->child_at(0)->GetEmbeddingToken();
+  ASSERT_TRUE(new_child_0_token.has_value());
+  EXPECT_EQ(child_0_token, new_child_0_token);
+
+  // TODO(ckitagawa): Somehow assert that the parent and child have matching
+  // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
+}
+
+IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
+                       EmbeddingTokenRemovedOnSubframeNavigationToSameOrigin) {
+  auto a_url = embedded_test_server()->GetURL("a.com", "/");
+  EXPECT_TRUE(NavigateToURL(
+      shell(), a_url.Resolve("cross_site_iframe_factory.html?a(b)")));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  ASSERT_EQ(1U, root->child_count());
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  // Child 0 (b) should have an embedding token.
+  FrameTreeNode* target = root->child_at(0);
+  auto child_0_token = target->GetEmbeddingToken();
+  ASSERT_TRUE(child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
+
+  // Navigate child 0 (b) to the same site as the main frame. This shouldn't
+  // create an embedding token as the child is now local.
+  {
+    RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
+    NavigateIframeToURL(shell()->web_contents(), "child-0",
+                        a_url.Resolve("site_isolation/").Resolve("blank.html"));
+    deleted_observer.WaitUntilDeleted();
+  }
+  ASSERT_FALSE(root->child_at(0)->GetEmbeddingToken().has_value());
+
+  // TODO(ckitagawa): Somehow assert that the parent and child have matching
+  // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
+}
+
+IN_PROC_BROWSER_TEST_F(
+    EmbeddingTokenBrowserTest,
+    EmbeddingTokenAddedOnSubframeNavigationAwayFromSameOrigin) {
+  auto a_url = embedded_test_server()->GetURL("a.com", "/");
+  EXPECT_TRUE(NavigateToURL(
+      shell(), a_url.Resolve("cross_site_iframe_factory.html?a(a)")));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  ASSERT_EQ(1U, root->child_count());
+  EXPECT_FALSE(root->GetEmbeddingToken().has_value());
+
+  // Child shouldn't have an embedding token.
+  FrameTreeNode* target = root->child_at(0);
+  auto child_0_token = target->GetEmbeddingToken();
+  EXPECT_FALSE(child_0_token.has_value());
+
+  // Navigate child 0 to a different site. This should now have an embedding
+  // token.
+  {
+    RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
+    NavigateIframeToURL(shell()->web_contents(), "child-0",
+                        embedded_test_server()
+                            ->GetURL("b.com", "/site_isolation/")
+                            .Resolve("blank.html"));
+    deleted_observer.WaitUntilDeleted();
+  }
+  auto new_child_0_token = root->child_at(0)->GetEmbeddingToken();
+  ASSERT_TRUE(new_child_0_token.has_value());
+  EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
+
+  // TODO(ckitagawa): Somehow assert that the parent and child have matching
+  // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
+}
+
+}  // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index 330efb1..7bac4b1 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -727,4 +727,20 @@
   }
 }
 
+const base::Optional<base::UnguessableToken>& FrameTreeNode::GetEmbeddingToken()
+    const {
+  return embedding_token_;
+}
+
+void FrameTreeNode::SetEmbeddingToken(
+    const base::Optional<base::UnguessableToken>& embedding_token) {
+  embedding_token_ = embedding_token;
+  if (embedding_token_.has_value()) {
+    // Propagate a non-null embedding token to the parent. Parents will
+    // invalidate their own tokens if a previously remote frame becomes local to
+    // them.
+    render_manager_.SetEmbeddingToken(embedding_token.value());
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h
index 7d8054d7..4d4f1f8 100644
--- a/content/browser/frame_host/frame_tree_node.h
+++ b/content/browser/frame_host/frame_tree_node.h
@@ -406,6 +406,18 @@
   void SetOpenerFeaturePolicyState(
       const blink::FeaturePolicy::FeatureState& feature_state);
 
+  // Returns the embedding token for the frame. A frame is embedded if it is the
+  // child to a parent frame that is cross-process. As such, this will return
+  // base::nullopt for:
+  // - The main frame.
+  // - Child frames that are in the same process as their parent.
+  const base::Optional<base::UnguessableToken>& GetEmbeddingToken() const;
+
+  // Called by NavigationImpl::DidNavigate() on completion of a navigation to
+  // update the embedding token for the frame.
+  void SetEmbeddingToken(
+      const base::Optional<base::UnguessableToken>& embedding_token);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessFeaturePolicyBrowserTest,
                            ContainerPolicyDynamic);
@@ -508,6 +520,13 @@
   // to look up the FrameTreeNode instance.
   base::UnguessableToken devtools_frame_token_;
 
+  // A token tracking the embedding relationship between a out-of-process
+  // frames. This is only accessible by the renderer for the active
+  // RenderFrameHost and the renderer for the RenderFrameProxyHost from
+  // RenderFrameProxyHostManager::GetProxyToParent(). Should only be set
+  // if the frame is embedded in a parent frame.
+  base::Optional<base::UnguessableToken> embedding_token_;
+
   // Tracks the scrolling and margin properties for this frame.  These
   // properties affect the child renderer but are stored on its parent's
   // frame element.  When this frame's parent dynamically updates these
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 374aebb..234f6b90 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -194,11 +194,20 @@
   bool previous_document_was_activated =
       frame_tree->root()->HasStickyUserActivation();
 
-  // Navigating to a new location means a new, fresh set of http headers and/or
-  // <meta> elements - we need to reset CSP and Feature Policy.
   if (!is_same_document_navigation) {
+    // Navigating to a new location means a new, fresh set of http headers
+    // and/or <meta> elements - we need to reset CSP and Feature Policy.
     render_frame_host->ResetContentSecurityPolicies();
     frame_tree_node->ResetForNavigation();
+
+    // Save the new page's embedding token and propagate to any frames that
+    // embed it.
+    // - A token will have a value if it is a cross-origin frame.
+    // - An empty token will occur for;
+    //   - main frames
+    //   - a previously out-of-process frame that navigated to be same-process
+    //     as its parent
+    frame_tree_node->SetEmbeddingToken(params.embedding_token);
   }
 
   // Update the site of the SiteInstance if it doesn't have one yet, unless
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 563e07a..ef733201 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -7066,6 +7066,27 @@
     return false;
   }
 
+  // A cross-document navigation requires an embedding token for all embedded
+  // frames (a child frame to a remote parent). Embedding tokens should not
+  // exist for other cases.
+  if (!is_same_document_navigation) {
+    if (frame_tree_node()->IsMainFrame() &&
+        params->embedding_token.has_value()) {
+      bad_message::ReceivedBadMessage(
+          process, bad_message::RFH_UNEXPECTED_EMBEDDING_TOKEN);
+      return false;
+    } else if (IsCrossProcessSubframe() &&
+               !params->embedding_token.has_value()) {
+      bad_message::ReceivedBadMessage(process,
+                                      bad_message::RFH_MISSING_EMBEDDING_TOKEN);
+      return false;
+    }
+  } else if (params->embedding_token.has_value()) {
+    bad_message::ReceivedBadMessage(
+        process, bad_message::RFH_UNEXPECTED_EMBEDDING_TOKEN);
+    return false;
+  }
+
   return true;
 }
 
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 5042925..0ce2a4fe 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1380,6 +1380,14 @@
   CreateNewFrameForInnerDelegateAttachIfNecessary();
 }
 
+void RenderFrameHostManager::SetEmbeddingToken(
+    const base::UnguessableToken& embedding_token) {
+  RenderFrameProxyHost* proxy_to_parent = GetProxyToParent();
+  DCHECK(proxy_to_parent);
+  proxy_to_parent->GetAssociatedRemoteFrame()->SetEmbeddingToken(
+      embedding_token);
+}
+
 RenderFrameHostManager::SiteInstanceDescriptor
 RenderFrameHostManager::DetermineSiteInstanceForURL(
     const GURL& dest_url,
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index 5debc67..0784353 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -504,6 +504,9 @@
     attach_to_inner_delegate_state_ = AttachToInnerDelegateState::ATTACHED;
   }
 
+  // Sets an embedding token to track the relationship of a frame to its parent.
+  void SetEmbeddingToken(const base::UnguessableToken& embedding_token);
+
  private:
   friend class NavigatorTest;
   friend class RenderFrameHostManagerTest;
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index 82c75d1..d76c90f 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -17,6 +17,7 @@
 #include "content/shell/common/shell_switches.h"
 #include "media/audio/audio_features.h"
 #include "media/base/media_switches.h"
+#include "media/base/supported_types.h"
 #include "media/base/test_data_util.h"
 #include "media/media_buildflags.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -344,6 +345,13 @@
   EXPECT_FALSE(shell()->web_contents()->IsCrashed());
 }
 
+IN_PROC_BROWSER_TEST_P(MediaTest, AudioOnly_XHE_AAC_MP4) {
+  if (media::IsSupportedAudioType(
+          {media::kCodecAAC, media::AudioCodecProfile::kXHE_AAC})) {
+    PlayAudio("noise-xhe-aac.mp4", GetParam());
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(File, MediaTest, ::testing::Values(false));
 INSTANTIATE_TEST_SUITE_P(Http, MediaTest, ::testing::Values(true));
 
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
index 4422f580..733ac96 100644
--- a/content/browser/media/media_canplaytype_browsertest.cc
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -1428,6 +1428,19 @@
   EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.4.5\"'"));
   EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.400.5\"'"));
   EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.040.5\"'"));
+
+// xHE-AAC support is currently only available on P+.
+#if defined(OS_ANDROID)
+  const char* kXHE_AACProbably =
+      base::android::BuildInfo::GetInstance()->sdk_int() >=
+              base::android::SDK_VERSION_P
+          ? kProbably
+          : kNot;
+#else
+  const char* kXHE_AACProbably = kNot;
+#endif
+  EXPECT_EQ(kXHE_AACProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.42\"'"));
+  EXPECT_EQ(kXHE_AACProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.42\"'"));
 }
 
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
diff --git a/content/browser/media/media_source_browsertest.cc b/content/browser/media/media_source_browsertest.cc
index 9faa3f4..1c523d81 100644
--- a/content/browser/media/media_source_browsertest.cc
+++ b/content/browser/media/media_source_browsertest.cc
@@ -6,6 +6,7 @@
 #include "build/build_config.h"
 #include "content/browser/media/media_browsertest.h"
 #include "media/base/media_switches.h"
+#include "media/base/supported_types.h"
 #include "media/base/test_data_util.h"
 #include "media/media_buildflags.h"
 
@@ -107,6 +108,13 @@
   TestSimplePlayback("bear-flac_frag.mp4", media::kEnded);
 }
 
+IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioOnly_XHE_AAC_MP4) {
+  if (media::IsSupportedAudioType(
+          {media::kCodecAAC, media::AudioCodecProfile::kXHE_AAC})) {
+    TestSimplePlayback("noise-xhe-aac.mp4", media::kEnded);
+  }
+}
+
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
 IN_PROC_BROWSER_TEST_F(MediaSourceTest, Playback_AudioVideo_Mp2t) {
diff --git a/content/browser/notifications/blink_notification_service_impl_unittest.cc b/content/browser/notifications/blink_notification_service_impl_unittest.cc
index 951dc88..619ad99 100644
--- a/content/browser/notifications/blink_notification_service_impl_unittest.cc
+++ b/content/browser/notifications/blink_notification_service_impl_unittest.cc
@@ -189,7 +189,7 @@
 
     {
       base::RunLoop run_loop;
-      embedded_worker_helper_->context()->storage()->FindRegistrationForId(
+      embedded_worker_helper_->context()->registry()->FindRegistrationForId(
           service_worker_registration_id, GURL(kTestOrigin),
           base::BindOnce(&BlinkNotificationServiceImplTest::
                              DidFindServiceWorkerRegistration,
diff --git a/content/browser/notifications/notification_storage_unittest.cc b/content/browser/notifications/notification_storage_unittest.cc
index 2bdf7bd..9d6eda7 100644
--- a/content/browser/notifications/notification_storage_unittest.cc
+++ b/content/browser/notifications/notification_storage_unittest.cc
@@ -84,7 +84,7 @@
 
     {
       base::RunLoop run_loop;
-      helper_->context()->storage()->FindRegistrationForId(
+      helper_->context()->registry()->FindRegistrationForId(
           service_worker_registration_id_, origin_,
           base::BindOnce(
               &NotificationStorageTest::DidFindServiceWorkerRegistration,
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 9fb44d0..ad9f828 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1934,6 +1934,8 @@
     const url::Origin& origin,
     mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // Note, the base::Unretained() is safe because the target object has an IO
+  // thread deleter and the callback is also targeting the IO thread.
   // TODO(https://crbug.com/873661): Pass origin to FileSystemManager.
   base::PostTask(
       FROM_HERE, {BrowserThread::IO},
@@ -2216,6 +2218,10 @@
         base::BindRepeating(&RenderProcessHostImpl::BindPushMessagingManager,
                             weak_factory_.GetWeakPtr()));
   } else {
+    // Note, the base::Unretained() is safe because the target object has an IO
+    // thread deleter and the callback is also targeting the IO thread.  When
+    // the RPHI is destroyed it also triggers the destruction of the registry
+    // on the IO thread.
     registry->AddInterface(
         base::BindRepeating(&PushMessagingManager::AddPushMessagingReceiver,
                             base::Unretained(push_messaging_manager_.get())));
@@ -2227,6 +2233,12 @@
   // This interface is still exposed by the RenderProcessHost's registry so
   // that it can be accessed by PepperFileSystemHost. Blink accesses this
   // interface through RenderFrameHost/RendererInterfaceBinders.
+  //
+  // Note, the base::Unretained() is safe because the target object has an IO
+  // thread deleter and the callback is also targeting the IO thread.  When
+  // the RPHI is destroyed it also triggers the destruction of the registry
+  // on the IO thread.
+  //
   // TODO(https://crbug.com/873661): Make PepperFileSystemHost access this with
   // the RenderFrameHost's registry, and remove this registration.
   registry->AddInterface(
@@ -2255,9 +2267,14 @@
       base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
                                        base::TaskPriority::USER_VISIBLE}));
 
+  // Note, the base::Unretained() is safe because the target object has an IO
+  // thread deleter and the callback is also targeting the IO thread.  When
+  // the RPHI is destroyed it also triggers the destruction of the registry
+  // on the IO thread.
+  media_stream_track_metrics_host_.reset(new MediaStreamTrackMetricsHost());
   registry->AddInterface(base::BindRepeating(
-      &RenderProcessHostImpl::CreateMediaStreamTrackMetricsHost,
-      base::Unretained(this)));
+      &MediaStreamTrackMetricsHost::BindReceiver,
+      base::Unretained(media_stream_track_metrics_host_.get())));
 
   AddUIThreadInterface(
       registry.get(),
@@ -2303,6 +2320,9 @@
       std::make_unique<blink::AssociatedInterfaceRegistry>();
   blink::AssociatedInterfaceRegistry* associated_registry =
       associated_interfaces_.get();
+
+  // This base::Unretained() usage is safe since the associated_registry is
+  // owned by this RPHI.
   associated_registry->AddInterface(base::BindRepeating(
       &RenderProcessHostImpl::BindRouteProvider, base::Unretained(this)));
   associated_registry->AddInterface(base::BindRepeating(
@@ -4800,14 +4820,6 @@
   return nullptr;
 }
 
-void RenderProcessHostImpl::CreateMediaStreamTrackMetricsHost(
-    mojo::PendingReceiver<blink::mojom::MediaStreamTrackMetricsHost> receiver) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!media_stream_track_metrics_host_)
-    media_stream_track_metrics_host_.reset(new MediaStreamTrackMetricsHost());
-  media_stream_track_metrics_host_->BindReceiver(std::move(receiver));
-}
-
 void RenderProcessHostImpl::CreateAgentMetricsCollectorHost(
     mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index d81f6915..5f4d1344 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -830,10 +830,6 @@
   static RenderProcessHost* FindReusableProcessHostForSiteInstance(
       SiteInstanceImpl* site_instance);
 
-  void CreateMediaStreamTrackMetricsHost(
-      mojo::PendingReceiver<blink::mojom::MediaStreamTrackMetricsHost>
-          receiver);
-
   void CreateAgentMetricsCollectorHost(
       mojo::PendingReceiver<blink::mojom::AgentMetricsCollectorHost> receiver);
 
@@ -906,6 +902,18 @@
   // if the request isn't handled on the IO thread.
   void OnBindHostReceiver(mojo::GenericPendingReceiver receiver);
 
+  // IOThreadHostImpl owns some IO-thread state associated with this
+  // RenderProcessHostImpl. This is mainly to allow various IPCs from the
+  // renderer to be handled on the IO thread without a hop to the UI thread.
+  //
+  // Declare this early to ensure it triggers the destruction of the
+  // IOThreadHostImpl prior to other objects with an IO thread deleter.  This
+  // is necessary to ensure those objects stop receiving mojo messages before
+  // their destruction.
+  class IOThreadHostImpl;
+  friend class IOThreadHostImpl;
+  base::Optional<base::SequenceBound<IOThreadHostImpl>> io_thread_host_impl_;
+
   mojo::OutgoingInvitation mojo_invitation_;
 
   size_t keep_alive_ref_count_;
@@ -1119,13 +1127,6 @@
 
   IpcSendWatcher ipc_send_watcher_for_testing_;
 
-  // IOThreadHostImpl owns some IO-thread state associated with this
-  // RenderProcessHostImpl. This is mainly to allow various IPCs from the
-  // renderer to be handled on the IO thread without a hop to the UI thread.
-  class IOThreadHostImpl;
-  friend class IOThreadHostImpl;
-  base::Optional<base::SequenceBound<IOThreadHostImpl>> io_thread_host_impl_;
-
   // Keeps this process registered with the tracing subsystem.
   std::unique_ptr<TracingServiceController::ClientRegistration>
       tracing_registration_;
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc
index e17abe7..019aaa0 100644
--- a/content/browser/service_worker/service_worker_registry.cc
+++ b/content/browser/service_worker/service_worker_registry.cc
@@ -88,14 +88,21 @@
     int64_t registration_id,
     const GURL& origin,
     FindRegistrationCallback callback) {
-  storage()->FindRegistrationForId(registration_id, origin,
-                                   std::move(callback));
+  storage()->FindRegistrationForId(
+      registration_id, origin,
+      base::BindOnce(&ServiceWorkerRegistry::DidFindRegistrationForId,
+                     weak_factory_.GetWeakPtr(), registration_id,
+                     std::move(callback)));
 }
 
 void ServiceWorkerRegistry::FindRegistrationForIdOnly(
     int64_t registration_id,
     FindRegistrationCallback callback) {
-  storage()->FindRegistrationForIdOnly(registration_id, std::move(callback));
+  storage()->FindRegistrationForIdOnly(
+      registration_id,
+      base::BindOnce(&ServiceWorkerRegistry::DidFindRegistrationForId,
+                     weak_factory_.GetWeakPtr(), registration_id,
+                     std::move(callback)));
 }
 
 ServiceWorkerRegistration* ServiceWorkerRegistry::GetUninstallingRegistration(
@@ -280,4 +287,23 @@
   CompleteFindNow(std::move(registration), status, std::move(callback));
 }
 
+void ServiceWorkerRegistry::DidFindRegistrationForId(
+    int64_t registration_id,
+    FindRegistrationCallback callback,
+    blink::ServiceWorkerStatusCode status,
+    scoped_refptr<ServiceWorkerRegistration> registration) {
+  if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
+    // Look for something currently being installed.
+    scoped_refptr<ServiceWorkerRegistration> installing_registration =
+        FindInstallingRegistrationForId(registration_id);
+    if (installing_registration) {
+      CompleteFindNow(std::move(installing_registration),
+                      blink::ServiceWorkerStatusCode::kOk, std::move(callback));
+      return;
+    }
+  }
+
+  CompleteFindNow(std::move(registration), status, std::move(callback));
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h
index 682955bd..100248e 100644
--- a/content/browser/service_worker/service_worker_registry.h
+++ b/content/browser/service_worker/service_worker_registry.h
@@ -83,16 +83,6 @@
       ServiceWorkerRegistration* registration,
       ServiceWorkerRegistration::Status new_status);
 
-  // TODO(crbug.com/1039200): Make these methods private once methods/fields
-  // related to ServiceWorkerRegistration in ServiceWorkerStorage are moved
-  // into this class.
-  ServiceWorkerRegistration* FindInstallingRegistrationForClientUrl(
-      const GURL& client_url);
-  ServiceWorkerRegistration* FindInstallingRegistrationForScope(
-      const GURL& scope);
-  ServiceWorkerRegistration* FindInstallingRegistrationForId(
-      int64_t registration_id);
-
   // TODO(crbug.com/1039200): Make this private once methods/fields related to
   // ServiceWorkerRegistration in ServiceWorkerStorage are moved into this
   // class.
@@ -113,6 +103,13 @@
   }
 
  private:
+  ServiceWorkerRegistration* FindInstallingRegistrationForClientUrl(
+      const GURL& client_url);
+  ServiceWorkerRegistration* FindInstallingRegistrationForScope(
+      const GURL& scope);
+  ServiceWorkerRegistration* FindInstallingRegistrationForId(
+      int64_t registration_id);
+
   void DidFindRegistrationForClientUrl(
       const GURL& client_url,
       int64_t trace_event_id,
@@ -124,6 +121,11 @@
       FindRegistrationCallback callback,
       blink::ServiceWorkerStatusCode status,
       scoped_refptr<ServiceWorkerRegistration> registration);
+  void DidFindRegistrationForId(
+      int64_t registration_id,
+      FindRegistrationCallback callback,
+      blink::ServiceWorkerStatusCode status,
+      scoped_refptr<ServiceWorkerRegistration> registration);
 
   // The ServiceWorkerContextCore object must outlive this.
   ServiceWorkerContextCore* const context_;
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index f95530b27..7f20a69 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -218,9 +218,8 @@
     FindRegistrationCallback callback) {
   switch (state_) {
     case STORAGE_STATE_DISABLED:
-      CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
-                      blink::ServiceWorkerStatusCode::kErrorAbort,
-                      std::move(callback));
+      std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+                              nullptr);
       return;
     case STORAGE_STATE_INITIALIZING:  // Fall-through.
     case STORAGE_STATE_UNINITIALIZED:
@@ -233,16 +232,10 @@
       break;
   }
 
-  // See if there are any stored registrations for the origin.
+  // Bypass database lookup when there is no stored registration.
   if (!base::Contains(registered_origins_, origin)) {
-    // Look for something currently being installed.
-    scoped_refptr<ServiceWorkerRegistration> installing_registration =
-        registry_->FindInstallingRegistrationForId(registration_id);
-    CompleteFindNow(installing_registration,
-                    installing_registration
-                        ? blink::ServiceWorkerStatusCode::kOk
-                        : blink::ServiceWorkerStatusCode::kErrorNotFound,
-                    std::move(callback));
+    std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorNotFound,
+                            nullptr);
     return;
   }
 
@@ -259,7 +252,7 @@
       base::BindOnce(
           &FindForIdInDB, database_.get(), base::ThreadTaskRunnerHandle::Get(),
           registration_id, origin,
-          base::BindOnce(&ServiceWorkerStorage::DidFindRegistrationForId,
+          base::BindOnce(&ServiceWorkerStorage::DidFindRegistration,
                          weak_factory_.GetWeakPtr(), std::move(callback))));
 }
 
@@ -268,8 +261,8 @@
     FindRegistrationCallback callback) {
   switch (state_) {
     case STORAGE_STATE_DISABLED:
-      CompleteFindNow(nullptr, blink::ServiceWorkerStatusCode::kErrorAbort,
-                      std::move(callback));
+      std::move(callback).Run(blink::ServiceWorkerStatusCode::kErrorAbort,
+                              nullptr);
       return;
     case STORAGE_STATE_INITIALIZING:  // Fall-through.
     case STORAGE_STATE_UNINITIALIZED:
@@ -298,7 +291,7 @@
       base::BindOnce(
           &FindForIdOnlyInDB, database_.get(),
           base::ThreadTaskRunnerHandle::Get(), registration_id,
-          base::BindOnce(&ServiceWorkerStorage::DidFindRegistrationForId,
+          base::BindOnce(&ServiceWorkerStorage::DidFindRegistration,
                          weak_factory_.GetWeakPtr(), std::move(callback))));
 }
 
@@ -1189,28 +1182,6 @@
                           scoped_refptr<ServiceWorkerRegistration>());
 }
 
-void ServiceWorkerStorage::DidFindRegistrationForId(
-    FindRegistrationCallback callback,
-    const ServiceWorkerDatabase::RegistrationData& data,
-    const ResourceList& resources,
-    ServiceWorkerDatabase::Status status) {
-  if (status == ServiceWorkerDatabase::STATUS_OK) {
-    ReturnFoundRegistration(std::move(callback), data, resources);
-    return;
-  }
-
-  if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
-    // TODO(nhiroki): Find a registration in |installing_registrations_|.
-    std::move(callback).Run(DatabaseStatusToStatusCode(status),
-                            scoped_refptr<ServiceWorkerRegistration>());
-    return;
-  }
-
-  ScheduleDeleteAndStartOver();
-  std::move(callback).Run(DatabaseStatusToStatusCode(status),
-                          scoped_refptr<ServiceWorkerRegistration>());
-}
-
 void ServiceWorkerStorage::ReturnFoundRegistration(
     FindRegistrationCallback callback,
     const ServiceWorkerDatabase::RegistrationData& data,
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 21f214e5..3ef57d7 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -389,11 +389,6 @@
                            const ServiceWorkerDatabase::RegistrationData& data,
                            const ResourceList& resources,
                            ServiceWorkerDatabase::Status status);
-  void DidFindRegistrationForId(
-      FindRegistrationCallback callback,
-      const ServiceWorkerDatabase::RegistrationData& data,
-      const ResourceList& resources,
-      ServiceWorkerDatabase::Status status);
   void DidGetRegistrationsForOrigin(GetRegistrationsCallback callback,
                                     RegistrationList* registration_data_list,
                                     std::vector<ResourceList>* resources_list,
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 45f7a9b0..a7e253d7 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -1259,6 +1259,8 @@
   appcache_service_ = base::MakeRefCounted<ChromeAppCacheService>(
       quota_manager_proxy.get(), weak_factory_.GetWeakPtr());
 
+  dedicated_worker_service_ = std::make_unique<DedicatedWorkerServiceImpl>();
+
   shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
       this, service_worker_context_, appcache_service_);
 
@@ -1502,6 +1504,11 @@
   return service_worker_context_.get();
 }
 
+DedicatedWorkerServiceImpl* StoragePartitionImpl::GetDedicatedWorkerService() {
+  DCHECK(initialized_);
+  return dedicated_worker_service_.get();
+}
+
 SharedWorkerServiceImpl* StoragePartitionImpl::GetSharedWorkerService() {
   DCHECK(initialized_);
   return shared_worker_service_.get();
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index f55df1d1..86ff25e 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -34,6 +34,7 @@
 #include "content/browser/push_messaging/push_messaging_context.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/url_loader_factory_getter.h"
+#include "content/browser/worker_host/dedicated_worker_service_impl.h"
 #include "content/browser/worker_host/shared_worker_service_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/storage_partition.h"
@@ -136,6 +137,7 @@
   NativeFileSystemEntryFactory* GetNativeFileSystemEntryFactory() override;
   CacheStorageContextImpl* GetCacheStorageContext() override;
   ServiceWorkerContextWrapper* GetServiceWorkerContext() override;
+  DedicatedWorkerServiceImpl* GetDedicatedWorkerService() override;
   SharedWorkerServiceImpl* GetSharedWorkerService() override;
   GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() override;
   DevToolsBackgroundServicesContextImpl* GetDevToolsBackgroundServicesContext()
@@ -438,6 +440,7 @@
   scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
   scoped_refptr<CacheStorageContextImpl> cache_storage_context_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+  std::unique_ptr<DedicatedWorkerServiceImpl> dedicated_worker_service_;
   std::unique_ptr<SharedWorkerServiceImpl> shared_worker_service_;
   scoped_refptr<PushMessagingContext> push_messaging_context_;
   scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc
index a78ba75..200ff81 100644
--- a/content/browser/worker_host/dedicated_worker_host.cc
+++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -20,6 +20,7 @@
 #include "content/browser/url_loader_factory_params_helper.h"
 #include "content/browser/websockets/websocket_connector_impl.h"
 #include "content/browser/webtransport/quic_transport_connector_impl.h"
+#include "content/browser/worker_host/dedicated_worker_service_impl.h"
 #include "content/browser/worker_host/worker_script_fetch_initiator.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
@@ -39,12 +40,16 @@
 namespace content {
 
 DedicatedWorkerHost::DedicatedWorkerHost(
+    DedicatedWorkerServiceImpl* service,
+    DedicatedWorkerId id,
     RenderProcessHost* worker_process_host,
     GlobalFrameRoutingId creator_render_frame_host_id,
     GlobalFrameRoutingId ancestor_render_frame_host_id,
     const url::Origin& origin,
     mojo::PendingReceiver<blink::mojom::DedicatedWorkerHost> host)
-    : worker_process_host_(worker_process_host),
+    : service_(service),
+      id_(id),
+      worker_process_host_(worker_process_host),
       scoped_process_host_observer_(this),
       creator_render_frame_host_id_(creator_render_frame_host_id),
       ancestor_render_frame_host_id_(ancestor_render_frame_host_id),
@@ -54,9 +59,14 @@
   DCHECK(worker_process_host_);
 
   scoped_process_host_observer_.Add(worker_process_host_);
+
+  service_->NotifyWorkerStarted(id_, worker_process_host_->GetID(),
+                                ancestor_render_frame_host_id_);
 }
 
-DedicatedWorkerHost::~DedicatedWorkerHost() = default;
+DedicatedWorkerHost::~DedicatedWorkerHost() {
+  service_->NotifyWorkerTerminating(id_, ancestor_render_frame_host_id_);
+}
 
 void DedicatedWorkerHost::BindBrowserInterfaceBrokerReceiver(
     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
@@ -518,14 +528,22 @@
       return;
     }
 
+    auto* storage_partition = static_cast<StoragePartitionImpl*>(
+        worker_process_host->GetStoragePartition());
+
+    // Get the dedicated worker service.
+    DedicatedWorkerServiceImpl* service =
+        storage_partition->GetDedicatedWorkerService();
+
     // TODO(crbug.com/729021): Once |parent_context_origin_| no longer races
     // with the request for |DedicatedWorkerHostFactory|, enforce that
     // the worker's origin either matches the origin of the creating context
     // (Document or DedicatedWorkerGlobalScope), or is unique.
     // Deletes itself on Mojo disconnection.
     auto* host = new DedicatedWorkerHost(
-        worker_process_host, creator_render_frame_host_id_,
-        ancestor_render_frame_host_id_, origin, std::move(host_receiver));
+        service, service->GenerateNextDedicatedWorkerId(), worker_process_host,
+        creator_render_frame_host_id_, ancestor_render_frame_host_id_, origin,
+        std::move(host_receiver));
     host->BindBrowserInterfaceBrokerReceiver(std::move(broker_receiver));
   }
 
@@ -557,15 +575,22 @@
       return;
     }
 
+    auto* storage_partition = static_cast<StoragePartitionImpl*>(
+        worker_process_host->GetStoragePartition());
+
+    // Get the dedicated worker service.
+    DedicatedWorkerServiceImpl* service =
+        storage_partition->GetDedicatedWorkerService();
+
     // TODO(crbug.com/729021): Once |parent_context_origin_| no longer races
     // with the request for |DedicatedWorkerHostFactory|, enforce that
     // the worker's origin either matches the origin of the creating context
     // (Document or DedicatedWorkerGlobalScope), or is unique.
     // Deletes itself on Mojo disconnection.
     auto* host = new DedicatedWorkerHost(
-        worker_process_host, creator_render_frame_host_id_,
-        ancestor_render_frame_host_id_, request_initiator_origin,
-        std::move(host_receiver));
+        service, service->GenerateNextDedicatedWorkerId(), worker_process_host,
+        creator_render_frame_host_id_, ancestor_render_frame_host_id_,
+        request_initiator_origin, std::move(host_receiver));
     mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker;
     host->BindBrowserInterfaceBrokerReceiver(
         broker.InitWithNewPipeAndPassReceiver());
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h
index 7d85c36..2f03e64b 100644
--- a/content/browser/worker_host/dedicated_worker_host.h
+++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -8,6 +8,7 @@
 #include "base/scoped_observer.h"
 #include "build/build_config.h"
 #include "content/browser/browser_interface_broker_impl.h"
+#include "content/public/browser/dedicated_worker_service.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
@@ -37,13 +38,14 @@
 
 namespace content {
 
+class DedicatedWorkerServiceImpl;
 class ServiceWorkerMainResourceHandle;
 class ServiceWorkerObjectHost;
 class StoragePartitionImpl;
 
 // Creates a host factory for a dedicated worker. This must be called on the UI
 // thread.
-void CreateDedicatedWorkerHostFactory(
+CONTENT_EXPORT void CreateDedicatedWorkerHostFactory(
     GlobalFrameRoutingId creator_render_frame_host_id,
     GlobalFrameRoutingId ancestor_render_frame_host_id,
     const url::Origin& origin,
@@ -56,6 +58,8 @@
                                   public RenderProcessHostObserver {
  public:
   DedicatedWorkerHost(
+      DedicatedWorkerServiceImpl* service,
+      DedicatedWorkerId id,
       RenderProcessHost* worker_process_host,
       GlobalFrameRoutingId creator_render_frame_host_id,
       GlobalFrameRoutingId ancestor_render_frame_host_id,
@@ -149,6 +153,11 @@
 
   void OnMojoDisconnect();
 
+  DedicatedWorkerServiceImpl* const service_;
+
+  // An internal ID that is unique within a storage partition.
+  const DedicatedWorkerId id_;
+
   // The RenderProcessHost that hosts this worker.
   RenderProcessHost* const worker_process_host_;
 
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.cc b/content/browser/worker_host/dedicated_worker_service_impl.cc
new file mode 100644
index 0000000..ecaa9f1
--- /dev/null
+++ b/content/browser/worker_host/dedicated_worker_service_impl.cc
@@ -0,0 +1,44 @@
+// 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 "content/browser/worker_host/dedicated_worker_service_impl.h"
+
+namespace content {
+
+DedicatedWorkerServiceImpl::DedicatedWorkerServiceImpl() = default;
+
+DedicatedWorkerServiceImpl::~DedicatedWorkerServiceImpl() = default;
+
+void DedicatedWorkerServiceImpl::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void DedicatedWorkerServiceImpl::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+DedicatedWorkerId DedicatedWorkerServiceImpl::GenerateNextDedicatedWorkerId() {
+  return dedicated_worker_id_generator_.GenerateNextId();
+}
+
+void DedicatedWorkerServiceImpl::NotifyWorkerStarted(
+    DedicatedWorkerId dedicated_worker_id,
+    int worker_process_id,
+    GlobalFrameRoutingId ancestor_render_frame_host_id) {
+  for (Observer& observer : observers_) {
+    observer.OnWorkerStarted(dedicated_worker_id, worker_process_id,
+                             ancestor_render_frame_host_id);
+  }
+}
+
+void DedicatedWorkerServiceImpl::NotifyWorkerTerminating(
+    DedicatedWorkerId dedicated_worker_id,
+    GlobalFrameRoutingId ancestor_render_frame_host_id) {
+  for (Observer& observer : observers_) {
+    observer.OnBeforeWorkerTerminated(dedicated_worker_id,
+                                      ancestor_render_frame_host_id);
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/worker_host/dedicated_worker_service_impl.h b/content/browser/worker_host/dedicated_worker_service_impl.h
new file mode 100644
index 0000000..987800c5
--- /dev/null
+++ b/content/browser/worker_host/dedicated_worker_service_impl.h
@@ -0,0 +1,44 @@
+// 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 CONTENT_BROWSER_WORKER_HOST_DEDICATED_WORKER_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_WORKER_HOST_DEDICATED_WORKER_SERVICE_IMPL_H_
+
+#include "base/observer_list.h"
+#include "content/public/browser/dedicated_worker_service.h"
+
+namespace content {
+
+class CONTENT_EXPORT DedicatedWorkerServiceImpl
+    : public DedicatedWorkerService {
+ public:
+  DedicatedWorkerServiceImpl();
+  ~DedicatedWorkerServiceImpl() override;
+
+  DedicatedWorkerServiceImpl(const DedicatedWorkerServiceImpl& other) = delete;
+
+  // DedicatedWorkerService:
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
+
+  DedicatedWorkerId GenerateNextDedicatedWorkerId();
+
+  void NotifyWorkerStarted(DedicatedWorkerId dedicated_worker_id,
+                           int worker_process_id,
+                           GlobalFrameRoutingId ancestor_render_frame_host_id);
+
+  void NotifyWorkerTerminating(
+      DedicatedWorkerId dedicated_worker_id,
+      GlobalFrameRoutingId ancestor_render_frame_host_id);
+
+ private:
+  // Generates IDs for new dedicated workers.
+  DedicatedWorkerId::Generator dedicated_worker_id_generator_;
+
+  base::ObserverList<Observer> observers_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WORKER_HOST_DEDICATED_WORKER_SERVICE_IMPL_H_
diff --git a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
new file mode 100644
index 0000000..136ed0d
--- /dev/null
+++ b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
@@ -0,0 +1,213 @@
+// 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 "content/browser/worker_host/dedicated_worker_service_impl.h"
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "base/scoped_observer.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/site_instance_impl.h"
+#include "content/browser/worker_host/dedicated_worker_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/worker/dedicated_worker_host_factory.mojom.h"
+#include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h"
+
+namespace content {
+
+// Mocks a dedicated worker living in a renderer process.
+class MockDedicatedWorker
+    : public blink::mojom::DedicatedWorkerHostFactoryClient {
+ public:
+  explicit MockDedicatedWorker(GlobalFrameRoutingId render_frame_host_id) {
+    CreateDedicatedWorkerHostFactory(render_frame_host_id, render_frame_host_id,
+                                     url::Origin(),
+                                     factory_.BindNewPipeAndPassReceiver());
+
+    if (base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)) {
+      factory_->CreateWorkerHostAndStartScriptLoad(
+          GURL(), url::Origin(), network::mojom::CredentialsMode::kSameOrigin,
+          blink::mojom::FetchClientSettingsObject::New(),
+          mojo::PendingRemote<blink::mojom::BlobURLToken>(),
+          receiver_.BindNewPipeAndPassRemote(),
+          remote_host_.BindNewPipeAndPassReceiver());
+    } else {
+      factory_->CreateWorkerHost(
+          url::Origin(), browser_interface_broker_.BindNewPipeAndPassReceiver(),
+          remote_host_.BindNewPipeAndPassReceiver());
+    }
+  }
+
+  ~MockDedicatedWorker() override = default;
+
+  // Non-copyable.
+  MockDedicatedWorker(const MockDedicatedWorker& other) = delete;
+
+  // blink::mojom::DedicatedWorkerHostFactoryClient:
+  void OnWorkerHostCreated(
+      mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
+          browser_interface_broker) override {
+    browser_interface_broker_.Bind(std::move(browser_interface_broker));
+  }
+
+  void OnScriptLoadStarted(
+      blink::mojom::ServiceWorkerProviderInfoForClientPtr
+          service_worker_provider_info,
+      blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params,
+      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
+          pending_subresource_loader_factory_bundle,
+      mojo::PendingReceiver<blink::mojom::SubresourceLoaderUpdater>
+          subresource_loader_updater,
+      blink::mojom::ControllerServiceWorkerInfoPtr controller_info) override {}
+  void OnScriptLoadStartFailed() override {}
+
+ private:
+  // Only used with the kPlzDedicatedWorker feature.
+  mojo::Receiver<blink::mojom::DedicatedWorkerHostFactoryClient> receiver_{
+      this};
+
+  // Allows creating the dedicated worker host.
+  mojo::Remote<blink::mojom::DedicatedWorkerHostFactory> factory_;
+
+  mojo::Remote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker_;
+  mojo::Remote<blink::mojom::DedicatedWorkerHost> remote_host_;
+};
+
+class DedicatedWorkerServiceImplTest : public RenderViewHostImplTestHarness,
+                                       public testing::WithParamInterface<bool>,
+                                       public DedicatedWorkerService::Observer {
+ public:
+  struct DedicatedWorkerInfo {
+    int worker_process_id;
+    GlobalFrameRoutingId ancestor_render_frame_host_id;
+  };
+
+  DedicatedWorkerServiceImplTest() = default;
+  ~DedicatedWorkerServiceImplTest() override = default;
+
+  // Non-copyable.
+  DedicatedWorkerServiceImplTest(const DedicatedWorkerServiceImplTest& other) =
+      delete;
+
+  void SetUp() override {
+    scoped_feature_list_.InitWithFeatureState(
+        blink::features::kPlzDedicatedWorker, GetParam());
+    RenderViewHostImplTestHarness::SetUp();
+    browser_context_ = std::make_unique<TestBrowserContext>();
+    scoped_dedicated_worker_service_observer_.Add(
+        BrowserContext::GetDefaultStoragePartition(browser_context_.get())
+            ->GetDedicatedWorkerService());
+  }
+
+  void TearDown() override {
+    scoped_dedicated_worker_service_observer_.RemoveAll();
+    browser_context_ = nullptr;
+    RenderViewHostImplTestHarness::TearDown();
+  }
+
+  // DedicatedWorkerService::Observer:
+  void OnWorkerStarted(
+      DedicatedWorkerId dedicated_worker_id,
+      int worker_process_id,
+      GlobalFrameRoutingId ancestor_render_frame_host_id) override {
+    bool inserted =
+        dedicated_worker_infos_
+            .emplace(dedicated_worker_id,
+                     DedicatedWorkerInfo{worker_process_id,
+                                         ancestor_render_frame_host_id})
+            .second;
+    DCHECK(inserted);
+
+    DCHECK(on_worker_event_callback_);
+    std::move(on_worker_event_callback_).Run();
+  }
+  void OnBeforeWorkerTerminated(
+      DedicatedWorkerId dedicated_worker_id,
+      GlobalFrameRoutingId ancestor_render_frame_host_id) override {
+    size_t removed = dedicated_worker_infos_.erase(dedicated_worker_id);
+    DCHECK_EQ(removed, 1u);
+
+    DCHECK(on_worker_event_callback_);
+    std::move(on_worker_event_callback_).Run();
+  }
+
+  void RunUntilWorkerEvent() {
+    base::RunLoop run_loop;
+    on_worker_event_callback_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+
+  const base::flat_map<DedicatedWorkerId, DedicatedWorkerInfo>&
+  dedicated_worker_infos() {
+    return dedicated_worker_infos_;
+  }
+
+  std::unique_ptr<TestWebContents> CreateWebContents(const GURL& url) {
+    std::unique_ptr<TestWebContents> web_contents(TestWebContents::Create(
+        browser_context_.get(),
+        SiteInstanceImpl::Create(browser_context_.get())));
+    web_contents->NavigateAndCommit(url);
+    return web_contents;
+  }
+
+ private:
+  // Controls the state of the blink::features::kPlzDedicatedWorker feature.
+  base::test::ScopedFeatureList scoped_feature_list_;
+
+  std::unique_ptr<TestBrowserContext> browser_context_;
+
+  ScopedObserver<DedicatedWorkerService, DedicatedWorkerService::Observer>
+      scoped_dedicated_worker_service_observer_{this};
+
+  // Used to wait until one of OnWorkerStarted() or OnBeforeWorkerTerminated()
+  // is called.
+  base::OnceClosure on_worker_event_callback_;
+
+  base::flat_map<DedicatedWorkerId, DedicatedWorkerInfo>
+      dedicated_worker_infos_;
+};
+
+TEST_P(DedicatedWorkerServiceImplTest, ObserveWorkerCreationAndDestruction) {
+  std::unique_ptr<TestWebContents> web_contents =
+      CreateWebContents(GURL("http://example.com/"));
+  TestRenderFrameHost* render_frame_host = web_contents->GetMainFrame();
+
+  // At first, there is no live dedicated worker.
+  EXPECT_TRUE(dedicated_worker_infos().empty());
+
+  // Create the dedicated worker.
+  GlobalFrameRoutingId ancestor_render_frame_host_id =
+      render_frame_host->GetGlobalFrameRoutingId();
+  auto mock_dedicated_worker =
+      std::make_unique<MockDedicatedWorker>(ancestor_render_frame_host_id);
+  RunUntilWorkerEvent();
+
+  // The service sent a OnWorkerStarted() notification.
+  ASSERT_EQ(dedicated_worker_infos().size(), 1u);
+  const DedicatedWorkerInfo& dedicated_worker_info =
+      dedicated_worker_infos().begin()->second;
+  EXPECT_EQ(dedicated_worker_info.worker_process_id,
+            render_frame_host->GetProcess()->GetID());
+  EXPECT_EQ(dedicated_worker_info.ancestor_render_frame_host_id,
+            ancestor_render_frame_host_id);
+
+  // Delete the dedicated worker.
+  mock_dedicated_worker = nullptr;
+  RunUntilWorkerEvent();
+
+  // The service sent a OnBeforeWorkerTerminated() notification.
+  EXPECT_TRUE(dedicated_worker_infos().empty());
+}
+
+// Runs DedicatedWorkerServiceImplTest with both the enabled and disabled state
+// of the kPlzDedicatedWorker feature.
+INSTANTIATE_TEST_SUITE_P(, DedicatedWorkerServiceImplTest, testing::Bool());
+
+}  // namespace content
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index f290e5ce..4a20c01 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -425,6 +425,10 @@
   // A token that has been passed by the browser process when it asked the
   // renderer process to commit the navigation.
   IPC_STRUCT_MEMBER(base::UnguessableToken, navigation_token)
+
+  // An embedding token used to signify the relationship between the frame and
+  // its parent. This is populated for cross-document navigations in a subframe.
+  IPC_STRUCT_MEMBER(base::Optional<base::UnguessableToken>, embedding_token)
 IPC_STRUCT_END()
 
 IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params)
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index bfc0a1f..f4aa12b 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -129,6 +129,7 @@
     "cors_exempt_headers.h",
     "cors_origin_pattern_setter.cc",
     "cors_origin_pattern_setter.h",
+    "dedicated_worker_service.h",
     "desktop_capture.cc",
     "desktop_capture.h",
     "desktop_media_id.cc",
diff --git a/content/public/browser/child_process_data.h b/content/public/browser/child_process_data.h
index 5848f90..128bf04 100644
--- a/content/public/browser/child_process_data.h
+++ b/content/public/browser/child_process_data.h
@@ -8,6 +8,7 @@
 #include "base/process/process.h"
 #include "base/strings/string16.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/sandbox_type.h"
 
 namespace content {
 
@@ -29,6 +30,10 @@
   // one run of the browser.
   int id = 0;
 
+  // The content::SandboxType that this process was launched at. May be
+  // invalid prior to process launch.
+  content::SandboxType sandbox_type;
+
   const base::Process& GetProcess() const { return process_; }
   // Since base::Process is non-copyable, the caller has to provide a rvalue.
   void SetProcess(base::Process process) { process_ = std::move(process); }
diff --git a/content/public/browser/dedicated_worker_service.h b/content/public/browser/dedicated_worker_service.h
new file mode 100644
index 0000000..b3fc1dc
--- /dev/null
+++ b/content/public/browser/dedicated_worker_service.h
@@ -0,0 +1,43 @@
+// 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 CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_SERVICE_H_
+#define CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_SERVICE_H_
+
+#include "base/observer_list_types.h"
+#include "base/util/type_safety/id_type.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/global_routing_id.h"
+
+namespace content {
+
+using DedicatedWorkerId = util::IdType64<class DedicatedWorkerTag>;
+
+// An interface that allows to subscribe to the lifetime of dedicated workers.
+// The service is owned by the StoragePartition and lives on the UI thread.
+class CONTENT_EXPORT DedicatedWorkerService {
+ public:
+  class Observer : public base::CheckedObserver {
+   public:
+    // Called when a dedicated worker has started/stopped.
+    virtual void OnWorkerStarted(
+        DedicatedWorkerId dedicated_worker_id,
+        int worker_process_id,
+        GlobalFrameRoutingId ancestor_render_frame_host_id) = 0;
+    virtual void OnBeforeWorkerTerminated(
+        DedicatedWorkerId dedicated_worker_id,
+        GlobalFrameRoutingId ancestor_render_frame_host_id) = 0;
+  };
+
+  // Adds/removes an observer.
+  virtual void AddObserver(Observer* observer) = 0;
+  virtual void RemoveObserver(Observer* observer) = 0;
+
+ protected:
+  virtual ~DedicatedWorkerService() = default;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_DEDICATED_WORKER_SERVICE_H_
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index 287f764d..333b2aa 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -57,10 +57,11 @@
 class BrowserContext;
 class CacheStorageContext;
 class ContentIndexContext;
-class DOMStorageContext;
+class DedicatedWorkerService;
 class DevToolsBackgroundServicesContext;
-class IndexedDBContext;
+class DOMStorageContext;
 class GeneratedCodeCacheContext;
+class IndexedDBContext;
 class NativeFileSystemEntryFactory;
 class PlatformNotificationContext;
 class ServiceWorkerContext;
@@ -130,6 +131,7 @@
   virtual IndexedDBContext* GetIndexedDBContext() = 0;
   virtual NativeFileSystemEntryFactory* GetNativeFileSystemEntryFactory() = 0;
   virtual ServiceWorkerContext* GetServiceWorkerContext() = 0;
+  virtual DedicatedWorkerService* GetDedicatedWorkerService() = 0;
   virtual SharedWorkerService* GetSharedWorkerService() = 0;
   virtual CacheStorageContext* GetCacheStorageContext() = 0;
   virtual GeneratedCodeCacheContext* GetGeneratedCodeCacheContext() = 0;
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc
index 1782b76..ec5fed1 100644
--- a/content/public/test/test_storage_partition.cc
+++ b/content/public/test/test_storage_partition.cc
@@ -98,6 +98,10 @@
   return service_worker_context_;
 }
 
+DedicatedWorkerService* TestStoragePartition::GetDedicatedWorkerService() {
+  return dedicated_worker_service_;
+}
+
 SharedWorkerService* TestStoragePartition::GetSharedWorkerService() {
   return shared_worker_service_;
 }
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h
index e4aee126..d36a1d8 100644
--- a/content/public/test/test_storage_partition.h
+++ b/content/public/test/test_storage_partition.h
@@ -119,6 +119,8 @@
   }
   ServiceWorkerContext* GetServiceWorkerContext() override;
 
+  DedicatedWorkerService* GetDedicatedWorkerService() override;
+
   void set_shared_worker_service(SharedWorkerService* service) {
     shared_worker_service_ = service;
   }
@@ -219,6 +221,7 @@
   mojo::Remote<storage::mojom::IndexedDBControl> indexed_db_control_;
   IndexedDBContext* indexed_db_context_ = nullptr;
   ServiceWorkerContext* service_worker_context_ = nullptr;
+  DedicatedWorkerService* dedicated_worker_service_ = nullptr;
   SharedWorkerService* shared_worker_service_ = nullptr;
   CacheStorageContext* cache_storage_context_ = nullptr;
   GeneratedCodeCacheContext* generated_code_cache_context_ = nullptr;
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index 5283e36..dc24d15 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -466,6 +466,7 @@
     return nullptr;
 
   auto factory_selector = std::make_unique<media::RendererFactorySelector>();
+  bool use_default_renderer_factory = true;
 
 #if defined(OS_ANDROID)
   DCHECK(interface_broker_);
@@ -483,6 +484,7 @@
   if (use_media_player) {
     factory_selector->AddBaseFactory(FactoryType::kMediaPlayer,
                                      std::move(media_player_factory));
+    use_default_renderer_factory = false;
   } else {
     // Always give |factory_selector| a MediaPlayerRendererClient factory. WMPI
     // might fallback to it if the final redirected URL is an HLS url.
@@ -509,8 +511,8 @@
       FactoryType::kFlinging, std::move(flinging_factory), is_flinging_cb);
 #endif  // defined(OS_ANDROID)
 
-  bool use_default_renderer_factory = true;
 #if BUILDFLAG(ENABLE_MOJO_RENDERER)
+  DCHECK(!use_media_player);
   if (enable_mojo_renderer) {
     use_default_renderer_factory = false;
 #if BUILDFLAG(ENABLE_CAST_RENDERER)
diff --git a/content/renderer/media/power_status_helper_impl.cc b/content/renderer/media/power_status_helper_impl.cc
index 992a294c..606435e 100644
--- a/content/renderer/media/power_status_helper_impl.cc
+++ b/content/renderer/media/power_status_helper_impl.cc
@@ -59,7 +59,12 @@
 
 // Number of buckets we want, which includes the overflow bucket but not the
 // implicit underflow bucket.
-static constexpr int kNumUmaBuckets = kMaxUmaValue - kMinUmaValue + 1;
+// NOTE: We add two here, else we don't quite get enough buckets.  This was
+// emperically determined by checking Histogram::bucket_ranges().  It might
+// be the case that we should subtract one here and from |kMaxUmaValue|, but
+// either way, i think it works out.  We just have one unused bucket at worst,
+// which won't be renumbered even if we start using it later.
+static constexpr int kNumUmaBuckets = kMaxUmaValue - kMinUmaValue + 2;
 
 // For example, if kMinEnum == 0 and kMaxEnum == 5 (inclusive), then:
 // kMinUma = 1 (0 is implicit), kMaxUma = 6, and we'll want the implicit
@@ -91,7 +96,7 @@
     media::VideoCodecProfile profile,
     gfx::Size natural_size,
     bool is_fullscreen,
-    base::TimeDelta average_duration) {
+    base::Optional<int> average_fps) {
   if (!is_playing)
     return {};
 
@@ -119,16 +124,16 @@
   else
     return {};
 
-  // Estimate the frame rate.
-  if (average_duration >= base::TimeDelta::FromSecondsD(1. / 62) &&
-      average_duration <= base::TimeDelta::FromSecondsD(1. / 58)) {
-    bucket |= kFrameRate60;
-  } else if (average_duration >= base::TimeDelta::FromSecondsD(1. / 31) &&
-             average_duration <= base::TimeDelta::FromSecondsD(1. / 29)) {
-    bucket |= kFrameRate30;
-  } else {
+  // Estimate the frame rate.  Since 24 is popular, allow a wide range around
+  // 30fps, since it's likely the same for power.
+  if (!average_fps)
     return {};
-  }
+  else if (*average_fps == 60)
+    bucket |= kFrameRate60;
+  else if (*average_fps >= 24 && *average_fps <= 30)
+    bucket |= kFrameRate30;
+  else
+    return {};
 
   bucket |= is_fullscreen ? kFullScreenYes : kFullScreenNo;
 
@@ -164,9 +169,9 @@
   OnAnyStateChange();
 }
 
-void PowerStatusHelperImpl::SetAverageDuration(
-    base::TimeDelta average_duration) {
-  average_duration_ = average_duration;
+void PowerStatusHelperImpl::SetAverageFrameRate(
+    base::Optional<int> average_fps) {
+  average_fps_ = average_fps;
   OnAnyStateChange();
 }
 
@@ -183,9 +188,8 @@
   // If we're the power experiment, then we might have a bucket.  Else, we
   // definitely don't.
   if (experiment_state_) {
-    current_bucket_ =
-        BucketFor(is_playing_, has_video_, codec_, profile_, natural_size_,
-                  is_fullscreen_, average_duration_);
+    current_bucket_ = BucketFor(is_playing_, has_video_, codec_, profile_,
+                                natural_size_, is_fullscreen_, average_fps_);
   }
 
   // If we're changing buckets, then request power updates with a new generation
diff --git a/content/renderer/media/power_status_helper_impl.h b/content/renderer/media/power_status_helper_impl.h
index cffb0f4..09f05609 100644
--- a/content/renderer/media/power_status_helper_impl.h
+++ b/content/renderer/media/power_status_helper_impl.h
@@ -69,7 +69,7 @@
   void SetIsPlaying(bool is_playing) override;
   void SetMetadata(const media::PipelineMetadata& metadata) override;
   void SetIsFullscreen(bool is_fullscreen) override;
-  void SetAverageDuration(base::TimeDelta average_duration) override;
+  void SetAverageFrameRate(base::Optional<int> average_fps) override;
   void UpdatePowerExperimentState(bool state) override;
 
  private:
@@ -84,7 +84,7 @@
                                        media::VideoCodecProfile profile,
                                        gfx::Size natural_size,
                                        bool is_fullscreen,
-                                       base::TimeDelta average_duration);
+                                       base::Optional<int> average_fps);
 
   // Return the histogram names.  Here so that tests can find them too.
   static const char* BatteryDeltaHistogram();
@@ -114,8 +114,8 @@
       media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
   gfx::Size natural_size_;
   bool is_fullscreen_ = false;
-  // For estimating fps.
-  base::TimeDelta average_duration_;
+  // For estimating fps.  Can be unset if we don't know.
+  base::Optional<int> average_fps_;
 
   // Current UMA bucket, if any.
   base::Optional<int> current_bucket_;
diff --git a/content/renderer/media/power_status_helper_impl_unittest.cc b/content/renderer/media/power_status_helper_impl_unittest.cc
index 3314e23d..c3eedcd 100644
--- a/content/renderer/media/power_status_helper_impl_unittest.cc
+++ b/content/renderer/media/power_status_helper_impl_unittest.cc
@@ -124,7 +124,7 @@
         std::vector<uint8_t>(), /* extra_data */
         media::EncryptionScheme::kUnencrypted);
     helper_->SetMetadata(metadata);
-    helper_->SetAverageDuration(base::TimeDelta::FromSecondsD(1. / 60));
+    helper_->SetAverageFrameRate(60);
     // Use |alternate| to set fullscreen state, since that should still be
     // recordable but in a different bucket.
     helper_->SetIsFullscreen(alternate);
@@ -317,6 +317,19 @@
   base::RunLoop().RunUntilIdle();
 }
 
+TEST_F(PowerStatusHelperImplTest, UnbucketedFrameRateStopsRecording) {
+  // If we switch to an unbucketed frame rate, then it should stop recording.
+  EXPECT_CALL(monitor_, DidGetBatteryMonitor()).Times(1);
+  EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(1);
+  MakeRecordable();
+
+  // Should disconnect when we send bad params.
+  EXPECT_CALL(monitor_, DidDisconnect()).Times(1);
+  EXPECT_CALL(monitor_, DidQueryNextStatus()).Times(0);
+  helper_->SetAverageFrameRate({});
+  base::RunLoop().RunUntilIdle();
+}
+
 using PlaybackParamsTuple =
     std::tuple<bool,                        /* is_playing */
                bool,                        /* has_video */
@@ -335,10 +348,10 @@
                                 media::VideoCodecProfile profile,
                                 gfx::Size coded_size,
                                 bool is_fullscreen,
-                                base::TimeDelta average_duration) {
+                                base::Optional<int> average_fps) {
     return PowerStatusHelperImpl::BucketFor(is_playing, has_video, codec,
                                             profile, coded_size, is_fullscreen,
-                                            average_duration);
+                                            average_fps);
   }
 };
 
@@ -387,13 +400,13 @@
   }
 
   auto fps = std::get<4>(GetParam());
-  base::TimeDelta average_duration;
+  base::Optional<int> average_fps;
   if (fps == PowerStatusHelperImpl::Bits::kFrameRate30) {
-    average_duration = base::TimeDelta::FromSecondsD(1. / 30);
+    average_fps = 30;
   } else if (fps == PowerStatusHelperImpl::Bits::kFrameRate60) {
-    average_duration = base::TimeDelta::FromSecondsD(1. / 60);
+    average_fps = 60;
   } else {
-    average_duration = base::TimeDelta::FromSecondsD(1. / 90);
+    average_fps = 90;
     expect_bucket = false;
   }
 
@@ -401,7 +414,7 @@
       (std::get<5>(GetParam()) == PowerStatusHelperImpl::Bits::kFullScreenYes);
 
   auto bucket = BucketFor(is_playing, has_video, codec, profile, coded_size,
-                          is_fullscreen, average_duration);
+                          is_fullscreen, average_fps);
   if (!expect_bucket) {
     EXPECT_FALSE(bucket);
   } else {
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 2ddacc4d4..ae797fb 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4391,12 +4391,40 @@
   NavigationState* navigation_state = internal_data->navigation_state();
   DCHECK(!navigation_state->WasWithinSameDocument());
 
+  base::Optional<base::UnguessableToken> embedding_token = base::nullopt;
   if (previous_routing_id_ != MSG_ROUTING_NONE) {
     // If this is a provisional frame associated with a proxy (i.e., a frame
     // created for a remote-to-local navigation), swap it into the frame tree
     // now.
     if (!SwapIn())
       return;
+
+    // Main frames don't require an embedding token since they aren't embedded
+    // in anything. Frames local to their parent also aren't considered to be
+    // embedded.
+    if (!is_main_frame_ && frame_->Parent()->IsWebRemoteFrame()) {
+      embedding_token = base::UnguessableToken::Create();
+      GetWebFrame()->SetEmbeddingToken(embedding_token.value());
+    }
+  } else {
+    // If this is not a provisional frame then use the old embedding token. This
+    // will be base::nullopt if there was no old embedding token.
+    embedding_token = GetWebFrame()->GetEmbeddingToken();
+
+    // In the case a crashed subframe is navigating to the same site
+    // e.g. https://crbug.com/634368 then generate a new embedding token to
+    // restore a sane state.
+    //
+    // Logic behind this behavior:
+    // - Main frames don't have embedding tokens.
+    // - A remote subframe *must* have an embedding token.
+    // - If a remote subframe doesn't have an embedding token to re-use we
+    //   need to create one.
+    if (!is_main_frame_ && frame_->Parent()->IsWebRemoteFrame() &&
+        !embedding_token.has_value()) {
+      embedding_token = base::UnguessableToken::Create();
+      GetWebFrame()->SetEmbeddingToken(embedding_token.value());
+    }
   }
 
   // Navigations that change the document represent a new content source.  Keep
@@ -4495,7 +4523,8 @@
           ? mojom::DidCommitProvisionalLoadInterfaceParams::New(
                 std::move(remote_interface_provider_receiver),
                 std::move(browser_interface_broker_receiver))
-          : nullptr);
+          : nullptr,
+      embedding_token);
 
   // If we end up reusing this WebRequest (for example, due to a #ref click),
   // we don't want the transition type to persist.  Just clear it.
@@ -4750,7 +4779,8 @@
                               // was_within_same_document
                               true, transition,
                               // interface_params
-                              nullptr);
+                              nullptr,
+                              /*embedding_token=*/base::nullopt);
 
   // If we end up reusing this WebRequest (for example, due to a #ref click),
   // we don't want the transition type to persist.  Just clear it.
@@ -5338,7 +5368,8 @@
 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
 RenderFrameImpl::MakeDidCommitProvisionalLoadParams(
     blink::WebHistoryCommitType commit_type,
-    ui::PageTransition transition) {
+    ui::PageTransition transition,
+    const base::Optional<base::UnguessableToken>& embedding_token) {
   WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
   const WebURLResponse& response = document_loader->GetResponse();
 
@@ -5358,6 +5389,7 @@
       document_loader->ReplacesCurrentHistoryItem();
   params->post_id = -1;
   params->nav_entry_id = navigation_state->commit_params().nav_entry_id;
+  params->embedding_token = embedding_token;
 
   // Pass the navigation token back to the browser process, or generate a new
   // one if this navigation is committing without the browser process asking for
@@ -5612,7 +5644,8 @@
     blink::WebHistoryCommitType commit_type,
     bool was_within_same_document,
     ui::PageTransition transition,
-    mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
+    mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
+    const base::Optional<base::UnguessableToken>& embedding_token) {
   DCHECK(!(was_within_same_document && interface_params));
   UpdateStateForCommit(item, commit_type, transition);
 
@@ -5624,7 +5657,8 @@
   // call chrome::ContentSettingsManager::OnContentBlocked, those calls arrive
   // after the browser process has already been informed of the provisional
   // load committing.
-  auto params = MakeDidCommitProvisionalLoadParams(commit_type, transition);
+  auto params = MakeDidCommitProvisionalLoadParams(commit_type, transition,
+                                                   embedding_token);
   if (was_within_same_document) {
     GetFrameHost()->DidCommitSameDocumentNavigation(std::move(params));
   } else {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 45ce9bd..426f8531 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1256,8 +1256,10 @@
 
   // Build DidCommitProvisionalLoad_Params based on the frame internal state.
   std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
-  MakeDidCommitProvisionalLoadParams(blink::WebHistoryCommitType commit_type,
-                                     ui::PageTransition transition);
+  MakeDidCommitProvisionalLoadParams(
+      blink::WebHistoryCommitType commit_type,
+      ui::PageTransition transition,
+      const base::Optional<base::UnguessableToken>& embedding_token);
 
   // Updates the navigation history depending on the passed parameters.
   // This could result either in the creation of a new entry or a modification
@@ -1284,7 +1286,8 @@
       blink::WebHistoryCommitType commit_type,
       bool was_within_same_document,
       ui::PageTransition transition,
-      mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params);
+      mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
+      const base::Optional<base::UnguessableToken>& embedding_token);
 
   blink::WebComputedAXTree* GetOrCreateWebComputedAXTree() override;
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 3918c070..8f66d6f 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -641,15 +641,11 @@
     "frame_host_test_interface.mojom",
     "test_browser_associated_interfaces.mojom",
   ]
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
 
 mojom("web_ui_test_mojo_bindings") {
-  sources = [
-    "data/web_ui_test_mojo_bindings.mojom",
-  ]
+  sources = [ "data/web_ui_test_mojo_bindings.mojom" ]
 }
 
 mojom("mojo_web_test_bindings") {
@@ -667,9 +663,7 @@
 
 mojom("test_interfaces") {
   testonly = true
-  sources = [
-    "echo.mojom",
-  ]
+  sources = [ "echo.mojom" ]
 }
 
 if (is_android) {
@@ -687,13 +681,9 @@
       "../public/test/nested_message_pump_android.h",
     ]
 
-    public_deps = [
-      "//base",
-    ]
+    public_deps = [ "//base" ]
 
-    deps = [
-      "//content/public/test/android:test_support_content_jni_headers",
-    ]
+    deps = [ "//content/public/test/android:test_support_content_jni_headers" ]
   }
 }
 
@@ -876,6 +866,7 @@
     "../browser/frame_host/ancestor_throttle_browsertest.cc",
     "../browser/frame_host/back_forward_cache_metrics_browsertest.cc",
     "../browser/frame_host/blocked_scheme_navigation_browsertest.cc",
+    "../browser/frame_host/embedding_token_browsertest.cc",
     "../browser/frame_host/frame_tree_browsertest.cc",
     "../browser/frame_host/interstitial_page_impl_browsertest.cc",
     "../browser/frame_host/navigation_controller_impl_browsertest.cc",
@@ -1456,9 +1447,7 @@
 
 static_library("run_all_unittests") {
   testonly = true
-  sources = [
-    "run_all_unittests.cc",
-  ]
+  sources = [ "run_all_unittests.cc" ]
   deps = [
     ":test_support",
     "//base/test:test_support",
@@ -1813,6 +1802,7 @@
     "../browser/webrtc/webrtc_internals_unittest.cc",
     "../browser/webui/web_ui_data_source_unittest.cc",
     "../browser/webui/web_ui_message_handler_unittest.cc",
+    "../browser/worker_host/dedicated_worker_service_impl_unittest.cc",
     "../browser/worker_host/mock_shared_worker.cc",
     "../browser/worker_host/mock_shared_worker.h",
     "../browser/worker_host/shared_worker_host_unittest.cc",
@@ -2252,9 +2242,7 @@
 
 if (enable_nocompile_tests) {
   nocompile_test("content_nocompile_tests") {
-    sources = [
-      "../public/browser/browser_task_traits_unittest.nc",
-    ]
+    sources = [ "../public/browser/browser_task_traits_unittest.nc" ]
 
     deps = [
       ":run_all_unittests",
@@ -2272,9 +2260,7 @@
     check_includes = false
   }
 
-  sources = [
-    "../test/run_all_perftests.cc",
-  ]
+  sources = [ "../test/run_all_perftests.cc" ]
   deps = [
     "//base/test:test_support",
     "//cc",
@@ -2300,9 +2286,7 @@
 }
 
 group("fuzzers") {
-  deps = [
-    "//content/test/fuzzer",
-  ]
+  deps = [ "//content/test/fuzzer" ]
 }
 
 # This group defines the isolate files needed to run
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 1d2270fc..ea78514 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -555,3 +555,4 @@
 
 # ChromeOS: AMD
 crbug.com/995652 [ chromeos amd ] conformance/uniforms/out-of-bounds-uniform-array-access.html [ Skip ]
+crbug.com/1042897 [ chromeos amd ] conformance/textures/webgl_canvas/tex-2d-rgba-rgba-unsigned_byte.html [ RetryOnFailure ]
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index 959da8e4..d2b32fb 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -1327,6 +1327,15 @@
     params->document_sequence_number = ++g_unique_identifier;
   }
 
+  // Simulate embedding token creation.
+  if (!same_document && !request_->IsInMainFrame()) {
+    RenderFrameHostImpl* parent = request_->GetParentFrame();
+    if (parent && parent->GetSiteInstance() !=
+                      request_->GetRenderFrameHost()->GetSiteInstance()) {
+      params->embedding_token = base::UnguessableToken::Create();
+    }
+  }
+
   params->page_state =
       page_state_.value_or(PageState::CreateForTestingWithSequenceNumbers(
           navigation_url_, params->item_sequence_number,
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc
index dd4ae95..94ea614 100644
--- a/gpu/command_buffer/client/raster_implementation.cc
+++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1145,8 +1145,7 @@
       GetOrCreatePaintCache(), font_manager_.strike_server(),
       raster_properties_->color_space, raster_properties_->can_use_lcd_text,
       capabilities().context_supports_distance_field_text,
-      capabilities().max_texture_size,
-      capabilities().glyph_cache_max_texture_bytes);
+      capabilities().max_texture_size);
   serializer.Serialize(&list->paint_op_buffer_, &temp_raster_offsets_,
                        preamble);
   // TODO(piman): raise error if !serializer.valid()?
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h
index 8e47e309..c72dab78 100644
--- a/gpu/command_buffer/common/capabilities.h
+++ b/gpu/command_buffer/common/capabilities.h
@@ -211,7 +211,6 @@
 
   // Used by OOP raster.
   bool context_supports_distance_field_text = true;
-  uint64_t glyph_cache_max_texture_bytes = 0.f;
 
   GpuMemoryBufferFormatSet gpu_memory_buffer_formats = {
       gfx::BufferFormat::BGR_565,   gfx::BufferFormat::RGBA_4444,
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index c333429c..a6a0694 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -931,8 +931,6 @@
   if (gr_context()) {
     caps.context_supports_distance_field_text =
         gr_context()->supportsDistanceFieldText();
-    caps.glyph_cache_max_texture_bytes =
-        shared_context_state_->glyph_cache_max_texture_bytes();
   }
   return caps;
 }
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h
index 7c761b60..3f82760 100644
--- a/gpu/command_buffer/service/shared_context_state.h
+++ b/gpu/command_buffer/service/shared_context_state.h
@@ -128,9 +128,6 @@
     return &scratch_deserialization_buffer_;
   }
   size_t max_resource_cache_bytes() const { return max_resource_cache_bytes_; }
-  size_t glyph_cache_max_texture_bytes() const {
-    return glyph_cache_max_texture_bytes_;
-  }
   bool use_virtualized_gl_contexts() const {
     return use_virtualized_gl_contexts_;
   }
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
index 7ec4699..7e77a13 100644
--- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h
+++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -152,7 +152,6 @@
   IPC_STRUCT_TRAITS_MEMBER(separate_stencil_ref_mask_writemask)
   IPC_STRUCT_TRAITS_MEMBER(use_gpu_fences_for_overlay_planes)
   IPC_STRUCT_TRAITS_MEMBER(context_supports_distance_field_text)
-  IPC_STRUCT_TRAITS_MEMBER(glyph_cache_max_texture_bytes)
   IPC_STRUCT_TRAITS_MEMBER(chromium_nonblocking_readback)
   IPC_STRUCT_TRAITS_MEMBER(mesa_framebuffer_flip_y)
 
diff --git a/infra/config/buckets/ci.star b/infra/config/buckets/ci.star
index 344cf59..7cb5ebb7 100644
--- a/infra/config/buckets/ci.star
+++ b/infra/config/buckets/ci.star
@@ -444,32 +444,26 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-asan-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-cfi-thin-lto-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-dbg',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-arm-generic-dbg',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-arm-generic-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-kevin-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
@@ -1044,12 +1038,10 @@
 
 fyi_builder(
     name = 'chromeos-amd64-generic-rel-vm-tests',
-    goma_enable_ats = True,
 )
 
 fyi_builder(
     name = 'chromeos-kevin-rel-hw-tests',
-    goma_enable_ats = True,
 )
 
 fyi_builder(
diff --git a/infra/config/buckets/try.star b/infra/config/buckets/try.star
index 03f6b6c2..5cd8c76 100644
--- a/infra/config/buckets/try.star
+++ b/infra/config/buckets/try.star
@@ -495,7 +495,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-dbg',
-    goma_enable_ats = True,
     tryjob = tryjob(
         location_regexp = [
             '.+/[+]/content/gpu/.+',
@@ -506,23 +505,19 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-cfi-thin-lto-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-arm-generic-dbg',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
     name = 'chromeos-arm-generic-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(),
 )
 
 chromiumos_builder(
     name = 'chromeos-kevin-compile-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(
         location_regexp = [
             '.+/[+]/chromeos/CHROMEOS_LKGM',
@@ -532,7 +527,6 @@
 
 chromiumos_builder(
     name = 'chromeos-kevin-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(
         location_regexp = [
             '.+/[+]/build/chromeos/.+',
@@ -1107,7 +1101,6 @@
 
 linux_builder(
     name = 'linux_arm',
-    goma_enable_ats = True,
 )
 
 linux_builder(
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index b29eab6..ef43d13e 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -31,7 +31,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -52,7 +52,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -73,7 +73,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -94,7 +94,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -115,7 +115,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -136,7 +136,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -157,7 +157,7 @@
         name: "chromium_afl"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -178,7 +178,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -199,7 +199,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -220,7 +220,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -241,7 +241,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -262,7 +262,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -283,7 +283,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -304,7 +304,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -325,7 +325,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -346,7 +346,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -367,7 +367,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -388,7 +388,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -409,7 +409,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -430,7 +430,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -451,7 +451,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -472,7 +472,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -493,7 +493,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -514,7 +514,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -536,7 +536,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -557,7 +557,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -578,7 +578,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -599,7 +599,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -620,7 +620,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -641,7 +641,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -662,7 +662,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android.fyi\""
       >
@@ -683,7 +683,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android.fyi\""
       >
@@ -704,7 +704,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -725,7 +725,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -746,7 +746,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -767,7 +767,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -830,7 +830,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -851,7 +851,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -872,7 +872,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":50,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":50,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -893,7 +893,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -914,7 +914,7 @@
         name: "closure_compilation"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -977,7 +977,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -998,7 +998,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1019,7 +1019,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1040,7 +1040,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1061,7 +1061,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1082,7 +1082,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1141,7 +1141,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1162,7 +1162,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1183,7 +1183,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1204,7 +1204,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1267,7 +1267,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1288,7 +1288,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1309,7 +1309,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1330,7 +1330,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1393,7 +1393,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1414,7 +1414,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1435,7 +1435,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1456,7 +1456,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.dawn\""
       >
@@ -1477,7 +1477,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -1498,7 +1498,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -1519,7 +1519,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -1540,7 +1540,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -1561,7 +1561,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -1582,7 +1582,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -1603,7 +1603,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -1624,7 +1624,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -1645,7 +1645,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -1666,7 +1666,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -1687,7 +1687,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -1768,7 +1768,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -1979,7 +1979,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -2000,7 +2000,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -2103,7 +2103,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -2124,7 +2124,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -2145,7 +2145,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -2166,7 +2166,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2187,7 +2187,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2208,7 +2208,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2229,7 +2229,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2249,7 +2249,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2270,7 +2270,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2291,7 +2291,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2312,7 +2312,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2333,7 +2333,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2354,7 +2354,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2375,7 +2375,7 @@
         name: "chromium_libfuzzer"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -2436,7 +2436,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2457,7 +2457,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2478,7 +2478,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2500,7 +2500,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -2521,7 +2521,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -2542,7 +2542,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -2563,7 +2563,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2584,7 +2584,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2605,7 +2605,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2626,7 +2626,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.chromiumos\""
       >
@@ -2647,7 +2647,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2668,7 +2668,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -2689,7 +2689,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -2770,7 +2770,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -2891,7 +2891,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu.fyi\""
       >
@@ -2992,7 +2992,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -3013,7 +3013,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -3035,7 +3035,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -3056,7 +3056,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -3077,7 +3077,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -3120,7 +3120,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -3141,7 +3141,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -3162,7 +3162,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -3183,7 +3183,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -3204,7 +3204,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -3225,7 +3225,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -3246,7 +3246,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -3267,7 +3267,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -3425,7 +3425,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -3707,7 +3707,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -3728,7 +3728,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -3750,7 +3750,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -3927,7 +3927,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -3948,7 +3948,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -3969,7 +3969,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -3990,7 +3990,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -4011,7 +4011,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -4052,7 +4052,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -4073,7 +4073,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -4094,7 +4094,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -4115,7 +4115,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -4136,7 +4136,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -4797,7 +4797,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -4818,7 +4818,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fuzz\""
       >
@@ -4839,7 +4839,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.clang\""
         properties_j: "perf_dashboard_machine_group:\"ChromiumClang\""
@@ -4861,7 +4861,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -4882,7 +4882,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -4903,7 +4903,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -4924,7 +4924,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -5509,7 +5509,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -5531,7 +5531,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -5752,7 +5752,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -5773,7 +5773,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium\""
       >
@@ -5794,7 +5794,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium\""
       >
@@ -5815,7 +5815,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -5836,7 +5836,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.memory\""
       >
@@ -5877,7 +5877,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android.fyi\""
       >
@@ -5899,7 +5899,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/code_coverage:{\"use_java_coverage\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -5921,7 +5921,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -5942,7 +5942,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -5963,7 +5963,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -5984,7 +5984,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6005,7 +6005,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6026,7 +6026,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6047,7 +6047,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6068,7 +6068,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6107,7 +6107,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6128,7 +6128,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6149,7 +6149,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6170,7 +6170,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6192,7 +6192,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6214,7 +6214,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6235,7 +6235,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android.fyi\""
       >
@@ -6256,7 +6256,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -6277,7 +6277,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6298,7 +6298,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -6319,7 +6319,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android.fyi\""
       >
@@ -6550,7 +6550,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -6571,7 +6571,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -6592,7 +6592,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -6613,7 +6613,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -6634,7 +6634,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -6655,7 +6655,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -6967,7 +6967,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -6988,7 +6988,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium\""
       >
@@ -7009,7 +7009,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium\""
       >
@@ -7030,7 +7030,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7051,7 +7051,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7072,7 +7072,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7093,7 +7093,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7114,7 +7114,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7136,7 +7136,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7157,7 +7157,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.chromiumos\""
       >
@@ -7179,7 +7179,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.chromiumos\""
       >
@@ -7200,7 +7200,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7221,7 +7221,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7243,7 +7243,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7264,7 +7264,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
       >
@@ -7306,7 +7306,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -7327,7 +7327,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7348,7 +7348,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7369,7 +7369,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7390,7 +7390,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7411,7 +7411,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7432,7 +7432,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.swangle\""
       >
@@ -7453,7 +7453,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -7516,7 +7516,7 @@
         name: "findit/chromium/update_components"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -8055,7 +8055,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8078,7 +8078,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8145,7 +8145,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -8168,7 +8168,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8235,7 +8235,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8258,7 +8258,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8473,7 +8473,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8496,7 +8496,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -8519,7 +8519,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -8589,7 +8589,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.chromiumos\""
       >
@@ -8650,7 +8650,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8673,7 +8673,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8740,7 +8740,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":500,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.linux\""
       >
@@ -8763,7 +8763,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8830,7 +8830,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -8853,7 +8853,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -9068,7 +9068,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.gpu\""
       >
@@ -9091,7 +9091,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -9114,7 +9114,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.android\""
       >
@@ -9184,7 +9184,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.chromiumos\""
       >
@@ -11270,7 +11270,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11299,7 +11299,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11328,7 +11328,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11357,7 +11357,7 @@
         name: "binary_size_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11386,7 +11386,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11415,7 +11415,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11444,7 +11444,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11474,7 +11474,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11505,7 +11505,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_java_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11534,7 +11534,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11563,7 +11563,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11592,7 +11592,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11621,7 +11621,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11651,7 +11651,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11680,7 +11680,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11709,7 +11709,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11738,7 +11738,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11767,7 +11767,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11796,7 +11796,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11825,7 +11825,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11854,7 +11854,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11883,7 +11883,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -11911,7 +11911,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -11939,7 +11939,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -11967,7 +11967,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -11995,7 +11995,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -12023,7 +12023,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -12051,7 +12051,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -12080,7 +12080,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12109,7 +12109,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12138,7 +12138,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12167,7 +12167,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12196,7 +12196,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12225,7 +12225,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12254,7 +12254,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12283,7 +12283,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12312,7 +12312,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12341,7 +12341,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "buildername:\"android-cronet-arm-dbg\""
         properties_j: "mastername:\"tryserver.chromium.android\""
@@ -12371,7 +12371,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12400,7 +12400,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12428,7 +12428,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12457,7 +12457,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12486,7 +12486,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -12515,7 +12515,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -12544,7 +12544,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -12808,7 +12808,7 @@
         name: "closure_compilation"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -12835,7 +12835,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.dawn\""
       >
@@ -12944,7 +12944,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -12973,7 +12973,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13002,7 +13002,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13031,7 +13031,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13060,7 +13060,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13089,7 +13089,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13118,7 +13118,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13147,7 +13147,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13176,7 +13176,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13204,7 +13204,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13232,7 +13232,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13260,7 +13260,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13288,7 +13288,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13316,7 +13316,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13344,7 +13344,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13372,7 +13372,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13400,7 +13400,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13428,7 +13428,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13456,7 +13456,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13484,7 +13484,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13512,7 +13512,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13540,7 +13540,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13568,7 +13568,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -13596,7 +13596,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13624,7 +13624,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13652,7 +13652,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13680,7 +13680,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13708,7 +13708,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13736,7 +13736,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13764,7 +13764,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13792,7 +13792,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13820,7 +13820,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13848,7 +13848,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -13876,7 +13876,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -14772,7 +14772,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -14800,7 +14800,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -14828,7 +14828,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15273,7 +15273,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15302,7 +15302,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15330,7 +15330,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -15359,7 +15359,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15388,7 +15388,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15417,7 +15417,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15446,7 +15446,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15475,7 +15475,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.blink\""
       >
@@ -15504,7 +15504,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.chromiumos\""
       >
@@ -15533,7 +15533,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.chromiumos\""
       >
@@ -15564,7 +15564,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.chromiumos\""
       >
@@ -15593,7 +15593,7 @@
         name: "tricium_clang_tidy_wrapper"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15622,7 +15622,7 @@
         name: "tricium_clang_tidy_wrapper"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15649,7 +15649,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.dawn\""
       >
@@ -15678,7 +15678,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15735,7 +15735,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15764,7 +15764,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15793,7 +15793,7 @@
         name: "chromium_libfuzzer_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15822,7 +15822,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15853,7 +15853,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -15882,7 +15882,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -15911,7 +15911,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -15940,7 +15940,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -15969,7 +15969,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -15998,7 +15998,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -16027,7 +16027,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.swangle\""
       >
@@ -16056,7 +16056,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16085,7 +16085,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16114,7 +16114,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16143,7 +16143,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16172,7 +16172,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -16200,7 +16200,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -16228,7 +16228,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.angle\""
       >
@@ -16286,7 +16286,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16315,7 +16315,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16344,7 +16344,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16373,7 +16373,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16402,7 +16402,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16431,7 +16431,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16460,7 +16460,7 @@
         name: "swarming/deterministic_build"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16489,7 +16489,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16518,7 +16518,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16547,7 +16547,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16580,7 +16580,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16609,7 +16609,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16642,7 +16642,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16671,7 +16671,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16700,7 +16700,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16729,7 +16729,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16758,7 +16758,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16787,7 +16787,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16816,7 +16816,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16844,7 +16844,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -16901,7 +16901,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -17520,7 +17520,7 @@
         name: "tricium_metrics"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -17549,7 +17549,7 @@
         name: "chromium_trybot"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -18507,7 +18507,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -18539,7 +18539,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_java_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -18666,7 +18666,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.chromiumos\""
       >
@@ -18698,7 +18698,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -18822,7 +18822,7 @@
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -18854,7 +18854,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_java_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":300,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.android\""
       >
@@ -18981,7 +18981,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.chromiumos\""
       >
@@ -19013,7 +19013,7 @@
         cipd_version: "refs/heads/master"
         properties_j: "$build/chromium_tests:{\"bucketed_triggers\":true}"
         properties_j: "$build/code_coverage:{\"use_clang_coverage\":true}"
-        properties_j: "$build/goma:{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"tryserver.chromium.linux\""
       >
@@ -19117,7 +19117,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc\""
         properties_j: "perf_dashboard_machine_group:\"ChromiumWebRTC\""
       >
@@ -19154,7 +19154,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc\""
         properties_j: "perf_dashboard_machine_group:\"ChromiumWebRTC\""
       >
@@ -19318,7 +19318,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc.fyi\""
       >
       execution_timeout_secs: 7200
@@ -19336,7 +19336,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc.fyi\""
       >
       execution_timeout_secs: 7200
@@ -19354,7 +19354,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc.fyi\""
       >
       execution_timeout_secs: 7200
@@ -19406,7 +19406,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc.fyi\""
       >
       execution_timeout_secs: 7200
@@ -19424,7 +19424,7 @@
         name: "chromium"
         cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
         cipd_version: "refs/heads/master"
-        properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "mastername:\"chromium.webrtc.fyi\""
       >
       execution_timeout_secs: 7200
diff --git a/infra/config/generated/tricium-prod.cfg b/infra/config/generated/tricium-prod.cfg
index 31e8437e..9e24eb8 100644
--- a/infra/config/generated/tricium-prod.cfg
+++ b/infra/config/generated/tricium-prod.cfg
@@ -48,7 +48,7 @@
   provides: RESULTS
   path_filters: "*.xml"
   path_filters: "*.json"
-  owner: "isherman@chromium.com"
+  owner: "isherman@chromium.org"
   monorail_component: "Internals>Metrics>Tricium"
   impls {
     runtime_platform: UBUNTU
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star
index 858fa3b..3310860 100644
--- a/infra/config/lib/builders.star
+++ b/infra/config/lib/builders.star
@@ -160,7 +160,7 @@
     goma_properties['enable_ats'] = True
   elif (goma_backend in (goma.backend.RBE_TOT, goma.backend.RBE_STAGING,
                          goma.backend.RBE_PROD) and
-        (os and os.category == os_category.WINDOWS)):
+        (os and os.category in (os_category.LINUX, os_category.WINDOWS))):
     goma_properties['enable_ats'] = True
 
   goma_jobs = _default('goma_jobs', goma_jobs)
diff --git a/infra/config/tricium-prod.cfg b/infra/config/tricium-prod.cfg
index 31e8437e..9e24eb8 100644
--- a/infra/config/tricium-prod.cfg
+++ b/infra/config/tricium-prod.cfg
@@ -48,7 +48,7 @@
   provides: RESULTS
   path_filters: "*.xml"
   path_filters: "*.json"
-  owner: "isherman@chromium.com"
+  owner: "isherman@chromium.org"
   monorail_component: "Internals>Metrics>Tricium"
   impls {
     runtime_platform: UBUNTU
diff --git a/infra/config/versioned/milestones/m79/buckets/ci.star b/infra/config/versioned/milestones/m79/buckets/ci.star
index 3cc3f3d..a8c6346 100644
--- a/infra/config/versioned/milestones/m79/buckets/ci.star
+++ b/infra/config/versioned/milestones/m79/buckets/ci.star
@@ -76,7 +76,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
diff --git a/infra/config/versioned/milestones/m79/buckets/try.star b/infra/config/versioned/milestones/m79/buckets/try.star
index 70b58a0..5518407 100644
--- a/infra/config/versioned/milestones/m79/buckets/try.star
+++ b/infra/config/versioned/milestones/m79/buckets/try.star
@@ -151,7 +151,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(
         # TODO(https://crbug.com/1024641) Make non-experimental
         experiment_percentage = 1,
diff --git a/infra/config/versioned/milestones/m80/buckets/ci.star b/infra/config/versioned/milestones/m80/buckets/ci.star
index 3cc3f3d..a8c6346 100644
--- a/infra/config/versioned/milestones/m80/buckets/ci.star
+++ b/infra/config/versioned/milestones/m80/buckets/ci.star
@@ -76,7 +76,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
diff --git a/infra/config/versioned/milestones/m80/buckets/try.star b/infra/config/versioned/milestones/m80/buckets/try.star
index 70cf4fd8..13390ee 100644
--- a/infra/config/versioned/milestones/m80/buckets/try.star
+++ b/infra/config/versioned/milestones/m80/buckets/try.star
@@ -145,7 +145,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(),
 )
 
diff --git a/infra/config/versioned/trunk/buckets/ci.star b/infra/config/versioned/trunk/buckets/ci.star
index 3cc3f3d..a8c6346 100644
--- a/infra/config/versioned/trunk/buckets/ci.star
+++ b/infra/config/versioned/trunk/buckets/ci.star
@@ -76,7 +76,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
 )
 
 chromiumos_builder(
diff --git a/infra/config/versioned/trunk/buckets/try.star b/infra/config/versioned/trunk/buckets/try.star
index 70cf4fd8..13390ee 100644
--- a/infra/config/versioned/trunk/buckets/try.star
+++ b/infra/config/versioned/trunk/buckets/try.star
@@ -145,7 +145,6 @@
 
 chromiumos_builder(
     name = 'chromeos-amd64-generic-rel',
-    goma_enable_ats = True,
     tryjob = tryjob(),
 )
 
diff --git a/ios/chrome/browser/itunes_urls/BUILD.gn b/ios/chrome/browser/itunes_urls/BUILD.gn
index 284abd6..91c5b24 100644
--- a/ios/chrome/browser/itunes_urls/BUILD.gn
+++ b/ios/chrome/browser/itunes_urls/BUILD.gn
@@ -23,9 +23,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "itunes_urls_handler_tab_helper_unittest.mm",
-  ]
+  sources = [ "itunes_urls_handler_tab_helper_unittest.mm" ]
   deps = [
     ":itunes_urls",
     "//base",
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
index f42be05..8ab228c 100644
--- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
@@ -28,6 +28,7 @@
 using chrome_test_util::ButtonWithAccessibilityLabel;
 using chrome_test_util::ButtonWithAccessibilityLabelId;
 using chrome_test_util::NavigationBarDoneButton;
+using chrome_test_util::SettingsMenuBackButton;
 using chrome_test_util::SettingsDoneButton;
 
 namespace {
@@ -61,17 +62,6 @@
   return grey_accessibilityID(kAutofillPaymentMethodsToolbarId);
 }
 
-id<GREYMatcher> SettingsMenuBackButton(NSString* backItemTitle) {
-#if defined(CHROME_EARL_GREY_2)
-  return grey_allOf(
-      grey_accessibilityLabel(backItemTitle),
-      grey_kindOfClassName(@"UIAccessibilityBackButtonElement"),
-      grey_ancestor(grey_accessibilityID(@"SettingNavigationBar")), nil);
-#else
-  return chrome_test_util::SettingsMenuBackButton();
-#endif
-}
-
 }  // namespace
 
 // Various tests for the Autofill credit cards section of the settings.
@@ -125,9 +115,7 @@
 
 // Close the settings.
 - (void)exitSettingsMenu {
-  [[EarlGrey
-      selectElementWithMatcher:SettingsMenuBackButton(l10n_util::GetNSString(
-                                   IDS_IOS_SETTINGS_TITLE))]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -152,9 +140,7 @@
   }
 
   // Go back to the list view page.
-  [[EarlGrey
-      selectElementWithMatcher:SettingsMenuBackButton(l10n_util::GetNSString(
-                                   IDS_AUTOFILL_PAYMENT_METHODS))]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
 
   [self exitSettingsMenu];
@@ -168,9 +154,7 @@
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
 
   // Go back to the list view page.
-  [[EarlGrey
-      selectElementWithMatcher:SettingsMenuBackButton(l10n_util::GetNSString(
-                                   IDS_AUTOFILL_PAYMENT_METHODS))]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
 
   [self exitSettingsMenu];
@@ -187,9 +171,7 @@
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
 
   // Go back to the list view page.
-  [[EarlGrey
-      selectElementWithMatcher:SettingsMenuBackButton(l10n_util::GetNSString(
-                                   IDS_AUTOFILL_PAYMENT_METHODS))]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
 
   [self exitSettingsMenu];
diff --git a/ios/chrome/browser/ui/settings/language/language_settings_egtest.mm b/ios/chrome/browser/ui/settings/language/language_settings_egtest.mm
index 40aff9e..b23a082 100644
--- a/ios/chrome/browser/ui/settings/language/language_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/language/language_settings_egtest.mm
@@ -53,12 +53,10 @@
   return grey_accessibilityID(kAddLanguageTableViewAccessibilityIdentifier);
 }
 
-#ifndef CHROME_EARL_GREY_2
 // Matcher for the Language Settings's Language Details page table view.
 id<GREYMatcher> LanguageDetailsTableView() {
   return grey_accessibilityID(kLanguageDetailsTableViewAccessibilityIdentifier);
 }
-#endif
 
 // Matcher for the Language Settings's general Settings menu entry.
 id<GREYMatcher> LanguageSettingsButton() {
@@ -180,9 +178,6 @@
       assertWithMatcher:grey_notNil()];
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
 
-// TODO(crbug.com/1036578): Enable the second part of the test when back button
-// matcher is fixed in EG2.
-#ifndef CHROME_EARL_GREY_2
   // Navigate back.
   [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
@@ -196,7 +191,6 @@
   [[EarlGrey selectElementWithMatcher:LanguageDetailsTableView()]
       assertWithMatcher:grey_notNil()];
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
-#endif
 }
 
 // Tests that the Translate Switch enables/disables Translate and the UI gets
diff --git a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
index 8bd8f88..e2e6f44 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_settings_egtest.mm
@@ -51,6 +51,7 @@
 using chrome_test_util::ButtonWithAccessibilityLabel;
 using chrome_test_util::NavigationBarDoneButton;
 using chrome_test_util::SettingsDoneButton;
+using chrome_test_util::SettingsMenuBackButton;
 using chrome_test_util::TurnSettingsSwitchOn;
 
 namespace {
@@ -109,17 +110,6 @@
       inRoot:grey_accessibilityID(kPasswordsExportConfirmViewId)];
 }
 
-id<GREYMatcher> SettingsMenuBackButton(NSString* backItemTitle) {
-#if defined(CHROME_EARL_GREY_2)
-  return grey_allOf(
-      grey_accessibilityLabel(backItemTitle),
-      grey_kindOfClassName(@"UIAccessibilityBackButtonElement"),
-      grey_ancestor(grey_accessibilityID(@"SettingNavigationBar")), nil);
-#else
-  return chrome_test_util::SettingsMenuBackButton();
-#endif
-}
-
 // Matcher for a UITextField inside a SettingsSearchCell.
 id<GREYMatcher> SearchTextField() {
   return grey_accessibilityID(kPasswordsSearchBarId);
@@ -395,10 +385,10 @@
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       performAction:grey_tap()];
   [ChromeEarlGrey verifyAccessibilityForCurrentScreen];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -439,9 +429,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -470,9 +460,9 @@
       selectElementWithMatcher:grey_accessibilityLabel(@"concrete password")]
       assertWithMatcher:grey_sufficientlyVisible()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -505,9 +495,9 @@
   // button, which does need one). The reason is that the password not being
   // shown is enough of a message that the action failed.
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -531,9 +521,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -557,9 +547,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -613,7 +603,7 @@
       assertWithMatcher:grey_allOf(grey_sufficientlyVisible(),
                                    grey_not(grey_enabled()), nil)];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -676,7 +666,7 @@
       assertWithMatcher:grey_allOf(grey_sufficientlyVisible(),
                                    grey_not(grey_enabled()), nil)];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -731,7 +721,7 @@
       assertWithMatcher:grey_allOf(grey_sufficientlyVisible(),
                                    grey_not(grey_enabled()), nil)];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -775,12 +765,12 @@
 
   // Go back to the list view and verify that the password is still in the
   // list.
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       assertWithMatcher:grey_sufficientlyVisible()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -810,7 +800,7 @@
   [[EarlGrey selectElementWithMatcher:CopyPasswordButton()]
       assertWithMatcher:grey_nil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -843,9 +833,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -879,9 +869,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -921,9 +911,9 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarLabel)]
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -971,9 +961,9 @@
   [GetInteractionForPasswordDetailItem(grey_text(kMaskedPassword))
       performAction:grey_tap()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1010,9 +1000,9 @@
   [GetInteractionForPasswordDetailItem(PasswordHeader())
       assertWithMatcher:grey_nil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1067,9 +1057,9 @@
   [[EarlGrey selectElementWithMatcher:FederationHeader()]
       assertWithMatcher:grey_nil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1107,9 +1097,9 @@
   [[EarlGrey selectElementWithMatcher:FederationHeader()]
       assertWithMatcher:grey_nil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1160,9 +1150,9 @@
   [[EarlGrey selectElementWithMatcher:PasswordHeader()]
       assertWithMatcher:grey_nil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1203,7 +1193,7 @@
         assertWithMatcher:grey_notNil()];
   }
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1228,7 +1218,7 @@
                     @"State of the UI toggle differs from real preferences.");
   }
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1257,7 +1247,7 @@
   [GetInteractionForPasswordEntry(@"example.com, concrete username")
       assertWithMatcher:grey_not(grey_sufficientlyVisible())];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1317,7 +1307,7 @@
                                    learnHow)] performAction:grey_tap()];
   // Check the sub menu is closed due to the help article.
   NSError* error = nil;
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       assertWithMatcher:grey_notNil()
                   error:&error];
   GREYAssertTrue(error, @"The settings back button is still displayed");
@@ -1380,9 +1370,9 @@
   [GetInteractionForPasswordDetailItem(siteCell)
       assertWithMatcher:grey_notNil()];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Passwords")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
@@ -1410,7 +1400,7 @@
       assertWithMatcher:grey_allOf(grey_sufficientlyVisible(),
                                    grey_not(grey_enabled()), nil)];
 
-  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton(@"Settings")]
+  [[EarlGrey selectElementWithMatcher:SettingsMenuBackButton()]
       performAction:grey_tap()];
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
diff --git a/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn
index e22d4c1..4a09aee 100644
--- a/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/grid/BUILD.gn
@@ -51,9 +51,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "grid_view_controller_unittest.mm",
-  ]
+  sources = [ "grid_view_controller_unittest.mm" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 
diff --git a/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn b/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn
index 0cd6645..adc9b86 100644
--- a/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/grid/resources/BUILD.gn
@@ -13,13 +13,9 @@
 }
 
 colorset("grid_theme_selection_tint_color") {
-  sources = [
-    "grid_theme_selection_tint_color.colorset/Contents.json",
-  ]
+  sources = [ "grid_theme_selection_tint_color.colorset/Contents.json" ]
 }
 
 colorset("grid_theme_dark_selection_tint_color") {
-  sources = [
-    "grid_theme_dark_selection_tint_color.colorset/Contents.json",
-  ]
+  sources = [ "grid_theme_dark_selection_tint_color.colorset/Contents.json" ]
 }
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 1dedb1ed..ecce0ed 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -546,9 +546,8 @@
       SubviewWithAccessibilityIdentifier(
           @"SettingNavigationBar",
           [[UIApplication sharedApplication] keyWindow]));
-  return grey_allOf(grey_anyOf(grey_accessibilityLabel(navBar.backItem.title),
-                               grey_accessibilityLabel(@"Back"), nil),
-                    grey_kindOfClass([UIButton class]),
+  return grey_allOf(grey_anyOf(grey_buttonTitle(navBar.backItem.title),
+                               grey_buttonTitle(@"Back"), nil),
                     grey_ancestor(grey_kindOfClass([UINavigationBar class])),
                     nil);
 }
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index 768d86d..7634b11 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -16,6 +16,7 @@
   # $ cd src/ios/third_party/material_components_ios
   # $ find src -path 'src/components/*/src/*.h' -a \! -path '*Test*'|\
   #   sed -e 's:\(.*\):  "\1",:'|sort -u
+  "src/components/private/Application/src/UIApplication+MDCAppExtensions.h",
   "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.h",
   "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.h",
   "src/components/ActionSheet/src/ActionSheetThemer/MaterialActionSheet+ActionSheetThemer.h",
@@ -193,8 +194,6 @@
   "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.h",
   "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MDCFlexibleHeaderView+canAlwaysExpandToMaximumHeight.h",
   "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MaterialFlexibleHeader+CanAlwaysExpandToMaximumHeight.h",
-  "src/components/FlexibleHeader/src/ColorThemer/MDCFlexibleHeaderColorThemer.h",
-  "src/components/FlexibleHeader/src/ColorThemer/MaterialFlexibleHeader+ColorThemer.h",
   "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h",
   "src/components/FlexibleHeader/src/MDCFlexibleHeaderView+ShiftBehavior.h",
   "src/components/FlexibleHeader/src/MDCFlexibleHeaderView.h",
@@ -417,7 +416,6 @@
   "src/components/Typography/src/private/MDCTypographyUtilities.h",
   "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h",
   "src/components/private/Application/src/MaterialApplication.h",
-  "src/components/private/Application/src/UIApplication+AppExtensions.h",
   "src/components/private/Beta/src/MaterialBetaComponent.h",
   "src/components/private/Color/src/MaterialColor.h",
   "src/components/private/Color/src/UIColor+MaterialBlending.h",
@@ -987,9 +985,6 @@
     "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.m",
     "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MDCFlexibleHeaderView+canAlwaysExpandToMaximumHeight.h",
     "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MaterialFlexibleHeader+CanAlwaysExpandToMaximumHeight.h",
-    "src/components/FlexibleHeader/src/ColorThemer/MDCFlexibleHeaderColorThemer.h",
-    "src/components/FlexibleHeader/src/ColorThemer/MDCFlexibleHeaderColorThemer.m",
-    "src/components/FlexibleHeader/src/ColorThemer/MaterialFlexibleHeader+ColorThemer.h",
     "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h",
     "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m",
     "src/components/FlexibleHeader/src/MDCFlexibleHeaderView+ShiftBehavior.h",
@@ -1342,8 +1337,8 @@
     "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h",
     "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m",
     "src/components/private/Application/src/MaterialApplication.h",
-    "src/components/private/Application/src/UIApplication+AppExtensions.h",
-    "src/components/private/Application/src/UIApplication+AppExtensions.m",
+    "src/components/private/Application/src/UIApplication+MDCAppExtensions.h",
+    "src/components/private/Application/src/UIApplication+MDCAppExtensions.m",
     "src/components/private/Beta/src/MaterialBetaComponent.h",
     "src/components/private/Color/src/MaterialColor.h",
     "src/components/private/Color/src/UIColor+MaterialBlending.h",
diff --git a/ios/web_view/public/cwv_back_forward_list.h b/ios/web_view/public/cwv_back_forward_list.h
index c972e8a..76e1c2e6 100644
--- a/ios/web_view/public/cwv_back_forward_list.h
+++ b/ios/web_view/public/cwv_back_forward_list.h
@@ -9,10 +9,9 @@
 
 #import "cwv_export.h"
 
-#import "ios/web_view/public/cwv_back_forward_list_item.h"
-
 NS_ASSUME_NONNULL_BEGIN
 
+@class CWVBackForwardListItem;
 @class CWVWebView;
 
 // This just behaves like a NSArray<CWVBackForwardListItem*>.
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index c4be311..31e8882 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -85,6 +85,7 @@
     "bit_reader_core.h",
     "bitstream_buffer.cc",
     "bitstream_buffer.h",
+    "buffering_state.cc",
     "buffering_state.h",
     "byte_queue.cc",
     "byte_queue.h",
@@ -178,10 +179,14 @@
     "media_export.h",
     "media_log.cc",
     "media_log.h",
+    "media_log_events.cc",
+    "media_log_events.h",
+    "media_log_message_levels.cc",
+    "media_log_message_levels.h",
     "media_log_properties.cc",
     "media_log_properties.h",
-    "media_log_properties_helper.h",
     "media_log_record.h",
+    "media_log_type_enforcement.h",
     "media_observer.cc",
     "media_observer.h",
     "media_permission.cc",
diff --git a/media/base/android/media_codec_bridge_impl.cc b/media/base/android/media_codec_bridge_impl.cc
index edf707cc..8bd73ac 100644
--- a/media/base/android/media_codec_bridge_impl.cc
+++ b/media/base/android/media_codec_bridge_impl.cc
@@ -22,7 +22,6 @@
 #include "media/base/android/media_jni_headers/MediaCodecBridgeBuilder_jni.h"
 #include "media/base/android/media_jni_headers/MediaCodecBridge_jni.h"
 #include "media/base/audio_codecs.h"
-#include "media/base/bit_reader.h"
 #include "media/base/subsample_entry.h"
 #include "media/base/video_codecs.h"
 
@@ -55,20 +54,27 @@
 using CodecSpecificData = std::vector<uint8_t>;
 
 // Parses |extra_data| to get info to be added to a Java MediaFormat.
-bool GetCodecSpecificDataForAudio(AudioCodec codec,
-                                  const uint8_t* extra_data,
-                                  size_t extra_data_size,
-                                  int64_t codec_delay_ns,
-                                  int64_t seek_preroll_ns,
+bool GetCodecSpecificDataForAudio(const AudioDecoderConfig& config,
                                   CodecSpecificData* output_csd0,
                                   CodecSpecificData* output_csd1,
                                   CodecSpecificData* output_csd2,
                                   bool* output_frame_has_adts_header) {
+  // It's important that the multiplication is first in this calculation to
+  // reduce the precision loss due to integer truncation.
+  const int64_t codec_delay_ns = base::Time::kNanosecondsPerSecond *
+                                 config.codec_delay() /
+                                 config.samples_per_second();
+  const int64_t seek_preroll_ns = config.seek_preroll().InMicroseconds() *
+                                  base::Time::kNanosecondsPerMicrosecond;
+
+  const uint8_t* extra_data = config.extra_data().data();
+  const size_t extra_data_size = config.extra_data().size();
+
   *output_frame_has_adts_header = false;
-  if (extra_data_size == 0 && codec != kCodecOpus)
+  if (extra_data_size == 0 && config.codec() != kCodecOpus)
     return true;
 
-  switch (codec) {
+  switch (config.codec()) {
     case kCodecVorbis: {
       if (extra_data[0] != 2) {
         LOG(ERROR) << "Invalid number of vorbis headers before the codec "
@@ -112,7 +118,8 @@
     }
     case kCodecAAC: {
       output_csd0->assign(extra_data, extra_data + extra_data_size);
-      *output_frame_has_adts_header = true;
+      *output_frame_has_adts_header =
+          config.profile() != AudioCodecProfile::kXHE_AAC;
       break;
     }
     case kCodecOpus: {
@@ -139,8 +146,8 @@
       break;
     }
     default:
-      LOG(ERROR) << "Invalid header encountered for codec: "
-                 << GetCodecName(codec);
+      LOG(ERROR) << "Unsupported audio codec encountered: "
+                 << GetCodecName(config.codec());
       return false;
   }
   return true;
@@ -173,19 +180,9 @@
   const int channel_count =
       ChannelLayoutToChannelCount(config.channel_layout());
 
-  // It's important that the multiplication is first in this calculation to
-  // reduce the precision loss due to integer truncation.
-  const int64_t codec_delay_ns = base::Time::kNanosecondsPerSecond *
-                                 config.codec_delay() /
-                                 config.samples_per_second();
-  const int64_t seek_preroll_ns = config.seek_preroll().InMicroseconds() *
-                                  base::Time::kNanosecondsPerMicrosecond;
-
   CodecSpecificData csd0, csd1, csd2;
   bool output_frame_has_adts_header;
-  if (!GetCodecSpecificDataForAudio(config.codec(), config.extra_data().data(),
-                                    config.extra_data().size(), codec_delay_ns,
-                                    seek_preroll_ns, &csd0, &csd1, &csd2,
+  if (!GetCodecSpecificDataForAudio(config, &csd0, &csd1, &csd2,
                                     &output_frame_has_adts_header)) {
     return nullptr;
   }
diff --git a/media/base/audio_codecs.cc b/media/base/audio_codecs.cc
index 5b39eb04..ba5dbc66 100644
--- a/media/base/audio_codecs.cc
+++ b/media/base/audio_codecs.cc
@@ -47,8 +47,15 @@
     case kCodecMpegHAudio:
       return "mpeg-h-audio";
   }
-  NOTREACHED();
-  return "";
+}
+
+std::string GetProfileName(AudioCodecProfile profile) {
+  switch (profile) {
+    case AudioCodecProfile::kUnknown:
+      return "unknown";
+    case AudioCodecProfile::kXHE_AAC:
+      return "xhe-aac";
+  }
 }
 
 AudioCodec StringToAudioCodec(const std::string& codec_id) {
diff --git a/media/base/audio_codecs.h b/media/base/audio_codecs.h
index 756a3bb3..5eb5ddc 100644
--- a/media/base/audio_codecs.h
+++ b/media/base/audio_codecs.h
@@ -42,7 +42,18 @@
   kAudioCodecMax = kCodecMpegHAudio,
 };
 
+enum class AudioCodecProfile {
+  // These values are histogrammed over time; do not change their ordinal
+  // values.  When deleting a profile replace it with a dummy value; when adding
+  // a profile, do so at the bottom before kMaxValue, and update the value of
+  // kMaxValue to equal the new codec.
+  kUnknown = 0,
+  kXHE_AAC = 1,
+  kMaxValue = kXHE_AAC,
+};
+
 std::string MEDIA_EXPORT GetCodecName(AudioCodec codec);
+std::string MEDIA_EXPORT GetProfileName(AudioCodecProfile profile);
 
 MEDIA_EXPORT AudioCodec StringToAudioCodec(const std::string& codec_id);
 
diff --git a/media/base/audio_decoder_config.cc b/media/base/audio_decoder_config.cc
index 4f13ee3..c05a64e 100644
--- a/media/base/audio_decoder_config.cc
+++ b/media/base/audio_decoder_config.cc
@@ -75,12 +75,14 @@
           (seek_preroll() == config.seek_preroll()) &&
           (codec_delay() == config.codec_delay()) &&
           (should_discard_decoder_delay() ==
-           config.should_discard_decoder_delay()));
+           config.should_discard_decoder_delay()) &&
+          (profile() == config.profile()));
 }
 
 std::string AudioDecoderConfig::AsHumanReadableString() const {
   std::ostringstream s;
   s << "codec: " << GetCodecName(codec())
+    << ", profile: " << GetProfileName(profile())
     << ", bytes_per_channel: " << bytes_per_channel()
     << ", channel_layout: " << ChannelLayoutToString(channel_layout())
     << ", channels: " << channels()
diff --git a/media/base/audio_decoder_config.h b/media/base/audio_decoder_config.h
index a7f294d..8fc0cd8 100644
--- a/media/base/audio_decoder_config.h
+++ b/media/base/audio_decoder_config.h
@@ -112,8 +112,14 @@
     return target_output_channel_layout_;
   }
 
+  // Optionally set if the AudioCodec has a profile which may preclude certain
+  // decoders from having support.
+  void set_profile(AudioCodecProfile profile) { profile_ = profile; }
+  AudioCodecProfile profile() const { return profile_; }
+
  private:
   AudioCodec codec_ = kUnknownAudioCodec;
+  AudioCodecProfile profile_ = AudioCodecProfile::kUnknown;
   SampleFormat sample_format_ = kUnknownSampleFormat;
   int bytes_per_channel_ = 0;
   int samples_per_second_ = 0;
diff --git a/media/base/buffering_state.cc b/media/base/buffering_state.cc
new file mode 100644
index 0000000..4cf3af51
--- /dev/null
+++ b/media/base/buffering_state.cc
@@ -0,0 +1,33 @@
+// 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 "media/base/buffering_state.h"
+#include <string>
+#include "base/logging.h"
+
+namespace media {
+
+std::string BufferingStateToString(BufferingState state,
+                                   BufferingStateChangeReason reason) {
+  DCHECK(state == BUFFERING_HAVE_NOTHING || state == BUFFERING_HAVE_ENOUGH);
+  DCHECK(reason == BUFFERING_CHANGE_REASON_UNKNOWN ||
+         reason == DEMUXER_UNDERFLOW || reason == DECODER_UNDERFLOW ||
+         reason == REMOTING_NETWORK_CONGESTION);
+
+  std::string state_string = state == BUFFERING_HAVE_NOTHING
+                                 ? "BUFFERING_HAVE_NOTHING"
+                                 : "BUFFERING_HAVE_ENOUGH";
+
+  std::vector<std::string> flag_strings;
+  if (reason == DEMUXER_UNDERFLOW)
+    state_string += " (DEMUXER_UNDERFLOW)";
+  else if (reason == DECODER_UNDERFLOW)
+    state_string += " (DECODER_UNDERFLOW)";
+  else if (reason == REMOTING_NETWORK_CONGESTION)
+    state_string += " (REMOTING_NETWORK_CONGESTION)";
+
+  return state_string;
+}
+
+}  // namespace media
diff --git a/media/base/buffering_state.h b/media/base/buffering_state.h
index 2de430f6..e1b03e3 100644
--- a/media/base/buffering_state.h
+++ b/media/base/buffering_state.h
@@ -5,6 +5,8 @@
 #ifndef MEDIA_BASE_BUFFERING_STATE_H_
 #define MEDIA_BASE_BUFFERING_STATE_H_
 
+#include <string>
+
 #include "base/callback_forward.h"
 
 namespace media {
@@ -48,10 +50,29 @@
   BUFFERING_STATE_CHANGE_REASON_MAX = REMOTING_NETWORK_CONGESTION,
 };
 
+enum class SerializableBufferingStateType {
+  kPipeline,
+  kVideo,
+  kAudio,
+};
+
+// A serializable combo of the state, type, and reason.
+template <SerializableBufferingStateType T>
+struct SerializableBufferingState {
+  BufferingState state;
+  BufferingStateChangeReason reason;
+  // Only included in the serialized state if |type == kPipeline|
+  bool suspended_start = false;
+};
+
 // Used to indicate changes in buffering state;
 typedef base::Callback<void(BufferingState, BufferingStateChangeReason)>
     BufferingStateCB;
 
+std::string BufferingStateToString(
+    BufferingState state,
+    BufferingStateChangeReason reason = BUFFERING_CHANGE_REASON_UNKNOWN);
+
 }  // namespace media
 
 #endif  // MEDIA_BASE_BUFFERING_STATE_H_
diff --git a/media/base/ipc/media_param_traits_macros.h b/media/base/ipc/media_param_traits_macros.h
index dc7617c..7e65add 100644
--- a/media/base/ipc/media_param_traits_macros.h
+++ b/media/base/ipc/media_param_traits_macros.h
@@ -50,6 +50,8 @@
 // Enum traits.
 
 IPC_ENUM_TRAITS_MAX_VALUE(media::AudioCodec, media::AudioCodec::kAudioCodecMax)
+IPC_ENUM_TRAITS_MAX_VALUE(media::AudioCodecProfile,
+                          media::AudioCodecProfile::kMaxValue)
 
 IPC_ENUM_TRAITS_MAX_VALUE(media::AudioLatency::LatencyType,
                           media::AudioLatency::LATENCY_COUNT)
diff --git a/media/base/media_log_events.cc b/media/base/media_log_events.cc
new file mode 100644
index 0000000..24c2f1e
--- /dev/null
+++ b/media/base/media_log_events.cc
@@ -0,0 +1,44 @@
+// 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 "media/base/media_log_events.h"
+
+#include <string>
+
+#include "base/logging.h"
+
+namespace media {
+
+std::string MediaLogEventToString(MediaLogEvent level) {
+  switch (level) {
+    case MediaLogEvent::kPlay:
+      return "PLAY";
+    case MediaLogEvent::kPause:
+      return "PAUSE";
+    case MediaLogEvent::kSeek:
+      return "SEEK";
+    case MediaLogEvent::kPipelineStateChange:
+      return "PIPELINE_STATE_CHANGED";
+    case MediaLogEvent::kWebMediaPlayerCreated:
+      return "WEBMEDIAPLAYER_CREATED";
+    case MediaLogEvent::kWebMediaPlayerDestroyed:
+      return "WEBMEDIAPLAYER_DESTROYED";
+    case MediaLogEvent::kLoad:
+      return "LOAD";
+    case MediaLogEvent::kVideoSizeChanged:
+      return "VIDEO_SIZE_SET";
+    case MediaLogEvent::kDurationChanged:
+      return "DURATION_SET";
+    case MediaLogEvent::kEnded:
+      return "ENDED";
+    case MediaLogEvent::kBufferingStateChanged:
+      return "BUFFERING_STATE_CHANGE";
+    case MediaLogEvent::kSuspended:
+      return "SUSPENDED";
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace media
\ No newline at end of file
diff --git a/media/base/media_log_events.h b/media/base/media_log_events.h
new file mode 100644
index 0000000..9a418aba
--- /dev/null
+++ b/media/base/media_log_events.h
@@ -0,0 +1,98 @@
+// 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 MEDIA_BASE_MEDIA_LOG_EVENTS_H_
+#define MEDIA_BASE_MEDIA_LOG_EVENTS_H_
+
+#include <string>
+#include "media/base/media_export.h"
+#include "media/base/media_log_type_enforcement.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+enum class MediaLogEvent {
+  // The media player has started playing.
+  kPlay,
+
+  // The media player has entered a paused state.
+  kPause,
+
+  // The media player has _started_ a seek operation.
+  kSeek,
+
+  // The pipeline state has changed - see PipelineStatus in
+  // media/base/pipeline_status.h
+  kPipelineStateChange,
+
+  // The media stack implementation of the blink media player has been created
+  // but may not be fully initialized.
+  kWebMediaPlayerCreated,
+
+  // The media player has been destroyed and the log will soon die. No events
+  // can come after receiving this one.
+  kWebMediaPlayerDestroyed,
+
+  // A web request has finished and the pipeline will start iminently.
+  kLoad,
+
+  // The video size has changed.
+  // TODO(tmathmeyer) This is already a property, it might be useless to have it
+  // be an event too. consider removing it.
+  kVideoSizeChanged,
+
+  // The runtime of the video was changed by the demuxer.
+  kDurationChanged,
+
+  // There is no more content to consume.
+  kEnded,
+
+  // There was a change to the buffering state of the video. This can be caused
+  // by either network slowness or decoding slowness. See the comments in
+  // media/base/buffering_state.h for more information.
+  kBufferingStateChanged,
+
+  // The player has been suspended to save resources.
+  kSuspended,
+};
+
+// This has to be declared before the macros use it - Some infra code relies on
+// the enum names to be UPPER_CASE, so this will convert them manually
+// instead of using macro stringification.
+MEDIA_EXPORT std::string MediaLogEventToString(MediaLogEvent level);
+
+// These events can be triggered with no extra associated data.
+MEDIA_LOG_EVENT_TYPELESS(kPlay);
+MEDIA_LOG_EVENT_TYPELESS(kPause);
+MEDIA_LOG_EVENT_TYPELESS(kWebMediaPlayerDestroyed);
+MEDIA_LOG_EVENT_TYPELESS(kEnded);
+MEDIA_LOG_EVENT_TYPELESS(kSuspended);
+MEDIA_LOG_EVENT_TYPELESS(kWebMediaPlayerCreated);
+
+// These events can be triggered with the extra data / names as defined here.
+// Note that some events can be defined multiple times.
+MEDIA_LOG_EVENT_NAMED_DATA(kLoad, std::string, "url");
+MEDIA_LOG_EVENT_NAMED_DATA(kSeek, double, "seek_target");
+MEDIA_LOG_EVENT_NAMED_DATA(kVideoSizeChanged, gfx::Size, "dimensions");
+MEDIA_LOG_EVENT_NAMED_DATA(kDurationChanged, base::TimeDelta, "duration");
+MEDIA_LOG_EVENT_NAMED_DATA(kWebMediaPlayerCreated, std::string, "origin_url");
+MEDIA_LOG_EVENT_NAMED_DATA(kPipelineStateChange, std::string, "pipeline_state");
+
+// Each type of buffering state gets a different name.
+MEDIA_LOG_EVENT_NAMED_DATA(
+    kBufferingStateChanged,
+    SerializableBufferingState<SerializableBufferingStateType::kVideo>,
+    "video_buffering_state");
+MEDIA_LOG_EVENT_NAMED_DATA(
+    kBufferingStateChanged,
+    SerializableBufferingState<SerializableBufferingStateType::kAudio>,
+    "audio_buffering_state");
+MEDIA_LOG_EVENT_NAMED_DATA(
+    kBufferingStateChanged,
+    SerializableBufferingState<SerializableBufferingStateType::kPipeline>,
+    "pipeline_buffering_state");
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_MEDIA_LOG_EVENTS_H_
diff --git a/media/base/media_log_message_levels.cc b/media/base/media_log_message_levels.cc
new file mode 100644
index 0000000..bea3f56
--- /dev/null
+++ b/media/base/media_log_message_levels.cc
@@ -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.
+
+#include "media/base/media_log_message_levels.h"
+
+#include <string>
+
+#include "base/logging.h"
+
+namespace media {
+
+std::string MediaLogMessageLevelToString(MediaLogMessageLevel level) {
+  switch (level) {
+    case MediaLogMessageLevel::kERROR:
+      return "error";
+    case MediaLogMessageLevel::kWARNING:
+      return "warning";
+    case MediaLogMessageLevel::kINFO:
+      return "info";
+    case MediaLogMessageLevel::kDEBUG:
+      return "debug";
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace media
\ No newline at end of file
diff --git a/media/base/media_log_message_levels.h b/media/base/media_log_message_levels.h
new file mode 100644
index 0000000..d79df67
--- /dev/null
+++ b/media/base/media_log_message_levels.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 MEDIA_BASE_MEDIA_LOG_MESSAGE_LEVELS_H_
+#define MEDIA_BASE_MEDIA_LOG_MESSAGE_LEVELS_H_
+
+#include <string>
+
+#include "media/base/media_export.h"
+
+namespace media {
+
+// TODO(tmathmeyer) Find a nice way to make this use the kCamelCase style, while
+// still preserving the "MEDIA_LOG(ERROR, ...)" syntax. macros are bad :(
+enum class MediaLogMessageLevel {
+  kERROR,
+  kWARNING,
+  kINFO,
+  kDEBUG,
+};
+
+MEDIA_EXPORT std::string MediaLogMessageLevelToString(
+    MediaLogMessageLevel level);
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_MEDIA_LOG_MESSAGE_LEVELS_H_
diff --git a/media/base/media_log_properties.h b/media/base/media_log_properties.h
index 1c89791..ed18f2b 100644
--- a/media/base/media_log_properties.h
+++ b/media/base/media_log_properties.h
@@ -10,7 +10,7 @@
 
 #include "media/base/audio_decoder_config.h"
 #include "media/base/media_export.h"
-#include "media/base/media_log_properties_helper.h"
+#include "media/base/media_log_type_enforcement.h"
 #include "media/base/video_decoder_config.h"
 #include "ui/gfx/geometry/size.h"
 
diff --git a/media/base/media_log_properties_helper.h b/media/base/media_log_properties_helper.h
deleted file mode 100644
index e8b325a..0000000
--- a/media/base/media_log_properties_helper.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_BASE_MEDIA_LOG_PROPERTIES_HELPER_H_
-#define MEDIA_BASE_MEDIA_LOG_PROPERTIES_HELPER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/values.h"
-#include "media/base/media_serializers.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace media {
-
-// Forward declare the enum.
-enum class MediaLogProperty;
-
-// Allow only specific types for an individual property.
-template <MediaLogProperty PROP, typename T>
-struct MediaLogPropertyTypeSupport {};
-
-// Lets us define the supported type in a single line in media_log_properties.h.
-#define MEDIA_LOG_PROPERTY_SUPPORTS_TYPE(PROPERTY, TYPE)                 \
-  template <>                                                            \
-  struct MediaLogPropertyTypeSupport<MediaLogProperty::PROPERTY, TYPE> { \
-    static base::Value Convert(const TYPE& type) {                       \
-      return MediaSerialize<TYPE>(type);                                 \
-    }                                                                    \
-  }
-
-}  // namespace media
-
-#endif  // MEDIA_BASE_MEDIA_LOG_PROPERTIES_HELPER_H_
diff --git a/media/base/media_log_type_enforcement.h b/media/base/media_log_type_enforcement.h
new file mode 100644
index 0000000..16bd9e7
--- /dev/null
+++ b/media/base/media_log_type_enforcement.h
@@ -0,0 +1,59 @@
+// 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 MEDIA_BASE_MEDIA_LOG_TYPE_ENFORCEMENT_H_
+#define MEDIA_BASE_MEDIA_LOG_TYPE_ENFORCEMENT_H_
+
+#include "media/base/media_serializers.h"
+
+namespace media {
+
+namespace internal {
+enum class UnmatchableType {};
+}  // namespace internal
+
+// Forward declare the enums.
+enum class MediaLogProperty;
+enum class MediaLogEvent;
+
+// Allow only specific types for an individual property.
+template <MediaLogProperty PROP, typename T>
+struct MediaLogPropertyTypeSupport {};
+
+// Allow only specific types for an individual event.
+// However unlike Property, T is not required, so we default it to some
+// unmatchable type that will never be passed as an argument accidentally.
+template <MediaLogEvent EVENT, typename T = internal::UnmatchableType>
+struct MediaLogEventTypeSupport {};
+
+// Lets us define the supported type in a single line in media_log_properties.h.
+#define MEDIA_LOG_PROPERTY_SUPPORTS_TYPE(PROPERTY, TYPE)                 \
+  template <>                                                            \
+  struct MediaLogPropertyTypeSupport<MediaLogProperty::PROPERTY, TYPE> { \
+    static base::Value Convert(const TYPE& type) {                       \
+      return MediaSerialize<TYPE>(type);                                 \
+    }                                                                    \
+  }
+
+#define MEDIA_LOG_EVENT_NAMED_DATA(EVENT, TYPE, DISPLAY)           \
+  template <>                                                      \
+  struct MediaLogEventTypeSupport<MediaLogEvent::EVENT, TYPE> {    \
+    static void AddExtraData(base::Value* params, const TYPE& t) { \
+      DCHECK(params);                                              \
+      params->SetKey(DISPLAY, MediaSerialize<TYPE>(t));            \
+    }                                                              \
+    static std::string TypeName() { return #EVENT; }               \
+  }
+
+// Specifically do not create the Convert or DisplayName methods
+#define MEDIA_LOG_EVENT_TYPELESS(EVENT)                   \
+  template <>                                             \
+  struct MediaLogEventTypeSupport<MediaLogEvent::EVENT> { \
+    static std::string TypeName() { return #EVENT; }      \
+    static void AddExtraData(base::Value* params) {}      \
+  }
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_MEDIA_LOG_TYPE_ENFORCEMENT_H_
\ No newline at end of file
diff --git a/media/base/media_serializers.h b/media/base/media_serializers.h
index 101ed7c9..5047cf46 100644
--- a/media/base/media_serializers.h
+++ b/media/base/media_serializers.h
@@ -9,6 +9,7 @@
 
 #include "base/strings/stringprintf.h"
 #include "media/base/audio_decoder_config.h"
+#include "media/base/buffering_state.h"
 #include "media/base/media_serializers_base.h"
 #include "media/base/video_decoder_config.h"
 #include "ui/gfx/geometry/size.h"
@@ -118,6 +119,14 @@
   }
 };
 
+// enum (simple)
+template <>
+struct MediaSerializer<base::TimeDelta> {
+  static inline base::Value Serialize(const base::TimeDelta value) {
+    return MediaSerializer<double>::Serialize(value.InSecondsF());
+  }
+};
+
 // Enum (simple)
 template <>
 struct MediaSerializer<media::AudioCodec> {
@@ -272,6 +281,60 @@
   }
 };
 
+// enum (simple)
+template <>
+struct MediaSerializer<media::BufferingState> {
+  static inline base::Value Serialize(const media::BufferingState value) {
+    return base::Value(value == media::BufferingState::BUFFERING_HAVE_ENOUGH
+                           ? "BUFFERING_HAVE_ENOUGH"
+                           : "BUFFERING_HAVE_NOTHING");
+  }
+};
+
+// enum (complex)
+template <>
+struct MediaSerializer<media::BufferingStateChangeReason> {
+  static base::Value Serialize(const media::BufferingStateChangeReason value) {
+    switch (value) {
+      case DEMUXER_UNDERFLOW:
+        return base::Value("DEMUXER_UNDERFLOW");
+      case DECODER_UNDERFLOW:
+        return base::Value("DECODER_UNDERFLOW");
+      case REMOTING_NETWORK_CONGESTION:
+        return base::Value("REMOTING_NETWORK_CONGESTION");
+      case BUFFERING_CHANGE_REASON_UNKNOWN:
+        return base::Value("BUFFERING_CHANGE_REASON_UNKNOWN");
+    }
+  }
+};
+
+// Class (complex)
+template <media::SerializableBufferingStateType T>
+struct MediaSerializer<media::SerializableBufferingState<T>> {
+  static base::Value Serialize(
+      const media::SerializableBufferingState<T>& value) {
+    base::Value result(base::Value::Type::DICTIONARY);
+    FIELD_SERIALIZE("state", value.state);
+
+    switch (value.reason) {
+      case DEMUXER_UNDERFLOW:
+      case DECODER_UNDERFLOW:
+      case REMOTING_NETWORK_CONGESTION:
+        FIELD_SERIALIZE("reason", value.reason);
+        break;
+
+      // Don't write anything here if the reason is unknown.
+      case BUFFERING_CHANGE_REASON_UNKNOWN:
+        break;
+    }
+
+    if (T == SerializableBufferingStateType::kPipeline)
+      result.SetBoolKey("for_suspended_start", value.suspended_start);
+
+    return result;
+  }
+};
+
 #undef FIELD_SERIALIZE
 
 }  // namespace internal
diff --git a/media/base/media_types.cc b/media/base/media_types.cc
index bc980c1..ceaddc7f 100644
--- a/media/base/media_types.cc
+++ b/media/base/media_types.cc
@@ -10,7 +10,7 @@
 
 // static
 AudioType AudioType::FromDecoderConfig(const AudioDecoderConfig& config) {
-  return {config.codec()};
+  return {config.codec(), AudioCodecProfile::kUnknown, false};
 }
 
 // static
@@ -57,7 +57,8 @@
 }
 
 bool operator==(const AudioType& x, const AudioType& y) {
-  return x.codec == y.codec;
+  return std::tie(x.codec, x.profile, x.spatial_rendering) ==
+         std::tie(y.codec, y.profile, y.spatial_rendering);
 }
 
 bool operator!=(const AudioType& x, const AudioType& y) {
diff --git a/media/base/media_types.h b/media/base/media_types.h
index 7ee96a1f..c7f6f2a5 100644
--- a/media/base/media_types.h
+++ b/media/base/media_types.h
@@ -22,7 +22,8 @@
   static AudioType FromDecoderConfig(const AudioDecoderConfig& config);
 
   AudioCodec codec;
-  bool spatialRendering;
+  AudioCodecProfile profile;
+  bool spatial_rendering;
 };
 
 struct MEDIA_EXPORT VideoType {
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 23381d0..000325d 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -69,6 +69,7 @@
       {"mp4a.40.5", MimeUtil::MPEG4_AAC},
       {"mp4a.40.05", MimeUtil::MPEG4_AAC},
       {"mp4a.40.29", MimeUtil::MPEG4_AAC},
+      {"mp4a.40.42", MimeUtil::MPEG4_XHE_AAC},
       // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6
       // codec ids are valid according to RFC 6381 section 3.3, 3.4.
       // Lower-case oti (mp4a.a5 and mp4a.a6) should be rejected. But
@@ -170,6 +171,7 @@
       return kCodecEAC3;
     case MimeUtil::MPEG2_AAC:
     case MimeUtil::MPEG4_AAC:
+    case MimeUtil::MPEG4_XHE_AAC:
       return kCodecAAC;
     case MimeUtil::MPEG_H_AUDIO:
       return kCodecMpegHAudio;
@@ -310,7 +312,7 @@
   mp4_video_codecs.emplace(VP9);
 
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
-  const CodecSet aac{MPEG2_AAC, MPEG4_AAC};
+  const CodecSet aac{MPEG2_AAC, MPEG4_AAC, MPEG4_XHE_AAC};
   mp4_audio_codecs.insert(aac.begin(), aac.end());
 
   CodecSet avc_and_aac(aac);
@@ -585,6 +587,10 @@
       DCHECK(!is_encrypted || platform_info.has_platform_decoders);
       return true;
 
+    case MPEG4_XHE_AAC:
+      // xHE-AAC is only supported via MediaCodec.
+      return platform_info.has_platform_decoders;
+
     case MPEG_H_AUDIO:
       return false;
 
@@ -885,7 +891,11 @@
 
   AudioCodec audio_codec = MimeUtilToAudioCodec(codec);
   if (audio_codec != kUnknownAudioCodec) {
-    if (!IsSupportedAudioType({audio_codec}))
+    AudioCodecProfile audio_profile = AudioCodecProfile::kUnknown;
+    if (codec == MPEG4_XHE_AAC)
+      audio_profile = AudioCodecProfile::kXHE_AAC;
+
+    if (!IsSupportedAudioType({audio_codec, audio_profile, false}))
       return IsNotSupported;
   }
 
diff --git a/media/base/mime_util_internal.h b/media/base/mime_util_internal.h
index 5f604ae..1401ba2 100644
--- a/media/base/mime_util_internal.h
+++ b/media/base/mime_util_internal.h
@@ -35,6 +35,7 @@
     EAC3,
     MPEG2_AAC,
     MPEG4_AAC,
+    MPEG4_XHE_AAC,
     VORBIS,
     OPUS,
     FLAC,
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc
index 01a6de5..3125845 100644
--- a/media/base/mime_util_unittest.cc
+++ b/media/base/mime_util_unittest.cc
@@ -440,6 +440,7 @@
           case MimeUtil::MP3:
           case MimeUtil::MPEG2_AAC:
           case MimeUtil::MPEG4_AAC:
+          case MimeUtil::MPEG4_XHE_AAC:
           case MimeUtil::VORBIS:
           case MimeUtil::FLAC:
           case MimeUtil::H264:
@@ -514,6 +515,10 @@
             break;
 
           // These codecs are only supported if platform decoders are supported.
+          case MimeUtil::MPEG4_XHE_AAC:
+            EXPECT_EQ(info.has_platform_decoders, result);
+            break;
+
           case MimeUtil::HEVC:
 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
             EXPECT_EQ(
diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc
index 911a64c..86c6dc7 100644
--- a/media/base/pipeline_impl.cc
+++ b/media/base/pipeline_impl.cc
@@ -1113,6 +1113,10 @@
 }
 
 bool PipelineImpl::RendererWrapper::HasEncryptedStream() {
+  // Encrypted streams are only handled explicitly for STREAM type.
+  if (demuxer_->GetType() != MediaResource::Type::STREAM)
+    return false;
+
   auto streams = demuxer_->GetAllStreams();
 
   for (auto* stream : streams) {
diff --git a/media/base/renderer_factory_selector.cc b/media/base/renderer_factory_selector.cc
index 924bd6c..3695c44 100644
--- a/media/base/renderer_factory_selector.cc
+++ b/media/base/renderer_factory_selector.cc
@@ -15,6 +15,7 @@
 void RendererFactorySelector::AddBaseFactory(
     RendererFactoryType type,
     std::unique_ptr<RendererFactory> factory) {
+  DVLOG(1) << __func__ << ": type=" << static_cast<int>(type);
   DCHECK(!base_factory_type_) << "At most one base factory!";
 
   AddFactory(type, std::move(factory));
diff --git a/media/base/supported_types.cc b/media/base/supported_types.cc
index 0a9ff94..e6821cff 100644
--- a/media/base/supported_types.cc
+++ b/media/base/supported_types.cc
@@ -185,7 +185,7 @@
 }
 
 bool IsDefaultSupportedAudioType(const AudioType& type) {
-  if (type.spatialRendering)
+  if (type.spatial_rendering)
     return false;
 
 #if !BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -195,6 +195,15 @@
 
   switch (type.codec) {
     case kCodecAAC:
+      if (type.profile != AudioCodecProfile::kXHE_AAC)
+        return true;
+#if defined(OS_ANDROID)
+      return base::android::BuildInfo::GetInstance()->sdk_int() >=
+             base::android::SDK_VERSION_P;
+#else
+      return false;
+#endif
+
     case kCodecFLAC:
     case kCodecMP3:
     case kCodecOpus:
diff --git a/media/base/supported_types_unittest.cc b/media/base/supported_types_unittest.cc
index 24d5ea8..7645614 100644
--- a/media/base/supported_types_unittest.cc
+++ b/media/base/supported_types_unittest.cc
@@ -4,8 +4,13 @@
 
 #include "media/base/supported_types.h"
 
+#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
 namespace media {
 
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
@@ -168,36 +173,71 @@
   const bool is_spatial_rendering = true;
   // Dolby Atmos = E-AC3 (Dolby Digital Plus) + spatialRendering. Currently not
   // supported.
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecEAC3, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecEAC3, AudioCodecProfile::kUnknown, is_spatial_rendering}));
 
   // Expect non-support for codecs with which there is no spatial audio format.
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecAAC, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecMP3, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecPCM, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecAAC, AudioCodecProfile::kUnknown, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecMP3, AudioCodecProfile::kUnknown, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecPCM, AudioCodecProfile::kUnknown, is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecVorbis, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecFLAC, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecVorbis, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecFLAC, AudioCodecProfile::kUnknown, is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecAMR_NB, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecAMR_NB, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecAMR_WB, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecAMR_WB, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecPCM_MULAW, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecPCM_MULAW, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecGSM_MS, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecGSM_MS, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecPCM_S16BE, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecPCM_S16BE, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecPCM_S24BE, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecOpus, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecPCM_S24BE, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecOpus, AudioCodecProfile::kUnknown, is_spatial_rendering}));
   EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecPCM_ALAW, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecALAC, is_spatial_rendering}));
-  EXPECT_FALSE(IsSupportedAudioType({media::kCodecAC3, is_spatial_rendering}));
-  EXPECT_FALSE(
-      IsSupportedAudioType({media::kCodecMpegHAudio, is_spatial_rendering}));
-  EXPECT_FALSE(
-      IsSupportedAudioType({media::kUnknownAudioCodec, is_spatial_rendering}));
+      IsSupportedAudioType({media::kCodecPCM_ALAW, AudioCodecProfile::kUnknown,
+                            is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecALAC, AudioCodecProfile::kUnknown, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecAC3, AudioCodecProfile::kUnknown, is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType({media::kCodecMpegHAudio,
+                                     AudioCodecProfile::kUnknown,
+                                     is_spatial_rendering}));
+  EXPECT_FALSE(IsSupportedAudioType({media::kUnknownAudioCodec,
+                                     AudioCodecProfile::kUnknown,
+                                     is_spatial_rendering}));
+}
+
+TEST(SupportedTypesTest, XHE_AACSupportedOnAndroidOnly) {
+  // TODO(dalecurtis): Update this test if we ever have support elsewhere.
+#if defined(OS_ANDROID)
+  const bool is_supported =
+      kPropCodecsEnabled &&
+      base::android::BuildInfo::GetInstance()->sdk_int() >=
+          base::android::SDK_VERSION_P;
+
+  EXPECT_EQ(is_supported,
+            IsSupportedAudioType(
+                {media::kCodecAAC, AudioCodecProfile::kXHE_AAC, false}));
+#else
+  EXPECT_FALSE(IsSupportedAudioType(
+      {media::kCodecAAC, AudioCodecProfile::kXHE_AAC, false}));
+#endif
 }
 
 }  // namespace media
diff --git a/media/base/test_data_util.cc b/media/base/test_data_util.cc
index 469be49a..d849db56 100644
--- a/media/base/test_data_util.cc
+++ b/media/base/test_data_util.cc
@@ -40,6 +40,7 @@
     "video/mp4; codecs=\"vp09.02.10.10.01.02.02.02.00\"";
 const char kMp4Vp9Video[] =
     "video/mp4; codecs=\"vp09.00.10.08.01.02.02.02.00\"";
+const char kMp4XheAacAudio[] = "audio/mp4; codecs=\"mp4a.40.42\"";
 // WebM
 const char kWebMAv110bitVideo[] = "video/webm; codecs=\"av01.0.04M.10\"";
 const char kWebMAv1Video[] = "video/webm; codecs=\"av01.0.04M.08\"";
@@ -139,6 +140,7 @@
       {"bear-vp9.webm", kWebMVp9Video},
       {"frame_size_change-av_enc-v.webm", kWebMVorbisAudioVp8Video},
       {"icy_sfx.mp3", kMp3Audio},
+      {"noise-xhe-aac.mp4", kMp4XheAacAudio},
       {"opus-trimming-test.mp4", kMp4OpusAudio},
       {"opus-trimming-test.webm", kWebMOpusAudio},
       {"sfx-flac_frag.mp4", kMp4FlacAudio},
diff --git a/media/blink/power_status_helper.h b/media/blink/power_status_helper.h
index ccc297ab..828055a 100644
--- a/media/blink/power_status_helper.h
+++ b/media/blink/power_status_helper.h
@@ -6,6 +6,7 @@
 #define MEDIA_BLINK_POWER_STATUS_HELPER_H_
 
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/time/time.h"
 #include "media/base/pipeline_metadata.h"
 #include "media/base/video_codecs.h"
@@ -24,7 +25,7 @@
   virtual void SetIsPlaying(bool is_playing) = 0;
   virtual void SetMetadata(const PipelineMetadata& metadata) = 0;
   virtual void SetIsFullscreen(bool is_fullscreen) = 0;
-  virtual void SetAverageDuration(base::TimeDelta average_duration) = 0;
+  virtual void SetAverageFrameRate(base::Optional<int> average_fps) = 0;
 
   // Handle notifications about the experiment state from the power experiment.
   // manager.  |state| indicates whether our player is eligible to record power
diff --git a/media/blink/smoothness_helper.cc b/media/blink/smoothness_helper.cc
index 76c530b..81b8ac1 100644
--- a/media/blink/smoothness_helper.cc
+++ b/media/blink/smoothness_helper.cc
@@ -13,6 +13,9 @@
 namespace {
 static constexpr base::TimeDelta kSegmentSize =
     base::TimeDelta::FromSeconds(60);
+
+// Max proportion of dropped frames in a window before we call it "not smooth".
+static constexpr float kMaxDroppedFramesPerWindow = 0.2;
 }
 
 namespace media {
@@ -21,120 +24,148 @@
 using learning::LearningTaskController;
 using learning::TargetValue;
 
-class SmoothnessHelperImpl : public SmoothnessHelper {
+// Monitor smoothness during a playback, and call back on each window.
+class SmoothnessWindowMonitor {
  public:
-  SmoothnessHelperImpl(std::unique_ptr<LearningTaskController> controller,
-                       const FeatureVector& features,
-                       Client* player)
-      : controller_(std::move(controller)),
-        features_(features),
-        player_(player) {}
+  using WindowCB = base::RepeatingCallback<void(int64_t dropped_frames,
+                                                int64_t decoded_frames)>;
+  SmoothnessWindowMonitor(SmoothnessHelper::Client* player, WindowCB cb)
+      : player_(player), cb_(std::move(cb)) {
+    segment_dropped_frames_ = player_->DroppedFrameCount();
+    segment_decoded_frames_ = player_->DecodedFrameCount();
 
-  // This will ignore the last segment, if any, which is fine since it's not
-  // a complete segment.
-  ~SmoothnessHelperImpl() override = default;
-
-  void NotifyPlayState(bool playing) override {
-    if (playing) {
-      if (segment_decoded_frames_)
-        return;
-
-      // We're starting a new playback, so record the baseline frame counts.
-      segment_dropped_frames_ = player_->DroppedFrameCount();
-      segment_decoded_frames_ = player_->DecodedFrameCount();
-      worst_segment_during_playback_ = TargetValue(0);
-
-      DCHECK(!id_);
-
-      // Don't bother to start the observation until the timer fires, since we
-      // don't wanto to record short playbacks.
-
-      update_timer_.Start(FROM_HERE, kSegmentSize,
-                          base::BindRepeating(&SmoothnessHelperImpl::OnTimer,
-                                              base::Unretained(this)));
-    } else {
-      if (!segment_decoded_frames_)
-        return;
-
-      // If we started an observation, then complete it.  Otherwise, the segment
-      // wasn't long enough.  Note that we also don't update the worst NNR
-      // rate here, so that we don't include very short partial segments that
-      // might be artificially high.  Note that this might be a bad idea; if
-      // the site detects bad playback and adapts before we've measured one
-      // segment, then we'll never record those NNRs.  We might want to allow
-      // the final segment to be smaller than |kSegmentSize|, as long as it's
-      // not too small.
-      if (id_)
-        controller_->CompleteObservation(*id_, worst_segment_during_playback_);
-
-      // End the segment and the playback.
-      segment_decoded_frames_.reset();
-      segment_dropped_frames_.reset();
-      update_timer_.Stop();
-      id_.reset();
-    }
+    update_timer_.Start(FROM_HERE, kSegmentSize,
+                        base::BindRepeating(&SmoothnessWindowMonitor::OnTimer,
+                                            base::Unretained(this)));
   }
 
+  ~SmoothnessWindowMonitor() = default;
+
   // Split playback into segments of length |kSegmentSize|, and update the
   // default value of the current playback.
   void OnTimer() {
-    DCHECK(segment_decoded_frames_);
-
     auto new_dropped_frames = player_->DroppedFrameCount();
-    auto dropped_frames = new_dropped_frames - *segment_dropped_frames_;
+    auto dropped_frames = new_dropped_frames - segment_dropped_frames_;
     segment_dropped_frames_ = new_dropped_frames;
 
     auto new_decoded_frames = player_->DecodedFrameCount();
-    auto decoded_frames = new_decoded_frames - *segment_decoded_frames_;
+    auto decoded_frames = new_decoded_frames - segment_decoded_frames_;
     segment_decoded_frames_ = new_decoded_frames;
 
     if (!decoded_frames)
       return;
 
-    // The target value is just the percentage of dropped frames.
-    auto target = TargetValue(((double)dropped_frames) / decoded_frames);
+    cb_.Run(dropped_frames, decoded_frames);
+  }
 
-    // See if this is worse than any previous segment.
-    if (target > worst_segment_during_playback_)
-      worst_segment_during_playback_ = target;
+ private:
+  SmoothnessHelper::Client* player_ = nullptr;
+  WindowCB cb_;
+  base::RepeatingTimer update_timer_;
+  // Current dropped, decoded frames at the start of the segment.
+  int64_t segment_decoded_frames_;
+  int64_t segment_dropped_frames_;
+};
 
-    // Start an observation for this playback, or update the default.
-    if (!id_) {
-      id_ = base::UnguessableToken::Create();
-      controller_->BeginObservation(*id_, features_,
-                                    worst_segment_during_playback_);
+class SmoothnessHelperImpl : public SmoothnessHelper {
+ public:
+  SmoothnessHelperImpl(
+      std::unique_ptr<LearningTaskController> consecutive_controller,
+      const FeatureVector& features,
+      Client* player)
+      : consecutive_bad_(std::move(consecutive_controller)),
+        features_(features),
+        player_(player) {
+    monitor_ = std::make_unique<SmoothnessWindowMonitor>(
+        player_, base::BindRepeating(&SmoothnessHelperImpl::OnWindow,
+                                     base::Unretained(this)));
+  }
+
+  // This will ignore the last segment, if any, which is fine since it's not
+  // a complete segment.  However, any in-progress observation will be completed
+  // with the default value if we've gotten enough data to set one.
+  ~SmoothnessHelperImpl() override = default;
+
+  // Split playback into segments of length |kSegmentSize|, and update the
+  // default value of the current playback.
+  void OnWindow(int64_t dropped_frames, int64_t decoded_frames) {
+    // Compute the percentage of dropped frames for this window.
+    double pct = (static_cast<double>(dropped_frames)) / decoded_frames;
+
+    // Once we get one full window, default to 0 for the consecutive windows
+    // prediction task.
+    if (!consecutive_bad_.is_started())
+      consecutive_bad_.UpdateObservation(features_, TargetValue(0));
+
+    // If this is a bad window, extend the run of consecutive bad windows, and
+    // update the target value if this is a new longest run.
+    if (pct >= kMaxDroppedFramesPerWindow) {
+      consecutive_bad_windows_++;
+      if (consecutive_bad_windows_ > max_consecutive_bad_windows_) {
+        max_consecutive_bad_windows_ = consecutive_bad_windows_;
+        consecutive_bad_.UpdateObservation(
+            features_, TargetValue(max_consecutive_bad_windows_));
+      }
     } else {
-      controller_->UpdateDefaultTarget(*id_, worst_segment_during_playback_);
+      consecutive_bad_windows_ = 0;
+      // Don't update the target value, since any previous target value is still
+      // the max consecutive windows.
     }
   }
 
-  // Current dropped, decoded frames at the start of the segment, if any.
-  base::Optional<int64_t> segment_decoded_frames_;
-  base::Optional<int64_t> segment_dropped_frames_;
+  // Helper for different learning tasks.
+  struct Task {
+    Task(std::unique_ptr<LearningTaskController> controller)
+        : controller_(std::move(controller)) {}
 
-  // Of all the segments in this playback, this is the worst NNR ratio.
-  TargetValue worst_segment_during_playback_;
+    ~Task() = default;
 
-  std::unique_ptr<LearningTaskController> controller_;
+    // Return true if and only if we've started an observation.
+    bool is_started() const { return !!id_; }
+
+    void UpdateObservation(const FeatureVector& features,
+                           TargetValue current_target) {
+      target_value_ = current_target;
+      if (!is_started()) {
+        id_ = base::UnguessableToken::Create();
+        controller_->BeginObservation(*id_, features, target_value_);
+      } else {
+        controller_->UpdateDefaultTarget(*id_, target_value_);
+      }
+    }
+
+    const TargetValue& target_value() const { return target_value_; }
+
+   private:
+    // If an observation is in progress, then this is the id.
+    base::Optional<base::UnguessableToken> id_;
+    std::unique_ptr<LearningTaskController> controller_;
+    TargetValue target_value_;
+
+    DISALLOW_COPY_AND_ASSIGN(Task);
+  };
+
+  // Struct to hold all of the "at least |n| consecutive bad windows" data.
+  struct Task consecutive_bad_;
+
+  int consecutive_bad_windows_ = 0;
+  int max_consecutive_bad_windows_ = 0;
 
   FeatureVector features_;
 
-  base::RepeatingTimer update_timer_;
-
   // WebMediaPlayer which will tell us about the decoded / dropped frame counts.
   Client* player_;
 
-  // If an observation is in progress, then this is the id.
-  base::Optional<base::UnguessableToken> id_;
+  std::unique_ptr<SmoothnessWindowMonitor> monitor_;
 };
 
 // static
 std::unique_ptr<SmoothnessHelper> SmoothnessHelper::Create(
-    std::unique_ptr<LearningTaskController> controller,
+    std::unique_ptr<LearningTaskController> consecutive_controller,
     const FeatureVector& features,
     Client* player) {
-  return std::make_unique<SmoothnessHelperImpl>(std::move(controller), features,
-                                                player);
+  return std::make_unique<SmoothnessHelperImpl>(
+      std::move(consecutive_controller), features, player);
 }
 
 // static
diff --git a/media/blink/smoothness_helper.h b/media/blink/smoothness_helper.h
index 02694a1..b4f302d 100644
--- a/media/blink/smoothness_helper.h
+++ b/media/blink/smoothness_helper.h
@@ -40,18 +40,10 @@
   // we create.  They should be features that could be captured at the time a
   // prediction would be needed.
   static std::unique_ptr<SmoothnessHelper> Create(
-      std::unique_ptr<learning::LearningTaskController> controller,
+      std::unique_ptr<learning::LearningTaskController> consecutive_controller,
       const learning::FeatureVector& features,
       Client* player);
 
-  // Notify us when we start or stop playing.
-  // TODO(liberato): There is an open question whether we'd like one call of
-  // the form "ThePlayerIsInTheRightStateToRecordSmoothness(bool)", or whether
-  // we'd like multiple calls to record the state of the player, like
-  // "SetIsPlaying", "SetIsBackgrounded", etc.  The difference is whether the
-  // decision to record is made by the player or by us.
-  virtual void NotifyPlayState(bool playing) = 0;
-
   // We split playbacks up into |kSegmentSize| units, and record the worst
   // dropped frame ratio over all segments of a playback.  A playback is not
   // recorded if it doesn't contain at least one full segment.
diff --git a/media/blink/smoothness_helper_unittest.cc b/media/blink/smoothness_helper_unittest.cc
index f4c9b8da..aa8cd881 100644
--- a/media/blink/smoothness_helper_unittest.cc
+++ b/media/blink/smoothness_helper_unittest.cc
@@ -73,10 +73,11 @@
 
  public:
   void SetUp() override {
-    auto ltc = std::make_unique<MockLearningTaskController>();
-    ltc_ = ltc.get();
+    auto consecutive_ltc = std::make_unique<MockLearningTaskController>();
+    consecutive_ltc_ = consecutive_ltc.get();
     features_.push_back(FeatureValue(123));
-    helper_ = SmoothnessHelper::Create(std::move(ltc), features_, &client_);
+    helper_ = SmoothnessHelper::Create(std::move(consecutive_ltc), features_,
+                                       &client_);
     segment_size_ = SmoothnessHelper::SegmentSizeForTesting();
   }
 
@@ -99,101 +100,62 @@
   // Helper under test
   std::unique_ptr<SmoothnessHelper> helper_;
 
-  MockLearningTaskController* ltc_ = nullptr;
+  MockLearningTaskController* consecutive_ltc_;
+
   MockClient client_;
   FeatureVector features_;
 
   base::TimeDelta segment_size_;
 };
 
-TEST_F(SmoothnessHelperTest, PauseWithoutPlayDoesNothing) {
-  EXPECT_CALL(*ltc_, BeginObservation(_, _, _)).Times(0);
-  helper_->NotifyPlayState(false);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(SmoothnessHelperTest, PlayThenImmediatePauseCancelsObservation) {
-  // If not enough time has elapsed, play then pause shouldn't record anything.
-  // Note that Begin then Cancel would be okay too, but it's hard to set
-  // expectations for either case.  So, we just pick the one that it actually
-  // does in this case.
-  EXPECT_CALL(*ltc_, BeginObservation(_, _, _)).Times(0);
-  helper_->NotifyPlayState(true);
-  helper_->NotifyPlayState(false);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(SmoothnessHelperTest, PlayRecordsWorstSegment) {
-  // Record three segments, and see if it chooses the worst.
+TEST_F(SmoothnessHelperTest, MaxBadWindowsRecordsTrue) {
+  // Record three bad segments, and verify that it records 'true'.
   SetFrameCounters(0, 0);
-  helper_->NotifyPlayState(true);
   base::RunLoop().RunUntilIdle();
+  int dropped_frames = 0;
+  int total_frames = 0;
 
-  // First segment has no dropped frames..
-  EXPECT_CALL(*ltc_, BeginObservation(_, _, OPT_TARGET(Eq(0.0)))).Times(1);
-  SetFrameCounters(0, 1000);
-  FastForwardBy(segment_size_);
-  base::RunLoop().RunUntilIdle();
-
-  // Second segment has quite a lot of dropped frames.
-  EXPECT_CALL(*ltc_, UpdateDefaultTarget(_, OPT_TARGET(Gt(0.99)))).Times(1);
-  SetFrameCounters(999, 2000);
-  FastForwardBy(segment_size_);
-  base::RunLoop().RunUntilIdle();
-
-  // Third segment has no dropped frames, so the default shouldn't change.
-  EXPECT_CALL(*ltc_, UpdateDefaultTarget(_, OPT_TARGET(Gt(0.99)))).Times(1);
-  SetFrameCounters(999, 3000);
-  FastForwardBy(segment_size_);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(*ltc_, CompleteObservation(_, COMPLETION_TARGET(Gt(0.99))))
+  // First segment has no dropped frames.  Should record 0.
+  EXPECT_CALL(*consecutive_ltc_, BeginObservation(_, _, OPT_TARGET(0.0)))
       .Times(1);
-  helper_->NotifyPlayState(false);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(SmoothnessHelperTest, PlayIgnoresTrailingPartialSegments) {
-  helper_->NotifyPlayState(true);
-  base::RunLoop().RunUntilIdle();
-
-  // First segment has no dropped frames.
-  EXPECT_CALL(*ltc_, BeginObservation(_, _, OPT_TARGET(Eq(0.0)))).Times(1);
-  SetFrameCounters(0, 1000);
+  SetFrameCounters(dropped_frames += 0, total_frames += 1000);
   FastForwardBy(segment_size_);
   base::RunLoop().RunUntilIdle();
+  testing::Mock::VerifyAndClearExpectations(consecutive_ltc_);
 
-  // Second segment has a lot of dropped frames, but isn't a full segment.
-  SetFrameCounters(1000, 2000);
-  FastForwardBy(segment_size_ / 2);
-  base::RunLoop().RunUntilIdle();
-
-  // On completion, we the observation should have no dropped frames.
-  EXPECT_CALL(*ltc_, CompleteObservation(_, COMPLETION_TARGET(Lt(0.1))))
+  // Second segment has a lot of dropped frames, so the target should increase.
+  EXPECT_CALL(*consecutive_ltc_, UpdateDefaultTarget(_, OPT_TARGET(1.0)))
       .Times(1);
-  helper_->NotifyPlayState(false);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(SmoothnessHelperTest, DestructionRecordsObservations) {
-  // Destroying |helper_| should not send any observation; the last default
-  // value should be used.
-  helper_->NotifyPlayState(true);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(*ltc_, BeginObservation(_, _, _)).Times(AnyNumber());
-  EXPECT_CALL(*ltc_, UpdateDefaultTarget(_, _)).Times(AnyNumber());
-  EXPECT_CALL(*ltc_, CancelObservation(_)).Times(0);
-  EXPECT_CALL(*ltc_, CompleteObservation(_, _)).Times(0);
-
-  // Fast forward so that we're sure that there is something to record.
-  SetFrameCounters(0, 1000);
+  SetFrameCounters(dropped_frames += 999, total_frames += 1000);
   FastForwardBy(segment_size_);
-  SetFrameCounters(0, 2000);
-  FastForwardBy(segment_size_);
-  helper_.reset();
-
   base::RunLoop().RunUntilIdle();
+  testing::Mock::VerifyAndClearExpectations(consecutive_ltc_);
+
+  // Third segment looks nice, so nothing should update.
+  EXPECT_CALL(*consecutive_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_)))
+      .Times(0);
+  SetFrameCounters(dropped_frames += 0, total_frames += 1000);
+  FastForwardBy(segment_size_);
+  base::RunLoop().RunUntilIdle();
+  testing::Mock::VerifyAndClearExpectations(consecutive_ltc_);
+
+  // Fourth segment has dropped frames, but the default shouldn't change.
+  // It's okay if it changes to the same value, but we just memorize that it
+  // won't change at all.
+  EXPECT_CALL(*consecutive_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_)))
+      .Times(0);
+  SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+  FastForwardBy(segment_size_);
+  base::RunLoop().RunUntilIdle();
+  testing::Mock::VerifyAndClearExpectations(consecutive_ltc_);
+
+  // The last segment is also bad, and should increase the max.
+  EXPECT_CALL(*consecutive_ltc_, UpdateDefaultTarget(_, OPT_TARGET(2.0)))
+      .Times(1);
+  SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+  FastForwardBy(segment_size_);
+  base::RunLoop().RunUntilIdle();
+  testing::Mock::VerifyAndClearExpectations(consecutive_ltc_);
 }
 
 }  // namespace media
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 6431f14..3e8fc7cb 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1828,13 +1828,8 @@
   MaybeSetContainerName();
 
   pipeline_metadata_ = metadata;
-  if (power_status_helper_) {
+  if (power_status_helper_)
     power_status_helper_->SetMetadata(metadata);
-    // TODO(liberato): This shouldn't be set here, but it'll do until we get
-    // the fps estimator.
-    power_status_helper_->SetAverageDuration(
-        base::TimeDelta::FromSecondsD(1. / 30));
-  }
 
   UMA_HISTOGRAM_ENUMERATION(
       "Media.VideoRotation",
@@ -2247,6 +2242,8 @@
 
 void WebMediaPlayerImpl::OnVideoFrameRateChange(base::Optional<int> fps) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
+  if (power_status_helper_)
+    power_status_helper_->SetAverageFrameRate(fps);
 }
 
 void WebMediaPlayerImpl::OnAudioConfigChange(const AudioDecoderConfig& config) {
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index ddce138..1f2e692 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -19,6 +19,10 @@
 #include "media/formats/mp4/box_definitions.h"
 #include "media/media_buildflags.h"
 
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+#include "media/formats/mp4/aac.h"
+#endif
+
 namespace media {
 
 namespace {
@@ -388,6 +392,18 @@
     return true;
 #endif
 
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  // TODO(dalecurtis): Just use the profile from the codec context if ffmpeg
+  // ever starts supporting xHE-AAC.
+  if (codec == kCodecAAC && codec_context->profile == FF_PROFILE_UNKNOWN) {
+    // Errors aren't fatal here, so just drop any MediaLog messages.
+    NullMediaLog media_log;
+    mp4::AAC aac_parser;
+    if (aac_parser.Parse(extra_data, &media_log))
+      config->set_profile(aac_parser.GetProfile());
+  }
+#endif
+
   // Verify that AudioConfig.bits_per_channel was calculated correctly for
   // codecs that have |sample_fmt| set by FFmpeg.
   DCHECK_EQ(av_get_bytes_per_sample(codec_context->sample_fmt) * 8,
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc
index 260f2b7..9a5c883 100644
--- a/media/filters/ffmpeg_audio_decoder.cc
+++ b/media/filters/ffmpeg_audio_decoder.cc
@@ -77,7 +77,9 @@
 
   InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
 
-  if (config.is_encrypted()) {
+  if (config.is_encrypted() ||
+      // TODO(dalecurtis): Remove this if ffmpeg ever gets xHE-AAC support.
+      config.profile() == AudioCodecProfile::kXHE_AAC) {
     std::move(bound_init_cb).Run(false);
     return;
   }
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 364e67a..8f68690 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -799,8 +799,13 @@
       break;
 #endif
     case AV_CODEC_ID_AAC:
-      bitstream_converter_.reset(
-          new FFmpegAACBitstreamConverter(stream_->codecpar));
+      // FFmpeg doesn't understand xHE-AAC profiles yet, which can't be put in
+      // ADTS anyways, so skip bitstream conversion when the profile is
+      // unknown.
+      if (audio_config_->profile() != AudioCodecProfile::kXHE_AAC) {
+        bitstream_converter_.reset(
+            new FFmpegAACBitstreamConverter(stream_->codecpar));
+      }
       break;
     default:
       break;
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc
index 08d290f..d6c9c17 100644
--- a/media/filters/ffmpeg_demuxer_unittest.cc
+++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -277,6 +277,13 @@
       demuxer_->duration_ = kInfiniteDuration;
   }
 
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  bool HasBitstreamConverter(DemuxerStream* stream) const {
+    return !!reinterpret_cast<FFmpegDemuxerStream*>(stream)
+                 ->bitstream_converter_;
+  }
+#endif
+
   // Fixture members.
 
   base::test::TaskEnvironment task_environment_;
@@ -1441,6 +1448,26 @@
   InitializeDemuxer();
 }
 
+TEST_F(FFmpegDemuxerTest, XHE_AAC) {
+  CreateDemuxer("noise-xhe-aac.mp4");
+  InitializeDemuxer();
+
+  DemuxerStream* audio = GetStream(DemuxerStream::AUDIO);
+  ASSERT_TRUE(audio);
+
+  EXPECT_EQ(audio->audio_decoder_config().profile(),
+            AudioCodecProfile::kXHE_AAC);
+
+  // ADTS bitstream conversion shouldn't be enabled for xHE-AAC since it can't
+  // be represented with only two bits for the profile.
+  audio->EnableBitstreamConverter();
+  EXPECT_FALSE(HasBitstreamConverter(audio));
+
+  // Even though FFmpeg can't decode xHE-AAC content, it should be demuxing it
+  // just fine.
+  Read(audio, FROM_HERE, 1796, 0, true);
+}
+
 #endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
 
 TEST_F(FFmpegDemuxerTest, Read_Webm_Multiple_Tracks) {
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc
index 0aaca79..4598b8e 100644
--- a/media/filters/stream_parser_factory.cc
+++ b/media/filters/stream_parser_factory.cc
@@ -140,15 +140,17 @@
 }
 
 // AAC Object Type IDs that Chrome supports.
-static const int kAACLCObjectType = 2;
-static const int kAACSBRObjectType = 5;
-static const int kAACPSObjectType = 29;
+constexpr int kAACLCObjectType = 2;
+constexpr int kAACSBRObjectType = 5;
+constexpr int kAACPSObjectType = 29;
+constexpr int kAACXHEObjectType = 42;
 
 bool ValidateMP4ACodecID(const std::string& codec_id, MediaLog* media_log) {
   int audio_object_type = GetMP4AudioObjectType(codec_id, media_log);
   if (audio_object_type == kAACLCObjectType ||
       audio_object_type == kAACSBRObjectType ||
-      audio_object_type == kAACPSObjectType) {
+      audio_object_type == kAACPSObjectType ||
+      audio_object_type == kAACXHEObjectType) {
     return true;
   }
 
diff --git a/media/formats/mp4/aac.cc b/media/formats/mp4/aac.cc
index 6590e48..ca92ff8 100644
--- a/media/formats/mp4/aac.cc
+++ b/media/formats/mp4/aac.cc
@@ -17,6 +17,8 @@
 namespace media {
 namespace mp4 {
 
+constexpr uint8_t kXHeAAcType = 42;
+
 AAC::AAC()
     : profile_(0), frequency_index_(0), channel_config_(0), frequency_(0),
       extension_frequency_(0), channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED) {
@@ -46,6 +48,14 @@
 
   // Read base configuration
   RCHECK(reader.ReadBits(5, &profile_));
+
+  // Signals that we need more than 5 bits for profile.
+  if (profile_ == 31) {
+    uint8_t tmp;
+    RCHECK(reader.ReadBits(6, &tmp));
+    profile_ = 32 + tmp;
+  }
+
   RCHECK(reader.ReadBits(4, &frequency_index_));
   if (frequency_index_ == 0xf)
     RCHECK(reader.ReadBits(24, &frequency_));
@@ -68,10 +78,10 @@
   // value of profile_ must now reflect the the underlying profile being used
   // with those extensions (these extensions are supported).
   // 1 = AAC main, 2 = AAC LC, 3 = AAC SSR, 4 = AAC LTP
-  if (profile_ < 1 || profile_ > 4) {
-    MEDIA_LOG(ERROR, media_log) << "Audio codec(mp4a.40."
-                                << static_cast<int>(profile_)
-                                << ") is not supported.";
+  if ((profile_ < 1 || profile_ > 4) && profile_ != kXHeAAcType) {
+    MEDIA_LOG(ERROR, media_log)
+        << "Audio codec(mp4a.40." << static_cast<int>(profile_)
+        << ") is not supported.";
     return false;
   }
 
@@ -176,6 +186,11 @@
 }
 
 bool AAC::ConvertEsdsToADTS(std::vector<uint8_t>* buffer) const {
+  // Don't append ADTS header for XHE-AAC; it doesn't have enough bits to signal
+  // the correct profile.
+  if (profile_ == kXHeAAcType)
+    return true;
+
   size_t size = buffer->size() + kADTSHeaderMinSize;
 
   DCHECK(profile_ >= 1 && profile_ <= 4 && frequency_index_ != 0xf &&
@@ -190,8 +205,8 @@
   adts.insert(buffer->begin(), kADTSHeaderMinSize, 0);
   adts[0] = 0xff;
   adts[1] = 0xf1;
-  adts[2] = ((profile_ - 1) << 6) + (frequency_index_ << 2) +
-      (channel_config_ >> 2);
+  adts[2] =
+      ((profile_ - 1) << 6) + (frequency_index_ << 2) + (channel_config_ >> 2);
   adts[3] = static_cast<uint8_t>(((channel_config_ & 0x3) << 6) + (size >> 11));
   adts[4] = static_cast<uint8_t>((size & 0x7ff) >> 3);
   adts[5] = ((size & 7) << 5) + 0x1f;
@@ -200,6 +215,11 @@
   return true;
 }
 
+AudioCodecProfile AAC::GetProfile() const {
+  return profile_ == kXHeAAcType ? AudioCodecProfile::kXHE_AAC
+                                 : AudioCodecProfile::kUnknown;
+}
+
 // Currently this function only support GASpecificConfig defined in
 // ISO 14496-3:2009 Table 4.1 - Syntax of GASpecificConfig()
 bool AAC::SkipDecoderGASpecificConfig(BitReader* bit_reader) const {
@@ -216,6 +236,7 @@
     case 21:
     case 22:
     case 23:
+    case kXHeAAcType:
       return SkipGASpecificConfig(bit_reader);
     default:
       break;
diff --git a/media/formats/mp4/aac.h b/media/formats/mp4/aac.h
index b6244ab..3fa403b 100644
--- a/media/formats/mp4/aac.h
+++ b/media/formats/mp4/aac.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "build/build_config.h"
+#include "media/base/audio_codecs.h"
 #include "media/base/channel_layout.h"
 #include "media/base/media_export.h"
 #include "media/base/media_log.h"
@@ -56,6 +57,9 @@
   // unchanged.
   bool ConvertEsdsToADTS(std::vector<uint8_t>* buffer) const;
 
+  // If known, returns the AudioCodecProfile.
+  AudioCodecProfile GetProfile() const;
+
 #if defined(OS_ANDROID)
   // Returns the codec specific data needed by android MediaCodec.
   std::vector<uint8_t> codec_specific_data() const {
diff --git a/media/formats/mp4/aac_unittest.cc b/media/formats/mp4/aac_unittest.cc
index e328dc0..5afee41 100644
--- a/media/formats/mp4/aac_unittest.cc
+++ b/media/formats/mp4/aac_unittest.cc
@@ -68,6 +68,7 @@
   EXPECT_TRUE(Parse(data));
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 44100);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 }
 
 TEST_F(AACTest, ExtensionTest) {
@@ -80,6 +81,7 @@
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 48000);
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(true), 48000);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 }
 
 // Test implicit SBR with mono channel config.
@@ -97,10 +99,12 @@
   // Test w/o implict SBR.
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 24000);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_MONO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 
   // Test implicit SBR.
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(true), 48000);
   EXPECT_EQ(aac_.GetChannelLayout(true), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 }
 
 // Tests implicit SBR with a stereo channel config.
@@ -115,10 +119,12 @@
   // Test w/o implict SBR.
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 24000);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 
   // Test implicit SBR.
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(true), 48000);
   EXPECT_EQ(aac_.GetChannelLayout(true), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 }
 
 TEST_F(AACTest, SixChannelTest) {
@@ -130,6 +136,7 @@
   EXPECT_TRUE(Parse(data));
   EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 48000);
   EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_5_1_BACK);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kUnknown);
 }
 
 TEST_F(AACTest, DataTooShortTest) {
@@ -236,6 +243,25 @@
   EXPECT_TRUE(Parse(data));
 }
 
+TEST_F(AACTest, XHE_AAC) {
+  InSequence s;
+  uint8_t buffer[] = {0xf9, 0x46, 0x43, 0x22, 0x2c, 0xc0, 0x4c, 0x00,
+                      0x85, 0xa0, 0x01, 0x13, 0x84, 0x00, 0x20, 0x00,
+                      0x02, 0x50, 0x01, 0x19, 0x72, 0xc0, 0x00};
+  std::vector<uint8_t> data;
+  data.assign(buffer, buffer + sizeof(buffer));
+
+  EXPECT_TRUE(Parse(data));
+  EXPECT_EQ(aac_.GetOutputSamplesPerSecond(false), 48000);
+  EXPECT_EQ(aac_.GetChannelLayout(false), CHANNEL_LAYOUT_STEREO);
+  EXPECT_EQ(aac_.GetProfile(), AudioCodecProfile::kXHE_AAC);
+
+  // ADTS conversion should do nothing since xHE-AAC can't be represented with
+  // only two bits for the profile.
+  EXPECT_TRUE(aac_.ConvertEsdsToADTS(&data));
+  EXPECT_EQ(data.size(), sizeof(buffer));
+}
+
 }  // namespace mp4
 
 }  // namespace media
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc
index 19617fe5..6fa01d7 100644
--- a/media/formats/mp4/mp4_stream_parser.cc
+++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -365,6 +365,7 @@
       }
 
       AudioCodec codec = kUnknownAudioCodec;
+      AudioCodecProfile profile = AudioCodecProfile::kUnknown;
       ChannelLayout channel_layout = CHANNEL_LAYOUT_NONE;
       int sample_per_second = 0;
       int codec_delay_in_frames = 0;
@@ -423,6 +424,7 @@
         if (ESDescriptor::IsAAC(audio_type)) {
           const AAC& aac = entry.esds.aac;
           codec = kCodecAAC;
+          profile = aac.GetProfile();
           channel_layout = aac.GetChannelLayout(has_sbr_);
           sample_per_second = aac.GetOutputSamplesPerSecond(has_sbr_);
 #if defined(OS_ANDROID)
@@ -478,8 +480,10 @@
       audio_config.Initialize(codec, sample_format, channel_layout,
                               sample_per_second, extra_data, scheme,
                               seek_preroll, codec_delay_in_frames);
-      if (codec == kCodecAAC)
+      if (codec == kCodecAAC) {
         audio_config.disable_discard_decoder_delay();
+        audio_config.set_profile(profile);
+      }
 
       DVLOG(1) << "audio_track_id=" << audio_track_id
                << " config=" << audio_config.AsHumanReadableString();
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc
index 134d485..c04a2c8 100644
--- a/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -401,6 +401,22 @@
   params.detected_video_track_count = 0;
   InitializeParserWithInitParametersExpectations(params);
   ParseMP4File("bear-mpeg2-aac-only_frag.mp4", 512);
+  EXPECT_EQ(audio_decoder_config_.profile(), AudioCodecProfile::kUnknown);
+}
+
+TEST_F(MP4StreamParserTest, MPEG4_XHE_AAC) {
+  InSequence s;
+  std::set<int> audio_object_types;
+  audio_object_types.insert(kISO_14496_3);
+  parser_.reset(new MP4StreamParser(audio_object_types, false, false));
+  auto params = GetDefaultInitParametersExpectations();
+  params.duration = base::TimeDelta::FromMicroseconds(1024000);
+  params.liveness = DemuxerStream::LIVENESS_RECORDED;
+  params.detected_video_track_count = 0;
+
+  InitializeParserWithInitParametersExpectations(params);
+  ParseMP4File("noise-xhe-aac.mp4", 512);
+  EXPECT_EQ(audio_decoder_config_.profile(), AudioCodecProfile::kXHE_AAC);
 }
 
 // Test that a moov box is not always required after Flush() is called.
diff --git a/media/gpu/h264_decoder.cc b/media/gpu/h264_decoder.cc
index acc8898..62c42d9 100644
--- a/media/gpu/h264_decoder.cc
+++ b/media/gpu/h264_decoder.cc
@@ -1127,7 +1127,12 @@
 
   if (!sps->gaps_in_frame_num_value_allowed_flag) {
     DVLOG(1) << "Invalid frame_num: " << frame_num;
-    return false;
+    // TODO(b:129119729, b:146914440): Youtube android app sometimes sends an
+    // invalid frame number after a seek. The sequence goes like:
+    // Seek, SPS, PPS, IDR-frame, non-IDR, ... non-IDR with invalid number.
+    // The only way to work around this reliably is to ignore this error.
+    // Video playback is not affected, no artefacts are visible.
+    // return false;
   }
 
   DVLOG(2) << "Handling frame_num gap: " << prev_ref_frame_num_ << "->"
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc
index 624f9f91..bf37b582 100644
--- a/media/gpu/v4l2/v4l2_device.cc
+++ b/media/gpu/v4l2/v4l2_device.cc
@@ -1051,7 +1051,9 @@
     switch (errno) {
       case EAGAIN:
       case EPIPE:
-        // This is not an error but won't provide a buffer either.
+        // This is not an error so we'll need to continue polling but won't
+        // provide a buffer.
+        device_->SchedulePoll();
         return std::make_pair(true, nullptr);
       default:
         VPQLOGF(1) << "VIDIOC_DQBUF failed";
@@ -1943,6 +1945,15 @@
   return requests_queue_.get();
 }
 
+bool V4L2Device::IsCtrlExposed(uint32_t ctrl_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
+
+  struct v4l2_queryctrl query_ctrl {};
+  query_ctrl.id = ctrl_id;
+
+  return Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0;
+}
+
 class V4L2Request {
  public:
   // Apply the passed controls to the request.
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h
index 8681f75d..5dedd0a 100644
--- a/media/gpu/v4l2/v4l2_device.h
+++ b/media/gpu/v4l2/v4l2_device.h
@@ -690,6 +690,9 @@
   // the queue creation failed or if requests are not supported.
   V4L2RequestsQueue* GetRequestsQueue();
 
+  // Check whether the V4L2 control with specified |ctrl_id| is supported.
+  bool IsCtrlExposed(uint32_t ctrl_id);
+
  protected:
   friend class base::RefCountedThreadSafe<V4L2Device>;
   V4L2Device();
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 777c61cd..eee0792 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -1494,15 +1494,6 @@
   return true;
 }
 
-bool V4L2VideoEncodeAccelerator::IsCtrlExposed(uint32_t ctrl_id) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
-
-  struct v4l2_queryctrl query_ctrl{};
-  query_ctrl.id = ctrl_id;
-
-  return device_->Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0;
-}
-
 bool V4L2VideoEncodeAccelerator::SetExtCtrls(
     std::vector<struct v4l2_ext_control> ctrls) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
@@ -1537,7 +1528,7 @@
 #endif
     // Request to inject SPS and PPS before each IDR, if the device supports
     // that feature. Otherwise we'll have to cache and inject ourselves.
-    if (IsCtrlExposed(V4L2_CID_MPEG_VIDEO_H264_SPS_PPS_BEFORE_IDR)) {
+    if (device_->IsCtrlExposed(V4L2_CID_MPEG_VIDEO_H264_SPS_PPS_BEFORE_IDR)) {
       memset(&ctrl, 0, sizeof(ctrl));
       ctrl.id = V4L2_CID_MPEG_VIDEO_H264_SPS_PPS_BEFORE_IDR;
       ctrl.value = 1;
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
index c913a69f..a4b91c66 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -233,10 +233,6 @@
   // Set controls in |ctrls| and return true if successful.
   bool SetExtCtrls(std::vector<struct v4l2_ext_control> ctrls);
 
-  // Return true if a V4L2 control of |ctrl_id| is supported by the device,
-  // false otherwise.
-  bool IsCtrlExposed(uint32_t ctrl_id);
-
   // Allocates |count| video frames with |visible_size| for image processor's
   // output buffers. Returns false if there's something wrong.
   bool AllocateImageProcessorOutputBuffers(size_t count,
diff --git a/media/learning/common/value.cc b/media/learning/common/value.cc
index fcaeed8..757a8b3 100644
--- a/media/learning/common/value.cc
+++ b/media/learning/common/value.cc
@@ -47,6 +47,10 @@
   return value_ > rhs.value_;
 }
 
+bool Value::operator>=(const Value& rhs) const {
+  return value_ >= rhs.value_;
+}
+
 std::ostream& operator<<(std::ostream& out, const Value& value) {
   return out << value.value_;
 }
diff --git a/media/learning/common/value.h b/media/learning/common/value.h
index 160d2aa9..1b7e3db1 100644
--- a/media/learning/common/value.h
+++ b/media/learning/common/value.h
@@ -48,6 +48,7 @@
   bool operator!=(const Value& rhs) const;
   bool operator<(const Value& rhs) const;
   bool operator>(const Value& rhs) const;
+  bool operator>=(const Value& rhs) const;
 
   double value() const { return value_; }
 
diff --git a/media/learning/common/value_unittest.cc b/media/learning/common/value_unittest.cc
index 91be729..8306875 100644
--- a/media/learning/common/value_unittest.cc
+++ b/media/learning/common/value_unittest.cc
@@ -39,11 +39,14 @@
   Value v2(i1);
   Value v3(i2);
   EXPECT_TRUE(v1 == v2);
+  EXPECT_TRUE(v1 >= v2);
   EXPECT_TRUE(v1 != v3);
   EXPECT_TRUE(v1 < v3);
+  EXPECT_FALSE(v1 >= v3);
   EXPECT_FALSE(v3 < v1);
   EXPECT_FALSE(v3 < v3);
   EXPECT_FALSE(v1 < v1);
+  EXPECT_TRUE(v1 >= v1);
   EXPECT_TRUE(v3 > v1);
   EXPECT_FALSE(v1 > v3);
   EXPECT_FALSE(v1 > v1);
diff --git a/media/mojo/mojom/audio_decoder_config_mojom_traits.cc b/media/mojo/mojom/audio_decoder_config_mojom_traits.cc
index 0aaae3d..fad4b8c1 100644
--- a/media/mojo/mojom/audio_decoder_config_mojom_traits.cc
+++ b/media/mojo/mojom/audio_decoder_config_mojom_traits.cc
@@ -37,14 +37,15 @@
   if (!input.ReadSeekPreroll(&seek_preroll))
     return false;
 
+  media::AudioCodecProfile profile;
+  if (!input.ReadProfile(&profile))
+    return false;
+
   output->Initialize(codec, sample_format, channel_layout,
                      input.samples_per_second(), extra_data, encryption_scheme,
                      seek_preroll, input.codec_delay());
-
-  if (!output->IsValidConfig())
-    return false;
-
-  return true;
+  output->set_profile(profile);
+  return output->IsValidConfig();
 }
 
 }  // namespace mojo
diff --git a/media/mojo/mojom/audio_decoder_config_mojom_traits.h b/media/mojo/mojom/audio_decoder_config_mojom_traits.h
index c95d33a..60aaca7 100644
--- a/media/mojo/mojom/audio_decoder_config_mojom_traits.h
+++ b/media/mojo/mojom/audio_decoder_config_mojom_traits.h
@@ -50,6 +50,11 @@
     return input.encryption_scheme();
   }
 
+  static media::AudioCodecProfile profile(
+      const media::AudioDecoderConfig& input) {
+    return input.profile();
+  }
+
   static bool Read(media::mojom::AudioDecoderConfigDataView input,
                    media::AudioDecoderConfig* output);
 };
diff --git a/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc b/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc
index 16ea462..ccbca0289 100644
--- a/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc
+++ b/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc
@@ -58,4 +58,19 @@
   EXPECT_TRUE(output.Matches(input));
 }
 
+TEST(AudioDecoderConfigStructTraitsTest,
+     ConvertAudioDecoderConfig_WithPorilfe) {
+  AudioDecoderConfig input;
+  input.Initialize(kCodecAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND, 48000,
+                   EmptyExtraData(), EncryptionScheme::kUnencrypted,
+                   base::TimeDelta(), 0);
+  input.set_profile(AudioCodecProfile::kXHE_AAC);
+  std::vector<uint8_t> data =
+      media::mojom::AudioDecoderConfig::Serialize(&input);
+  AudioDecoderConfig output;
+  EXPECT_TRUE(
+      media::mojom::AudioDecoderConfig::Deserialize(std::move(data), &output));
+  EXPECT_TRUE(output.Matches(input));
+}
+
 }  // namespace media
diff --git a/media/mojo/mojom/media_types.mojom b/media/mojo/mojom/media_types.mojom
index aa82c11..f220a9eba 100644
--- a/media/mojo/mojom/media_types.mojom
+++ b/media/mojo/mojom/media_types.mojom
@@ -15,6 +15,8 @@
 // See media/base/audio_codecs.h for descriptions.
 [Native]
 enum AudioCodec;
+[Native]
+enum AudioCodecProfile;
 
 // See media/base/buffering_state.h for descriptions.
 [Native]
@@ -141,6 +143,7 @@
 // See media/base/audio_decoder_config.h for descriptions.
 struct AudioDecoderConfig {
   AudioCodec codec;
+  AudioCodecProfile profile;
   SampleFormat sample_format;
   ChannelLayout channel_layout;
   int32 samples_per_second;
diff --git a/media/mojo/mojom/media_types.typemap b/media/mojo/mojom/media_types.typemap
index dd2eab00..e8ed773 100644
--- a/media/mojo/mojom/media_types.typemap
+++ b/media/mojo/mojom/media_types.typemap
@@ -44,6 +44,7 @@
 
 type_mappings = [
   "media.mojom.AudioCodec=::media::AudioCodec",
+  "media.mojom.AudioCodecProfile=::media::AudioCodecProfile",
   "media.mojom.BufferingState=::media::BufferingState",
   "media.mojom.BufferingStateChangeReason=::media::BufferingStateChangeReason",
   "media.mojom.ChannelLayout=::media::ChannelLayout",
diff --git a/media/test/data/README.md b/media/test/data/README.md
index 910d5e9..8f08323 100644
--- a/media/test/data/README.md
+++ b/media/test/data/README.md
@@ -46,8 +46,15 @@
 Just the first initialization segment of bear-1280x720_av_frag.mp4, modified to
 have the mvhd version 0 32-bit duration field set to all 1's.
 
-#### media/test/data/negative-audio-timestamps.avi
-A truncated audio/video file with audio packet timestamps of -1. We need to ensure that these packets arent dropped.
+#### negative-audio-timestamps.avi
+A truncated audio/video file with audio packet timestamps of -1. We need to ensure that these packets aren't dropped.
+
+#### noise-xhe-aac.mp4
+Fragmented mp4 of noise encoded with xHE-AAC, from xHE-AAC samples in [Android
+CTS](https://android.googlesource.com/platform/cts/+/master/tests/tests/media/res/raw)
+```
+ffmpeg -i noise_2ch_48khz_aot42_19_lufs_mp4.m4a -acodec copy -t 1 noise-xhe-aac.mp4
+```
 
 ### FLAC
 
diff --git a/media/test/data/noise-xhe-aac.mp4 b/media/test/data/noise-xhe-aac.mp4
new file mode 100644
index 0000000..5e25c544
--- /dev/null
+++ b/media/test/data/noise-xhe-aac.mp4
Binary files differ
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index e560dd4..dc50a2b5 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -712,107 +712,107 @@
   // semantics:
   std::vector<IncludeForRequestURLTestCase> common_test_cases = {
       // Strict cookies:
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=1;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=2;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=3;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT)},
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=4;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=5;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_SECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Strict", CookieSameSite::STRICT_MODE,
+      {"Common=6;SameSite=Strict", CookieSameSite::STRICT_MODE,
        CookieEffectiveSameSite::STRICT_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_INSECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
       // Lax cookies:
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=7;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=8;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX)},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=9;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=10;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=11;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_LAX_CROSS_SCHEME_SECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=12;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_SECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=13;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_LAX_CROSS_SCHEME_INSECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=Lax", CookieSameSite::LAX_MODE,
+      {"Common=14;SameSite=Lax", CookieSameSite::LAX_MODE,
        CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_INSECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
       // None and Secure cookies:
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=15;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=19;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_LAX_CROSS_SCHEME_SECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=20;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_SECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=21;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_LAX_CROSS_SCHEME_INSECURE_URL,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2; SameSite=None; Secure", CookieSameSite::NO_RESTRICTION,
+      {"Common=22;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::
            SAME_SITE_STRICT_CROSS_SCHEME_INSECURE_URL,
@@ -822,7 +822,7 @@
   // semantics is UNKNOWN and feature is enabled):
   std::vector<IncludeForRequestURLTestCase> default_none_test_cases = {
       // Unspecified cookies (without SameSite-by-default):
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultNone=1", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
@@ -830,7 +830,7 @@
                CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultNone=2", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
@@ -838,11 +838,11 @@
                CanonicalCookie::CookieInclusionStatus::ExclusionReason>(),
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultNone=3", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus()},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultNone=4", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::NO_RESTRICTION,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus()}};
@@ -851,7 +851,7 @@
   // or access semantics is UNKNOWN and feature is enabled):
   std::vector<IncludeForRequestURLTestCase> default_lax_test_cases = {
       // Unspecified recently-created cookies (with SameSite-by-default):
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultLax=1", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus(
@@ -860,7 +860,7 @@
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kShortAge},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultLax=2", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
@@ -869,16 +869,17 @@
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE),
        kShortAge},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultLax=3", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus(), kShortAge},
-      {"A=2", CookieSameSite::UNSPECIFIED,
+      {"DefaultLax=4", CookieSameSite::UNSPECIFIED,
        CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus(), kShortAge},
       // Unspecified not-recently-created cookies (with SameSite-by-default):
-      {"A=2", CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
+      {"DefaultLax=5", CookieSameSite::UNSPECIFIED,
+       CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::CROSS_SITE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::
@@ -886,7 +887,8 @@
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kLongAge},
-      {"A=2", CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
+      {"DefaultLax=6", CookieSameSite::UNSPECIFIED,
+       CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX_METHOD_UNSAFE,
        CanonicalCookie::CookieInclusionStatus(
            CanonicalCookie::CookieInclusionStatus::
@@ -894,10 +896,12 @@
            CanonicalCookie::CookieInclusionStatus::
                WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
        kLongAge},
-      {"A=2", CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
+      {"DefaultLax=7", CookieSameSite::UNSPECIFIED,
+       CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_LAX,
        CanonicalCookie::CookieInclusionStatus(), kLongAge},
-      {"A=2", CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
+      {"DefaultLax=8", CookieSameSite::UNSPECIFIED,
+       CookieEffectiveSameSite::LAX_MODE,
        CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT,
        CanonicalCookie::CookieInclusionStatus(), kLongAge},
   };
diff --git a/services/network/origin_policy/origin_policy_parser.cc b/services/network/origin_policy/origin_policy_parser.cc
index 62cf8cd8..f00df11d 100644
--- a/services/network/origin_policy/origin_policy_parser.cc
+++ b/services/network/origin_policy/origin_policy_parser.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/optional.h"
 #include "base/values.h"
 #include "services/network/public/cpp/isolation_opt_in_hints.h"
 #include "url/gurl.h"
@@ -19,30 +20,26 @@
 
 OriginPolicyContentsPtr OriginPolicyParser::Parse(base::StringPiece text) {
   OriginPolicyParser parser;
-  if (!parser.DoParse(text))
-    return std::make_unique<OriginPolicyContents>();
+  parser.DoParse(text);
   return std::move(parser.policy_contents_);
 }
 
-OriginPolicyParser::OriginPolicyParser() {}
-OriginPolicyParser::~OriginPolicyParser() {}
+OriginPolicyParser::OriginPolicyParser() = default;
+OriginPolicyParser::~OriginPolicyParser() = default;
 
-bool OriginPolicyParser::DoParse(base::StringPiece policy_contents_text) {
-  if (policy_contents_text.empty())
-    return false;
-
-  std::unique_ptr<base::Value> json =
-      base::JSONReader::ReadDeprecated(policy_contents_text);
-  if (!json || !json->is_dict())
-    return false;
-
+void OriginPolicyParser::DoParse(base::StringPiece policy_contents_text) {
   policy_contents_ = std::make_unique<OriginPolicyContents>();
 
-  base::Value* csp = json->FindListKey("content-security-policy");
-  bool csp_ok = !csp || ParseContentSecurityPolicies(*csp);
+  base::Optional<base::Value> json =
+      base::JSONReader::Read(policy_contents_text);
+  if (!json || !json->is_dict())
+    return;
 
-  base::Value* features = json->FindDictKey("features");
-  if (features) {
+  if (base::Value* content_security = json->FindDictKey("content_security")) {
+    ParseContentSecurity(*content_security);
+  }
+
+  if (base::Value* features = json->FindDictKey("features")) {
     ParseFeatures(*features);
   }
 
@@ -53,33 +50,30 @@
   } else if (base::Value* isolation = json->FindDictKey("isolation")) {
     ParseIsolation(*isolation);
   }
-
-  return csp_ok;
 }
 
-bool OriginPolicyParser::ParseContentSecurityPolicies(
-    const base::Value& policies) {
-  bool ok = true;
-  for (const auto& csp : policies.GetList()) {
-    ok &= csp.is_dict() && ParseContentSecurityPolicy(csp);
-  }
-  return ok;
-}
-
-bool OriginPolicyParser::ParseContentSecurityPolicy(const base::Value& csp) {
-  const std::string* policy = csp.FindStringKey("policy");
-  if (!policy)
-    return false;
-
-  const base::Optional<bool> report_only = csp.FindBoolKey("report-only");
-
-  if (report_only.has_value() && report_only.value()) {
-    policy_contents_->content_security_policies_report_only.push_back(*policy);
-  } else {
-    policy_contents_->content_security_policies.push_back(*policy);
+void OriginPolicyParser::ParseContentSecurity(
+    const base::Value& content_security) {
+  const base::Value* policies = content_security.FindListKey("policies");
+  if (policies) {
+    for (const auto& policy : policies->GetList()) {
+      if (policy.is_string()) {
+        policy_contents_->content_security_policies.push_back(
+            policy.GetString());
+      }
+    }
   }
 
-  return true;
+  const base::Value* policies_report_only =
+      content_security.FindListKey("policies_report_only");
+  if (policies_report_only) {
+    for (const auto& policy : policies_report_only->GetList()) {
+      if (policy.is_string()) {
+        policy_contents_->content_security_policies_report_only.push_back(
+            policy.GetString());
+      }
+    }
+  }
 }
 
 void OriginPolicyParser::ParseFeatures(const base::Value& features) {
diff --git a/services/network/origin_policy/origin_policy_parser.h b/services/network/origin_policy/origin_policy_parser.h
index 2535cd56..3e960210 100644
--- a/services/network/origin_policy/origin_policy_parser.h
+++ b/services/network/origin_policy/origin_policy_parser.h
@@ -18,31 +18,20 @@
 
 namespace network {
 
+// https://wicg.github.io/origin-policy/#parsing
 class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyParser {
  public:
   // Parse the given origin policy. Returns an empty policy if parsing is not
   // successful.
-  // TODO(vogelheim): Decide how parsing errors should be handled.
   static OriginPolicyContentsPtr Parse(base::StringPiece);
 
  private:
   OriginPolicyParser();
   ~OriginPolicyParser();
 
-  // The older spec treated parsing errors as failures that would cause an
-  // interstitial, so we have a boolean return value to represent that. The
-  // newer spec does not treat parsing errors as failures; see
-  // https://github.com/WICG/origin-policy/issues/49.
-  // TODO(domenic): update everything to the newer spec and remove all boolean
-  // return values.
+  void DoParse(base::StringPiece);
 
-  bool DoParse(base::StringPiece);
-
-  // The following methods are implemented according to the older spec:
-  bool ParseContentSecurityPolicies(const base::Value&);
-  bool ParseContentSecurityPolicy(const base::Value&);
-
-  // The following methods are implemented according to the newer spec:
+  void ParseContentSecurity(const base::Value&);
   void ParseFeatures(const base::Value&);
   void ParseIsolation(const base::Value&);
 
diff --git a/services/network/origin_policy/origin_policy_parser_unittest.cc b/services/network/origin_policy/origin_policy_parser_unittest.cc
index 01b10d2..6ec5c3d 100644
--- a/services/network/origin_policy/origin_policy_parser_unittest.cc
+++ b/services/network/origin_policy/origin_policy_parser_unittest.cc
@@ -19,6 +19,7 @@
 void AssertEmptyPolicy(
     const network::OriginPolicyContentsPtr& policy_contents) {
   ASSERT_FALSE(policy_contents->feature_policy.has_value());
+  ASSERT_FALSE(policy_contents->isolation_optin_hints.has_value());
   ASSERT_EQ(0u, policy_contents->content_security_policies.size());
   ASSERT_EQ(0u, policy_contents->content_security_policies_report_only.size());
 }
@@ -37,6 +38,17 @@
   AssertEmptyPolicy(policy_contents);
 }
 
+TEST(OriginPolicyParser, InvalidString) {
+  auto policy_contents = OriginPolicyParser::Parse("\"potato potato potato\"");
+  AssertEmptyPolicy(policy_contents);
+}
+
+TEST(OriginPolicyParser, InvalidArray) {
+  auto policy_contents =
+      OriginPolicyParser::Parse("[\"potato potato potato\"]");
+  AssertEmptyPolicy(policy_contents);
+}
+
 TEST(OriginPolicyParser, ValidButEmpty) {
   auto policy_contents = OriginPolicyParser::Parse("{}");
   AssertEmptyPolicy(policy_contents);
@@ -44,24 +56,21 @@
 
 TEST(OriginPolicyParser, SimpleCSP) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self' 'unsafe-inline'"
-      }] }
+      { "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline'"]
+      } }
   )");
   ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
   ASSERT_EQ(policy_contents->content_security_policies[0],
             "script-src 'self' 'unsafe-inline'");
 }
 
-TEST(OriginPolicyParser, DoubleCSP) {
+TEST(OriginPolicyParser, CSPIncludingReportOnly) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self' 'unsafe-inline'",
-          "report-only": false
-        },{
-          "policy": "script-src 'self' 'https://example.com/'",
-          "report-only": true
-      }] }
+      { "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline'"],
+          "policies_report_only": ["script-src 'self' 'https://example.com/'"]
+      } }
   )");
   ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
   ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
@@ -72,87 +81,173 @@
             "script-src 'self' 'https://example.com/'");
 }
 
-TEST(OriginPolicyParser, HalfDoubleCSP) {
+TEST(OriginPolicyParser, CSPMultiItemArrays) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self' 'unsafe-inline'",
-        },{
-          "policies": "script-src 'self' 'https://example.com/'",
-      }] }
+      { "content_security": {
+          "policies": [
+            "script-src 'self' 'unsafe-inline'",
+            "frame-ancestors 'none'",
+            "object-src 'none'"
+          ],
+          "policies_report_only": [
+            "script-src 'self' 'https://example.com/'",
+            "object-src 'none'"
+          ]
+      } }
   )");
-  AssertEmptyPolicy(policy_contents);
+  ASSERT_EQ(policy_contents->content_security_policies.size(), 3U);
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 2U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0],
+            "script-src 'self' 'unsafe-inline'");
+  ASSERT_EQ(policy_contents->content_security_policies[1],
+            "frame-ancestors 'none'");
+  ASSERT_EQ(policy_contents->content_security_policies[2], "object-src 'none'");
+
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
+            "script-src 'self' 'https://example.com/'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[1],
+            "object-src 'none'");
+}
+
+TEST(OriginPolicyParser, CSPTwoContentSecurity) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": {
+          "policies": ["frame-ancestors 'none'", "object-src 'none'"],
+          "policies_report_only": ["script-src 'self' https://cdn.example.com/js/"]
+      }, "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline'"],
+          "policies_report_only": ["script-src 'self' 'https://example.com/'"]
+      } }
+  )");
+  ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0],
+            "script-src 'self' 'unsafe-inline'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
+            "script-src 'self' 'https://example.com/'");
+}
+
+TEST(OriginPolicyParser, CSPTwoContentSecurityNoReportOnly) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline'"]
+      },
+      "content_security": {
+          "policies": ["img-src 'none'"]
+      } }
+  )");
+  ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 0U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0], "img-src 'none'");
+}
+
+TEST(OriginPolicyParser, CSPTwoPolicies) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": {
+          "policies": ["frame-ancestors 'none'", "object-src 'none'"],
+          "policies": ["script-src 'self' 'unsafe-inline'"],
+          "policies_report_only": ["script-src 'self' https://cdn.example.com/js/"],
+          "policies_report_only": ["script-src 'self' 'https://example.com/'"]
+      } }
+  )");
+  ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0],
+            "script-src 'self' 'unsafe-inline'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
+            "script-src 'self' 'https://example.com/'");
 }
 
 TEST(OriginPolicyParser, CSPWithoutCSP) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "police": "script-src 'self' 'unsafe-inline'",
-          "report-only": false
-        }] }
+      { "content_security": {
+          "police": ["frame-ancestors 'none'", "object-src 'none'"]
+      } }
   )");
   AssertEmptyPolicy(policy_contents);
 }
 
 TEST(OriginPolicyParser, ExtraFieldsDontBreakParsing) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "potatoes": "are better than kale",
-        "content-security-policy": [{
-          "report-only": false,
-          "potatoes": "are best",
-          "policy": "script-src 'self' 'unsafe-inline'"
-        }],
-        "other": {
-          "name": "Sieglinde",
-          "value": "best of potatoes"
-      }}
+      { "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline'"],
+          "policies_report_only": ["script-src 'self' 'https://example.com/'"],
+          "potatoes": "are best"
+      } }
   )");
   ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
+
   ASSERT_EQ(policy_contents->content_security_policies[0],
             "script-src 'self' 'unsafe-inline'");
-}
-
-TEST(OriginPolicyParser, CSPDispositionEnforce) {
-  auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self'",
-          "report-only": false
-        }] }
-  )");
-  ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
-  ASSERT_EQ(policy_contents->content_security_policies[0], "script-src 'self'");
-}
-
-TEST(OriginPolicyParser, CSPDispositionReport) {
-  auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self'",
-          "report-only": true
-        }] }
-  )");
-  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
   ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
-            "script-src 'self'");
+            "script-src 'self' 'https://example.com/'");
 }
 
-TEST(OriginPolicyParser, CSPDispositionInvalid) {
+// At this level we don't validate the syntax, so commas get passed through.
+// Integration tests will show that comma-containing policies get discarded,
+// though.
+TEST(OriginPolicyParser, CSPComma) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self'",
-          "report-only": "potato"
-        }] }
+      { "content_security": {
+          "policies": ["script-src 'self' 'unsafe-inline', script-src 'self' 'https://example.com/'"],
+          "policies_report_only": ["script-src 'self' 'https://example.com/', frame-ancestors 'none', object-src 'none'"]
+      } }
   )");
+
   ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
-  ASSERT_EQ(policy_contents->content_security_policies[0], "script-src 'self'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0],
+            "script-src 'self' 'unsafe-inline', script-src 'self' "
+            "'https://example.com/'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
+            "script-src 'self' 'https://example.com/', frame-ancestors 'none', "
+            "object-src 'none'");
 }
 
-TEST(OriginPolicyParser, CSPDispositionAbsent) {
+// Similarly, complete garbage will be passed through; this is expected.
+TEST(OriginPolicyParser, CSPGarbage) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
-      { "content-security-policy": [{
-          "policy": "script-src 'self'"
-        }] }
+      { "content_security": {
+          "policies": ["potato potato potato"],
+          "policies_report_only": ["tomato tomato tomato"]
+      } }
   )");
+
   ASSERT_EQ(policy_contents->content_security_policies.size(), 1U);
-  ASSERT_EQ(policy_contents->content_security_policies[0], "script-src 'self'");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only.size(), 1U);
+
+  ASSERT_EQ(policy_contents->content_security_policies[0],
+            "potato potato potato");
+  ASSERT_EQ(policy_contents->content_security_policies_report_only[0],
+            "tomato tomato tomato");
+}
+
+TEST(OriginPolicyParser, CSPNonDict) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": "script-src 'self' 'unsafe-inline'"
+      } )");
+  AssertEmptyPolicy(policy_contents);
+}
+
+TEST(OriginPolicyParser, CSPNonArray) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": { "policies": "script-src 'self' 'unsafe-inline'" }
+      } )");
+  AssertEmptyPolicy(policy_contents);
+}
+
+TEST(OriginPolicyParser, CSPNonString) {
+  auto policy_contents = OriginPolicyParser::Parse(R"(
+      { "content_security": { "policies":
+        [["script-src 'self' 'unsafe-inline'"]]
+      } } )");
+  AssertEmptyPolicy(policy_contents);
 }
 
 TEST(OriginPolicyParser, FeatureOne) {
@@ -220,14 +315,14 @@
   auto policy_contents = OriginPolicyParser::Parse(R"(
       { "features": "geolocation 'self' http://maps.google.com"
       } )");
-  ASSERT_FALSE(policy_contents->feature_policy.has_value());
+  AssertEmptyPolicy(policy_contents);
 }
 
 TEST(OriginPolicyParser, FeatureNonString) {
   auto policy_contents = OriginPolicyParser::Parse(R"(
       { "features": { "policy": ["geolocation 'self' http://maps.google.com"]
       } )");
-  ASSERT_FALSE(policy_contents->feature_policy.has_value());
+  AssertEmptyPolicy(policy_contents);
 }
 
 namespace {
diff --git a/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc b/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
index d5dba27..97064ee 100644
--- a/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
@@ -19,7 +19,7 @@
   // constraints explicitly disable serializing images using the transfer cache
   // and serialization of PaintRecords.
   cc::PaintOp::SerializeOptions options(nullptr, nullptr, nullptr, nullptr,
-                                        nullptr, nullptr, false, false, 0, 0.f,
+                                        nullptr, nullptr, false, false, 0,
                                         SkMatrix::I());
   cc::PaintOpWriter writer(memory.data(), memory.size(), options,
                            true /* enable_security_constraints */);
diff --git a/sql/database.cc b/sql/database.cc
index 7f7bcd2a..5535cd1 100644
--- a/sql/database.cc
+++ b/sql/database.cc
@@ -217,7 +217,7 @@
     // TODO(paivanof@gmail.com): This should move to the beginning
     // of the function. http://crbug.com/136655.
     base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-    InitScopedBlockingCall(&scoped_blocking_call);
+    InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
     sqlite3_finalize(stmt_);
     stmt_ = nullptr;
   }
@@ -309,9 +309,9 @@
     // TODO(paivanof@gmail.com): This should move to the beginning
     // of the function. http://crbug.com/136655.
     base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-    InitScopedBlockingCall(&scoped_blocking_call);
+    InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
-    // Reseting acquires a lock to ensure no dump is happening on the database
+    // Resetting acquires a lock to ensure no dump is happening on the database
     // at the same time. Unregister takes ownership of provider and it is safe
     // since the db is reset. memory_dump_provider_ could be null if db_ was
     // poisoned.
@@ -353,7 +353,7 @@
   }
 
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   // Maximum number of bytes that will be prefetched from the database.
   //
@@ -636,7 +636,7 @@
 
 size_t Database::GetAppropriateMmapSize() {
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   // How much to map if no errors are found.  50MB encompasses the 99th
   // percentile of Chrome databases in the wild, so this should be good.
@@ -777,7 +777,7 @@
 // size, then backup that database over the existing database.
 bool Database::Raze() {
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   if (!db_) {
     DCHECK(poisoned_) << "Cannot raze null db";
@@ -1079,7 +1079,7 @@
   }
 
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   int rc = SQLITE_OK;
   while ((rc == SQLITE_OK) && *sql) {
@@ -1198,7 +1198,7 @@
     return base::MakeRefCounted<StatementRef>(nullptr, nullptr, poisoned_);
 
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   // TODO(pwnall): Cached statements (but not unique statements) should be
   //               prepared with prepFlags set to SQLITE_PREPARE_PERSISTENT.
@@ -1247,7 +1247,7 @@
 
 bool Database::IsSQLValid(const char* sql) {
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
   if (!db_) {
     DCHECK(poisoned_) << "Illegal use of Database without a db";
     return false;
@@ -1352,7 +1352,7 @@
   }
 
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  InitScopedBlockingCall(&scoped_blocking_call);
+  InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   EnsureSqliteInitialized();
 
diff --git a/sql/database.h b/sql/database.h
index ccb1dad..18ccdcd 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -129,7 +129,7 @@
   // histogram is recorded.
   void AddTaggedHistogram(const std::string& name, int sample) const;
 
-  // Track various API calls and results.  Values corrospond to UMA
+  // Track various API calls and results.  Values correspond to UMA
   // histograms, do not modify, or add or delete other than directly
   // before EVENT_MAX_VALUE.
   enum Events {
@@ -520,11 +520,13 @@
   void CloseInternal(bool forced);
 
   // Construct a ScopedBlockingCall to annotate IO calls, but only if
-  // database wasn't open in memory.
+  // database wasn't open in memory. ScopedBlockingCall uses |from_here| to
+  // declare its blocking execution scope (see https://www.crbug/934302).
   void InitScopedBlockingCall(
+      const base::Location& from_here,
       base::Optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
     if (!in_memory_)
-      scoped_blocking_call->emplace(FROM_HERE, base::BlockingType::MAY_BLOCK);
+      scoped_blocking_call->emplace(from_here, base::BlockingType::MAY_BLOCK);
   }
 
   // Internal helper for Does*Exist() functions.
@@ -588,11 +590,13 @@
     void Close(bool forced);
 
     // Construct a ScopedBlockingCall to annotate IO calls, but only if
-    // database wasn't open in memory.
+    // database wasn't open in memory. ScopedBlockingCall uses |from_here| to
+    // declare its blocking execution scope (see https://www.crbug/934302).
     void InitScopedBlockingCall(
+        const base::Location& from_here,
         base::Optional<base::ScopedBlockingCall>* scoped_blocking_call) const {
       if (database_)
-        database_->InitScopedBlockingCall(scoped_blocking_call);
+        database_->InitScopedBlockingCall(from_here, scoped_blocking_call);
     }
 
    private:
diff --git a/sql/statement.cc b/sql/statement.cc
index 372b2894..b49e47b 100644
--- a/sql/statement.cc
+++ b/sql/statement.cc
@@ -58,7 +58,7 @@
     return SQLITE_ERROR;
 
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  ref_->InitScopedBlockingCall(&scoped_blocking_call);
+  ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
 
   stepped_ = true;
   int ret = sqlite3_step(ref_->stmt());
@@ -76,7 +76,7 @@
 
 void Statement::Reset(bool clear_bound_vars) {
   base::Optional<base::ScopedBlockingCall> scoped_blocking_call;
-  ref_->InitScopedBlockingCall(&scoped_blocking_call);
+  ref_->InitScopedBlockingCall(FROM_HERE, &scoped_blocking_call);
   if (is_valid()) {
     if (clear_bound_vars)
       sqlite3_clear_bindings(ref_->stmt());
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 89bc4cec..fc73c0f 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -31,9 +31,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 3
         },
         "trigger_script": {
@@ -77,9 +77,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -124,9 +124,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 4
         },
         "trigger_script": {
@@ -169,9 +169,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 4
         },
         "trigger_script": {
@@ -215,9 +215,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -260,9 +260,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index cb9f3ec..5c7288d 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -32,9 +32,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 16
         },
         "trigger_script": {
@@ -78,9 +78,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 16
         },
         "trigger_script": {
@@ -124,9 +124,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 12
         },
         "trigger_script": {
@@ -170,9 +170,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 4
         },
         "trigger_script": {
@@ -215,9 +215,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 4
         },
         "trigger_script": {
@@ -257,9 +257,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -281,9 +281,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -305,9 +305,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -329,9 +329,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -353,9 +353,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -377,9 +377,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -401,9 +401,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -425,9 +425,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       }
     ]
@@ -462,9 +462,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 19
         },
         "trigger_script": {
@@ -507,9 +507,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 13
         },
         "trigger_script": {
@@ -553,9 +553,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 35
         },
         "trigger_script": {
@@ -598,9 +598,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 4
         },
         "trigger_script": {
@@ -643,9 +643,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 21
         },
         "trigger_script": {
@@ -685,9 +685,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -709,9 +709,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -733,9 +733,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -757,9 +757,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -781,9 +781,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -805,9 +805,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       },
       {
@@ -829,9 +829,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800
+          "io_timeout": 21600
         }
       }
     ]
@@ -867,9 +867,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -905,9 +905,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -943,9 +943,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -981,9 +981,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -1019,9 +1019,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -1057,9 +1057,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -1099,9 +1099,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 26
         },
         "trigger_script": {
@@ -1141,9 +1141,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -1179,9 +1179,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 1
         },
         "trigger_script": {
@@ -1221,9 +1221,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 26
         },
         "trigger_script": {
@@ -1267,9 +1267,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 26
         },
         "trigger_script": {
@@ -1318,9 +1318,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 26
         },
         "trigger_script": {
@@ -1363,9 +1363,9 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 19800,
+          "hard_timeout": 21600,
           "ignore_task_failure": false,
-          "io_timeout": 19800,
+          "io_timeout": 21600,
           "shards": 26
         },
         "trigger_script": {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 53af653..c2402dd 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -851,6 +851,18 @@
     "label": "//google_apis:google_apis_unittests",
     "type": "console_test_launcher",
   },
+  "gpu_perftests": {
+    "args": [
+      "gpu_perftests",
+      "--non-telemetry=true",
+      "--adb-path",
+      "src/third_party/android_sdk/public/platform-tools/adb",
+    ],
+    "label": "//gpu:gpu_perftests",
+    "skip_usage_check": True,  # Used by Pinpoint: crbug.com/1042778
+    "script": "//testing/scripts/run_performance_tests.py",
+    "type": "script",
+  },
   "gpu_unittests": {
     "label": "//gpu:gpu_unittests",
     "type": "windowed_test_launcher",
diff --git a/third_party/blink/common/feature_policy/document_policy.cc b/third_party/blink/common/feature_policy/document_policy.cc
index 9a19a27..1d81d81 100644
--- a/third_party/blink/common/feature_policy/document_policy.cc
+++ b/third_party/blink/common/feature_policy/document_policy.cc
@@ -226,17 +226,8 @@
 bool DocumentPolicy::IsFeatureEnabled(
     mojom::FeaturePolicyFeature feature) const {
   mojom::PolicyValueType feature_type = GetFeatureDefaults().at(feature).Type();
-  // TODO(iclelland): Generate this switch block
-  switch (feature) {
-    case mojom::FeaturePolicyFeature::kFontDisplay:
-      return font_display_;
-    case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
-      return PolicyValue(unoptimized_lossless_images_) >=
-             PolicyValue::CreateMaxPolicyValue(feature_type);
-    default:
-      NOTREACHED();
-      return true;
-  }
+  return IsFeatureEnabled(feature,
+                          PolicyValue::CreateMaxPolicyValue(feature_type));
 }
 
 bool DocumentPolicy::IsFeatureEnabled(
@@ -247,16 +238,7 @@
 
 PolicyValue DocumentPolicy::GetFeatureValue(
     mojom::FeaturePolicyFeature feature) const {
-  // TODO(iclelland): Generate this switch block
-  switch (feature) {
-    case mojom::FeaturePolicyFeature::kFontDisplay:
-      return PolicyValue(font_display_);
-    case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
-      return PolicyValue(unoptimized_lossless_images_);
-    default:
-      NOTREACHED();
-      return PolicyValue(false);
-  }
+  return internal_feature_state_[static_cast<size_t>(feature)];
 }
 
 bool DocumentPolicy::IsFeatureSupported(
@@ -273,30 +255,11 @@
 
 void DocumentPolicy::UpdateFeatureState(const FeatureState& feature_state) {
   for (const auto& feature_and_value : feature_state) {
-    // TODO(iclelland): Generate this switch block
-    switch (feature_and_value.first) {
-      case mojom::FeaturePolicyFeature::kFontDisplay:
-        font_display_ = feature_and_value.second.BoolValue();
-        break;
-      case mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages:
-        unoptimized_lossless_images_ = feature_and_value.second.DoubleValue();
-        break;
-      default:
-        NOTREACHED();
-    }
+    internal_feature_state_[static_cast<size_t>(feature_and_value.first)] =
+        feature_and_value.second;
   }
 }
 
-DocumentPolicy::FeatureState DocumentPolicy::GetFeatureState() const {
-  FeatureState feature_state;
-  // TODO(iclelland): Generate this block
-  feature_state[mojom::FeaturePolicyFeature::kFontDisplay] =
-      PolicyValue(font_display_);
-  feature_state[mojom::FeaturePolicyFeature::kUnoptimizedLosslessImages] =
-      PolicyValue(unoptimized_lossless_images_);
-  return feature_state;
-}
-
 DocumentPolicy::DocumentPolicy(const FeatureState& defaults) {
   UpdateFeatureState(defaults);
 }
diff --git a/third_party/blink/public/common/feature_policy/document_policy.h b/third_party/blink/public/common/feature_policy/document_policy.h
index 8e84cea..af222ec 100644
--- a/third_party/blink/public/common/feature_policy/document_policy.h
+++ b/third_party/blink/public/common/feature_policy/document_policy.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/feature_policy/policy_value.h"
-#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-forward.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"
 #include "third_party/blink/public/mojom/feature_policy/policy_value.mojom.h"
 
 namespace blink {
@@ -88,11 +88,6 @@
   // Returns the value of the given feature on the given origin.
   PolicyValue GetFeatureValue(mojom::FeaturePolicyFeature feature) const;
 
-  // Returns the current threshold values assigned to all document policies.
-  // the declared header policy as well as any unadvertised required policies
-  // (such as sandbox policies).
-  FeatureState GetFeatureState() const;
-
   // Returns true if the incoming policy is compatible with the given required
   // policy, i.e. incoming policy is at least as strict as required policy.
   static bool IsPolicyCompatible(const FeatureState& required_policy,
@@ -124,11 +119,10 @@
 
   void UpdateFeatureState(const FeatureState& feature_state);
 
-  // Threshold values for each defined feature.
-  // TODO(iclelland): Generate these members; pack booleans in bitfields if
-  // possible.
-  bool font_display_ = true;
-  double unoptimized_lossless_images_ = std::numeric_limits<double>::infinity();
+  // Internal feature state is represented as an array to avoid overhead
+  // in using container classes.
+  PolicyValue internal_feature_state_
+      [static_cast<size_t>(mojom::FeaturePolicyFeature::kMaxValue) + 1];
 
   DISALLOW_COPY_AND_ASSIGN(DocumentPolicy);
 };
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 53bb637..e4e5e2ee 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -6,6 +6,7 @@
 
 import "cc/mojom/touch_action.mojom";
 import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/content_security_policy.mojom";
 import "skia/public/mojom/skcolor.mojom";
 import "third_party/blink/public/mojom/devtools/console_message.mojom";
@@ -284,4 +285,9 @@
   // user activation state in appropriate part of the frame tree (ancestors for
   // activation notification and all nodes for consumption).
   UpdateUserActivationState(blink.mojom.UserActivationUpdateType state_update_type);
+
+  // Sent to the process that owns this frame's HTMLFrameOwnerElement to
+  // set the embedding token. This token uniquely specifies the relationship
+  // between a frame and its parent.
+  SetEmbeddingToken(mojo_base.mojom.UnguessableToken embedding_token);
 };
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 461e157..a51479a5 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -9,6 +9,8 @@
 #include <set>
 
 #include "base/callback.h"
+#include "base/optional.h"
+#include "base/unguessable_token.h"
 #include "services/network/public/mojom/fetch_api.mojom-shared.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/frame/sandbox_flags.h"
@@ -202,6 +204,17 @@
                         bool animate,
                         base::OnceClosure on_finish) = 0;
 
+  // Sets an embedding token for the frame. This token is propagated to the
+  // remote parent of this frame (via the browser) such that it can uniquely
+  // refer to this frame.
+  virtual void SetEmbeddingToken(
+      const base::UnguessableToken& embedding_token) = 0;
+
+  // Returns the embedding token for this frame or nullopt if it isn't embedded.
+  // This is the token that the remote parent of this frame uses to uniquely
+  // identify it.
+  virtual const base::Optional<base::UnguessableToken>& GetEmbeddingToken() = 0;
+
   // Navigation Ping --------------------------------------------------------
 
   virtual void SendPings(const WebURL& destination_url) = 0;
diff --git a/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index 926fc05..b102701 100644
--- a/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -42,6 +42,7 @@
             generated_webcore_testing_idl_files
   if (use_v8_bind_gen_for_dictionary) {
     sources -= core_dictionary_idl_files
+    sources -= core_testing_dictionary_idl_files
   }
   output_dir = bindings_core_v8_output_dir
   output_name_suffix = ""
diff --git a/third_party/blink/renderer/bindings/core/v8/generated.gni b/third_party/blink/renderer/bindings/core/v8/generated.gni
index d10a47e..41826fd6 100644
--- a/third_party/blink/renderer/bindings/core/v8/generated.gni
+++ b/third_party/blink/renderer/bindings/core/v8/generated.gni
@@ -209,23 +209,32 @@
 
 if (use_v8_bind_gen_for_dictionary) {
   generated_core_dictionary_files +=
-      process_file_template(core_dictionary_idl_files,
-                            [
-                              "{{source_gen_dir}}/{{source_name_part}}.cc",
-                              "{{source_gen_dir}}/{{source_name_part}}.h",
-                            ])
+      process_file_template(
+          core_dictionary_idl_files,
+          [
+            "$bindings_core_v8_output_dir/v8_{{source_name_part}}.cc",
+            "$bindings_core_v8_output_dir/v8_{{source_name_part}}.h",
+          ])
+
+  generated_core_testing_dictionary_files =
+      process_file_template(
+          core_testing_dictionary_idl_files,
+          [
+            "$bindings_core_v8_output_dir/v8_{{source_name_part}}.cc",
+            "$bindings_core_v8_output_dir/v8_{{source_name_part}}.h",
+          ])
 
   # Generated file from demonstration_and_testing.idl, which won't be compiled.
   generated_demo_files += [
-    "$bindings_scripts_output_dir/web_idl/example_dictionary.cc",
-    "$bindings_scripts_output_dir/web_idl/example_dictionary.h",
+    "$bindings_core_v8_output_dir/v8_example_dictionary.cc",
+    "$bindings_core_v8_output_dir/v8_example_dictionary.h",
   ]
+} else {
+  generated_core_testing_dictionary_files =
+      process_file_template(
+          core_testing_dictionary_idl_files,
+          [
+            "$blink_core_output_dir/testing/{{source_name_part}}.cc",
+            "$blink_core_output_dir/testing/{{source_name_part}}.h",
+          ])
 }
-
-generated_core_testing_dictionary_files =
-    process_file_template(
-        core_testing_dictionary_idl_files,
-        [
-          "$blink_core_output_dir/testing/{{source_name_part}}.cc",
-          "$blink_core_output_dir/testing/{{source_name_part}}.h",
-        ])
diff --git a/third_party/blink/renderer/bindings/modules/v8/generated.gni b/third_party/blink/renderer/bindings/modules/v8/generated.gni
index 33e9f7a..e4785a9 100644
--- a/third_party/blink/renderer/bindings/modules/v8/generated.gni
+++ b/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -173,9 +173,10 @@
 
 if (use_v8_bind_gen_for_dictionary) {
   generated_modules_dictionary_files +=
-      process_file_template(modules_dictionary_idl_files,
-                            [
-                              "{{source_gen_dir}}/{{source_name_part}}.cc",
-                              "{{source_gen_dir}}/{{source_name_part}}.h",
-                            ])
+      process_file_template(
+          modules_dictionary_idl_files,
+          [
+            "$bindings_modules_v8_output_dir/v8_{{source_name_part}}.cc",
+            "$bindings_modules_v8_output_dir/v8_{{source_name_part}}.h",
+          ])
 }
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
index 14d2b82..d1b2de27 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_utils.py
@@ -154,8 +154,6 @@
     for type_def_obj in type_def_objs:
         if isinstance(type_def_obj, web_idl.Enumeration):
             continue
-        if isinstance(type_def_obj, web_idl.Dictionary):
-            header_paths.add(PathManager(type_def_obj).dict_path(ext="h"))
         header_paths.add(PathManager(type_def_obj).api_path(ext="h"))
 
     return header_paths
@@ -188,9 +186,6 @@
             header_paths.add(
                 "third_party/blink/renderer/platform/heap/handle.h")
             type_def_obj = idl_type.type_definition_object
-            # TODO(crbug.com/1034398): Remove this hack
-            if idl_type.is_dictionary:
-                header_paths.add(PathManager(type_def_obj).dict_path(ext="h"))
             header_paths.add(PathManager(type_def_obj).api_path(ext="h"))
         elif (idl_type.is_sequence or idl_type.is_frozen_array
               or idl_type.is_variadic or idl_type.is_record):
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
index 33517319..16a444a 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -614,8 +614,8 @@
         base_class_name=base_class_name)
 
     # Filepaths
-    header_path = path_manager.dict_path(ext="h")
-    source_path = path_manager.dict_path(ext="cc")
+    header_path = path_manager.api_path(ext="h")
+    source_path = path_manager.api_path(ext="cc")
 
     # Root nodes
     header_node = ListNode(tail="\n")
@@ -634,10 +634,7 @@
 
     # Header part (copyright, include directives, and forward declarations)
     if dictionary.inherited:
-        # TODO(crbug.com/1034398): Use api_path() or impl_path() once we
-        # migrate IDL compiler and move generated code of dictionaries.
-        base_class_header = PathManager(
-            dictionary.inherited).dict_path(ext="h")
+        base_class_header = PathManager(dictionary.inherited).api_path(ext="h")
     else:
         base_class_header = (
             "third_party/blink/renderer/platform/bindings/dictionary_base.h")
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
index 4459b89..dc5e1ca 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
@@ -76,15 +76,6 @@
     def __init__(self, idl_definition):
         assert self._is_initialized, self._REQUIRE_INIT_MESSAGE
 
-        if isinstance(idl_definition, web_idl.Dictionary):
-            idl_path = PathManager.relpath_to_project_root(
-                posixpath.normpath(
-                    idl_definition.debug_info.location.filepath))
-            idl_basepath, _ = posixpath.splitext(idl_path)
-            self._idl_dir, _ = posixpath.split(idl_basepath)
-        else:
-            self._idl_dir = None
-
         components = sorted(idl_definition.components)  # "core" < "modules"
 
         if len(components) == 0:
@@ -95,7 +86,7 @@
             default_component = web_idl.Component("core")
             self._api_component = default_component
             self._impl_component = default_component
-        if len(components) == 1:
+        elif len(components) == 1:
             component = components[0]
             self._is_cross_components = False
             self._api_component = component
@@ -113,8 +104,6 @@
         self._impl_dir = self._component_reldirs[self._impl_component]
         self._v8_bind_basename = name_style.file("v8",
                                                  idl_definition.identifier)
-        self._blink_basename = name_style.file(
-            blink_class_name(idl_definition))
 
     @property
     def is_cross_components(self):
@@ -148,14 +137,6 @@
             filename=(filename or self._v8_bind_basename),
             ext=ext)
 
-    # TODO(crbug.com/1034398): Remove this API
-    def dict_path(self, filename=None, ext=None):
-        assert self._idl_dir is not None
-        return self._join(
-            dirpath=self._idl_dir,
-            filename=(filename or self._blink_basename),
-            ext=ext)
-
     @staticmethod
     def _join(dirpath, filename, ext=None):
         if ext is not None:
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 268495d..dbbd48b 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -69,6 +69,7 @@
     "checking",
     "click",
     "close",
+    "closing",
     "complete",
     "compositionend",
     "compositionstart",
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index f7536b08..b2649f5 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1842,6 +1842,18 @@
   return *local_frame_host_remote_.get();
 }
 
+void LocalFrame::SetEmbeddingToken(
+    const base::UnguessableToken& embedding_token) {
+  DCHECK(Tree().Parent());
+  DCHECK(Tree().Parent()->IsRemoteFrame());
+  embedding_token_ = embedding_token;
+}
+
+const base::Optional<base::UnguessableToken>& LocalFrame::GetEmbeddingToken()
+    const {
+  return embedding_token_;
+}
+
 void LocalFrame::GetTextSurroundingSelection(
     uint32_t max_length,
     GetTextSurroundingSelectionCallback callback) {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 3e8bfef..da804f1 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -460,6 +460,9 @@
   void SetPrescientNetworkingForTesting(
       std::unique_ptr<WebPrescientNetworking> prescient_networking);
 
+  void SetEmbeddingToken(const base::UnguessableToken& embedding_token);
+  const base::Optional<base::UnguessableToken>& GetEmbeddingToken() const;
+
   // blink::mojom::LocalFrame overrides:
   void GetTextSurroundingSelection(
       uint32_t max_length,
@@ -609,6 +612,8 @@
 
   std::unique_ptr<FrameOverlay> frame_color_overlay_;
 
+  base::Optional<base::UnguessableToken> embedding_token_;
+
   mojom::FrameLifecycleState lifecycle_state_;
   base::Optional<mojom::FrameLifecycleState> pending_lifecycle_state_;
 
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index e408449..191fdfa 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -392,6 +392,12 @@
   }
 }
 
+void RemoteFrame::SetEmbeddingToken(
+    const base::UnguessableToken& embedding_token) {
+  FrameOwner* owner = Owner();
+  To<HTMLFrameOwnerElement>(owner)->SetEmbeddingToken(embedding_token);
+}
+
 bool RemoteFrame::IsIgnoredForHitTest() const {
   HTMLFrameOwnerElement* owner = DeprecatedLocalOwner();
   if (!owner || !owner->GetLayoutObject())
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h
index e348b8c1..59f45f18 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -109,6 +109,8 @@
       ui::input_types::ScrollGranularity granularity) override;
   void UpdateUserActivationState(
       mojom::blink::UserActivationUpdateType) override;
+  void SetEmbeddingToken(
+      const base::UnguessableToken& embedding_token) override;
 
  private:
   // Frame protected overrides:
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 3de275c6..b847224 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
@@ -2098,6 +2098,16 @@
   return true;
 }
 
+void WebLocalFrameImpl::SetEmbeddingToken(
+    const base::UnguessableToken& embedding_token) {
+  frame_->SetEmbeddingToken(embedding_token);
+}
+
+const base::Optional<base::UnguessableToken>&
+WebLocalFrameImpl::GetEmbeddingToken() {
+  return frame_->GetEmbeddingToken();
+}
+
 void WebLocalFrameImpl::SendPings(const WebURL& destination_url) {
   DCHECK(GetFrame());
   if (Node* node = ContextMenuNodeInner()) {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 8e28c1d..8eedb5b 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -125,6 +125,9 @@
   bool ScrollTo(const gfx::Point& scrollPosition,
                 bool animate,
                 base::OnceClosure on_finish) override;
+  void SetEmbeddingToken(
+      const base::UnguessableToken& embedding_token) override;
+  const base::Optional<base::UnguessableToken>& GetEmbeddingToken() override;
   void SendPings(const WebURL& destination_url) override;
   void StartReload(WebFrameLoadType) override;
   void StartNavigation(const WebURLRequest&) override;
diff --git a/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc b/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
index b4e3c3b4..ad6d6a6e 100644
--- a/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
@@ -200,7 +200,11 @@
 }
 
 bool BaseTemporalInputType::ValueMissing(const String& value) const {
-  return GetElement().IsRequired() && value.IsEmpty();
+  // For text-mode input elements (including dates), the value is missing only
+  // if it is mutable.
+  // https://html.spec.whatwg.org/multipage/input.html#the-required-attribute
+  return GetElement().IsRequired() && value.IsEmpty() &&
+         !GetElement().IsDisabledOrReadOnly();
 }
 
 bool BaseTemporalInputType::MayTriggerVirtualKeyboard() const {
diff --git a/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc b/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
index d27648c..ed5f449 100644
--- a/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
+++ b/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.cc
@@ -54,12 +54,8 @@
       popup_(nullptr),
       locale_(Locale::DefaultLocale()) {}
 
-ColorChooserPopupUIController::~ColorChooserPopupUIController() = default;
-
-void ColorChooserPopupUIController::Dispose() {
-  // Finalized earlier so as to access chrome_client_ while alive.
-  CancelPopup();
-  // ~ColorChooserUIController calls EndChooser().
+ColorChooserPopupUIController::~ColorChooserPopupUIController() {
+  DCHECK(!popup_);
 }
 
 void ColorChooserPopupUIController::Trace(Visitor* visitor) {
diff --git a/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h b/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
index 736b8697..ca194f1 100644
--- a/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
+++ b/third_party/blink/renderer/core/html/forms/color_chooser_popup_ui_controller.h
@@ -39,8 +39,6 @@
 class CORE_EXPORT ColorChooserPopupUIController final
     : public ColorChooserUIController,
       public PagePopupClient {
-  USING_PRE_FINALIZER(ColorChooserPopupUIController, Dispose);
-
  public:
   ColorChooserPopupUIController(LocalFrame*,
                                 ChromeClient*,
@@ -69,7 +67,6 @@
   ChromeClient& GetChromeClient() override;
 
   void OpenPopup();
-  void Dispose();
 
   void WriteColorPickerDocument(SharedBuffer*);
   void WriteColorSuggestionPickerDocument(SharedBuffer*);
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc
index 1ea89ad9..f2a45b2c 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1654,9 +1654,8 @@
     client->DidChooseColor(color);
 }
 
-void HTMLInputElement::EndColorChooser() {
-  if (ColorChooserClient* client = input_type_->GetColorChooserClient())
-    client->DidEndChooser();
+void HTMLInputElement::EndColorChooserForTesting() {
+  input_type_view_->ClosePopupView();
 }
 
 HTMLElement* HTMLInputElement::list() const {
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h
index 508dde07..b045f20 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -261,7 +261,7 @@
 
   // For test purposes.
   void SelectColorInColorChooser(const Color&);
-  void EndColorChooser();
+  void EndColorChooserForTesting();
 
   String DefaultToolTip() const override;
 
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
index cb4cce7..ca49b44 100644
--- a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -511,7 +511,10 @@
 }
 
 bool HTMLTextAreaElement::ValueMissing(const String* value) const {
-  return IsRequiredFormControl() && (value ? *value : this->value()).IsEmpty();
+  // For textarea elements, the value is missing only if it is mutable.
+  // https://html.spec.whatwg.org/multipage/form-elements.html#attr-textarea-required
+  return IsRequiredFormControl() && !IsDisabledOrReadOnly() &&
+         (value ? *value : this->value()).IsEmpty();
 }
 
 bool HTMLTextAreaElement::TooLong() const {
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
index 43a626f..f6a2789 100644
--- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -134,7 +134,10 @@
 }
 
 bool TextFieldInputType::ValueMissing(const String& value) const {
-  return GetElement().IsRequired() && value.IsEmpty();
+  // For text-mode input elements, the value is missing only if it is mutable.
+  // https://html.spec.whatwg.org/multipage/input.html#the-required-attribute
+  return GetElement().IsRequired() && value.IsEmpty() &&
+         !GetElement().IsDisabledOrReadOnly();
 }
 
 bool TextFieldInputType::CanSetSuggestedValue() {
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index a24e05d..503e38f 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -225,6 +225,7 @@
 
   DCHECK_EQ(content_frame_->Owner(), this);
   content_frame_ = nullptr;
+  embedding_token_ = base::nullopt;
 
   for (ContainerNode* node = this; node; node = node->ParentOrShadowHostNode())
     node->DecrementConnectedSubframeCount();
@@ -562,6 +563,13 @@
   }
 }
 
+void HTMLFrameOwnerElement::SetEmbeddingToken(
+    const base::UnguessableToken& embedding_token) {
+  DCHECK(content_frame_);
+  DCHECK(content_frame_->IsRemoteFrame());
+  embedding_token_ = embedding_token;
+}
+
 void HTMLFrameOwnerElement::Trace(Visitor* visitor) {
   visitor->Trace(content_frame_);
   visitor->Trace(embedded_content_view_);
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h
index c6d50ff..27c4c96 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -46,6 +46,7 @@
 class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
                                           public FrameOwner {
   USING_GARBAGE_COLLECTED_MIXIN(HTMLFrameOwnerElement);
+
  public:
   ~HTMLFrameOwnerElement() override;
 
@@ -126,6 +127,11 @@
 
   void ParseAttribute(const AttributeModificationParams&) override;
 
+  void SetEmbeddingToken(const base::UnguessableToken& token);
+  const base::Optional<base::UnguessableToken>& GetEmbeddingToken() const {
+    return embedding_token_;
+  }
+
   void Trace(Visitor*) override;
 
  protected:
@@ -192,6 +198,7 @@
   Member<Frame> content_frame_;
   Member<EmbeddedContentView> embedded_content_view_;
   FramePolicy frame_policy_;
+  base::Optional<base::UnguessableToken> embedding_token_;
 
   Member<LazyLoadFrameObserver> lazy_load_frame_observer_;
   bool should_lazy_load_children_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
index 229af34..2ba9550 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -180,17 +180,48 @@
   LayoutUnit block_size = fragment_geometry.border_box_size.block_size;
   bool is_initial_block_size_indefinite = block_size == kIndefiniteSize;
   if (is_initial_block_size_indefinite) {
-    // The intrinsic size of column flex-boxes can depend on the
-    // %-resolution-block-size. This occurs when a flex-box has "max-height:
-    // 100%" or similar on itself.
-    //
-    // Due to this we can't use cached |NGLayoutResult::IntrinsicBlockSize|
-    // value, as the following |block_size| calculation would be incorrect.
-    if (node.IsFlexibleBox() && style.ResolvedIsColumnFlexDirection() &&
-        layout_result.PhysicalFragment().DependsOnPercentageBlockSize()) {
-      if (new_space.PercentageResolutionBlockSize() !=
-          old_space.PercentageResolutionBlockSize())
+    if (node.IsFlexibleBox()) {
+      // Flex-boxes can have their children calculate their size based in their
+      // parent's final block-size. E.g.
+      // <div style="display: flex;">
+      //   <div style="display: flex;">
+      //     <!-- Child will stretch to the parent's fixed block-size -->
+      //     <div></div>
+      //   </div>
+      // </div>
+      // <div style="display: flex;">
+      //   <div style="display: flex; flex-direction: column;">
+      //     <!-- Child will grow to the parent's fixed block-size -->
+      //     <div style="flex: 1;"></div>
+      //   </div>
+      // </div>
+      //
+      // If the previous |layout_result| was produced by a space which had a
+      // fixed block-size we can't use |NGLayoutResult::IntrinsicBlockSize()|,
+      // and need to layout.
+      //
+      // TODO(ikilpatrick): Similar to %-block-size descendants we could store
+      // a bit on the |NGLayoutResult| which indicates if it had a child which
+      // sized itself based on the parent's block-size.
+      // We should consider this optimization if we are missing this cache
+      // often within this branch (and could have re-used the result).
+      // TODO(ikilaptrick): This may occur for other layout modes, e.g.
+      // grid/custom-layout/etc.
+      if (old_space.IsFixedBlockSize())
         return NGLayoutCacheStatus::kNeedsLayout;
+
+      // The intrinsic size of column flex-boxes can depend on the
+      // %-resolution-block-size. This occurs when a flex-box has "max-height:
+      // 100%" or similar on itself.
+      //
+      // Due to this we can't use cached |NGLayoutResult::IntrinsicBlockSize|
+      // value, as the following |block_size| calculation would be incorrect.
+      if (style.ResolvedIsColumnFlexDirection() &&
+          layout_result.PhysicalFragment().DependsOnPercentageBlockSize()) {
+        if (new_space.PercentageResolutionBlockSize() !=
+            old_space.PercentageResolutionBlockSize())
+          return NGLayoutCacheStatus::kNeedsLayout;
+      }
     }
 
     block_size = ComputeBlockSizeForFragment(
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc
index 97155f7..49f7c3c8 100644
--- a/third_party/blink/renderer/core/testing/internals.cc
+++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -852,7 +852,7 @@
 void Internals::endColorChooser(Element* element) {
   DCHECK(element);
   if (auto* input = DynamicTo<HTMLInputElement>(*element))
-    input->EndColorChooser();
+    input->EndColorChooserForTesting();
 }
 
 bool Internals::hasAutofocusRequest(Document* document) {
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index 70e8ed3..0ff1813c 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -396,6 +396,7 @@
     const String& mime_type,
     const String& codec) {
   media::AudioCodec audio_codec = media::kUnknownAudioCodec;
+  media::AudioCodecProfile audio_profile = media::AudioCodecProfile::kUnknown;
   bool is_audio_codec_ambiguous = true;
   bool is_spatial_rendering = false;
 
@@ -408,7 +409,8 @@
   if (audio_config->hasSpatialRendering())
     is_spatial_rendering = audio_config->spatialRendering();
 
-  return media::IsSupportedAudioType({audio_codec, is_spatial_rendering});
+  return media::IsSupportedAudioType(
+      {audio_codec, audio_profile, is_spatial_rendering});
 }
 
 // Returns whether the VideoConfiguration is supported.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 2f5018d8..f3c97e6 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -222,6 +222,7 @@
       buffered_amount_low_threshold_(0U),
       buffered_amount_(0U),
       stopped_(false),
+      closed_from_owner_(false),
       observer_(base::MakeRefCounted<Observer>(
           context->GetTaskRunner(TaskType::kNetworking),
           this,
@@ -427,6 +428,7 @@
 
 void RTCDataChannel::close() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  closed_from_owner_ = true;
   if (observer_)
     channel()->Close();
   // Note that even though Close() will run synchronously, the readyState has
@@ -459,9 +461,10 @@
 
   // A RTCDataChannel object must not be garbage collected if its
   // * readyState is connecting and at least one event listener is registered
-  //   for open events, message events, error events, or close events.
+  //   for open events, message events, error events, closing events
+  //   or close events.
   // * readyState is open and at least one event listener is registered for
-  //   message events, error events, or close events.
+  //   message events, error events, closing events, or close events.
   // * readyState is closing and at least one event listener is registered for
   //   error events, or close events.
   // * underlying data transport is established and data is queued to be
@@ -472,7 +475,8 @@
       has_valid_listeners |= HasEventListeners(event_type_names::kOpen);
       FALLTHROUGH;
     case webrtc::DataChannelInterface::kOpen:
-      has_valid_listeners |= HasEventListeners(event_type_names::kMessage);
+      has_valid_listeners |= HasEventListeners(event_type_names::kMessage) ||
+                             HasEventListeners(event_type_names::kClosing);
       FALLTHROUGH;
     case webrtc::DataChannelInterface::kClosing:
       has_valid_listeners |= HasEventListeners(event_type_names::kError) ||
@@ -509,6 +513,11 @@
       IncrementCounter(DataChannelCounters::kOpened);
       ScheduleDispatchEvent(Event::Create(event_type_names::kOpen));
       break;
+    case webrtc::DataChannelInterface::kClosing:
+      if (!closed_from_owner_) {
+        ScheduleDispatchEvent(Event::Create(event_type_names::kClosing));
+      }
+      break;
     case webrtc::DataChannelInterface::kClosed:
       if (!channel()->error().ok()) {
         ScheduleDispatchEvent(MakeGarbageCollected<RTCErrorEvent>(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
index f0b5ed9..0ec633b 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
@@ -91,6 +91,7 @@
   DEFINE_ATTRIBUTE_EVENT_LISTENER(bufferedamountlow, kBufferedamountlow)
   DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)
   DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose)
+  DEFINE_ATTRIBUTE_EVENT_LISTENER(closing, kClosing)
   DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage)
 
   // EventTarget
@@ -174,6 +175,7 @@
   unsigned buffered_amount_low_threshold_;
   unsigned buffered_amount_;
   bool stopped_;
+  bool closed_from_owner_;
   scoped_refptr<Observer> observer_;
   THREAD_CHECKER(thread_checker_);
 };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.idl b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.idl
index 85f38c6..ceb685c 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.idl
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.idl
@@ -51,6 +51,7 @@
              attribute EventHandler onopen;
              attribute EventHandler onbufferedamountlow;
              attribute EventHandler onerror;
+             attribute EventHandler onclosing;
              attribute EventHandler onclose;
     void close();
              attribute EventHandler onmessage;
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc b/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
index faa184dd..b444d6c 100644
--- a/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
@@ -122,20 +122,23 @@
                             1.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
-      gain_(
+      gain_(AudioParam::Create(context,
+                               Uuid(),
+                               AudioParamHandler::kParamTypeBiquadFilterGain,
+                               0.0,
+                               AudioParamHandler::AutomationRate::kAudio,
+                               AudioParamHandler::AutomationRateMode::kVariable,
+                               std::numeric_limits<float>::lowest(),
+                               40 * log10f(std::numeric_limits<float>::max()))),
+      detune_(
           AudioParam::Create(context,
                              Uuid(),
-                             AudioParamHandler::kParamTypeBiquadFilterGain,
+                             AudioParamHandler::kParamTypeBiquadFilterDetune,
                              0.0,
                              AudioParamHandler::AutomationRate::kAudio,
-                             AudioParamHandler::AutomationRateMode::kVariable)),
-      detune_(AudioParam::Create(
-          context,
-          Uuid(),
-          AudioParamHandler::kParamTypeBiquadFilterDetune,
-          0.0,
-          AudioParamHandler::AutomationRate::kAudio,
-          AudioParamHandler::AutomationRateMode::kVariable)) {
+                             AudioParamHandler::AutomationRateMode::kVariable,
+                             -1200 * log2f(std::numeric_limits<float>::max()),
+                             1200 * log2f(std::numeric_limits<float>::max()))) {
   SetHandler(BiquadFilterHandler::Create(*this, context.sampleRate(),
                                          frequency_->Handler(), q_->Handler(),
                                          gain_->Handler(), detune_->Handler()));
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index 1d1396c9..e8e61caa 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -278,6 +278,8 @@
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (!use_gpu_compositing) {
     resource_provider_->Initialize(nullptr, this);
+    if (frame_sink_id_.is_valid())
+      StartSubmitting();
     return;
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 330aa1b..c75ccfe0 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -642,6 +642,27 @@
   task_environment_.RunUntilIdle();
 }
 
+// Test that after context is lost, the CompositorFrameSink is recreated but the
+// SurfaceEmbedder isn't even with software compositing.
+TEST_F(VideoFrameSubmitterTest,
+       RecreateCompositorFrameSinkAfterContextLostSoftwareCompositing) {
+  MockEmbeddedFrameSinkProvider mock_embedded_frame_sink_provider;
+  mojo::Receiver<mojom::blink::EmbeddedFrameSinkProvider>
+      embedded_frame_sink_provider_binding(&mock_embedded_frame_sink_provider);
+  auto override =
+      mock_embedded_frame_sink_provider.CreateScopedOverrideMojoInterface(
+          &embedded_frame_sink_provider_binding);
+
+  EXPECT_CALL(*resource_provider_, Initialize(_, _));
+  EXPECT_CALL(mock_embedded_frame_sink_provider, ConnectToEmbedder(_, _))
+      .Times(0);
+  EXPECT_CALL(mock_embedded_frame_sink_provider, CreateCompositorFrameSink_(_))
+      .Times(1);
+  submitter_->OnContextLost();
+  OnReceivedContextProvider(false, nullptr);
+  task_environment_.RunUntilIdle();
+}
+
 // This test simulates a race condition in which the |video_frame_provider_| is
 // destroyed before OnReceivedContextProvider returns.
 TEST_F(VideoFrameSubmitterTest, StopUsingProviderDuringContextLost) {
diff --git a/third_party/blink/renderer/platform/p2p/OWNERS b/third_party/blink/renderer/platform/p2p/OWNERS
index 70573c4..eabc2b2 100644
--- a/third_party/blink/renderer/platform/p2p/OWNERS
+++ b/third_party/blink/renderer/platform/p2p/OWNERS
@@ -1,4 +1,5 @@
+guidou@chromium.org
 sergeyu@chromium.org
-juberti@chromium.org
+steveanton@chromium.org
 
 # COMPONENT: Blink>WebRTC
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index acfaf7f..092a9c4 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -327,36 +327,7 @@
 external/wpt/webgpu/* [ Skip ]
 wpt_internal/webgpu/* [ Skip ]
 
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-1-iframe-scrolled.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-1-iframe.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-composited-inner.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-composited-outer.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner-late-composite.html [ Failure ]
 crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-inner.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer-late-composite.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/gestures/gesture-tapHighlight-2-iframe.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/iframe-graphics-tree-changes-parents-does-not.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/low-dpi-non-stacking-context-scrolled-content.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/ancestor-overflow-layer-of-sticky-child-of-compositing-container.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/composited-scroller-can-be-normal-flow.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/nested-vertical-rl-overflow.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/overflow-scroll-background-fractional-offset.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/overflow-scroll-content-fractional-offset.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/overflow-scroll-with-local-background-and-child.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/overlap-testing-ancestor-scroller-high-dpi.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/overflow/scroll-children-do-not-paint-comp-scroll-phase.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/squashing/attempting-to-squash-into-compositing-container.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/squashing/attempting-to-squash-into-stacking-ancestor.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/squashing/squashing-does-not-stop-transform-propagation.html [ Failure ]
-crbug.com/1018273 [ Mac ] compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure ]
-crbug.com/1018273 [ Mac ] paint/invalidation/compositing/iframe-clip-removed.html [ Failure ]
-crbug.com/1018273 [ Mac ] paint/invalidation/compositing/should-not-paint-outline-on-foreground-layer.html [ Failure ]
-crbug.com/1018273 [ Mac ] paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure ]
-crbug.com/1018273 [ Mac ] paint/invalidation/compositing/stop-painting-onto-scrolling-contents.html [ Failure ]
-crbug.com/1018273 [ Mac ] paint/overflow/composited-scroll-vertical-rl.html [ Failure ]
 
 # Fail due to lack of fuzzy matching on Win and Mac platforms for WPT. The pixels in the pre-rotated reference
 # images do not exactly match the exif rotated images, probably due to jpeg decoding/encoding issues. Maybe
@@ -1343,7 +1314,6 @@
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-004v.html [ Failure ]
 crbug.com/846557 [ Mac ] virtual/layout_ng_flex_box/css3/flexbox/button.html [ Failure ]
-crbug.com/996474 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html [ Pass Failure ]
 
 # Fail in both legacy flex and NG flex
 crbug.com/249112 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-005.xht [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-comma-in-policy b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-comma-in-policy
new file mode 100644
index 0000000..42990f93
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-comma-in-policy
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline', img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-content-security b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-content-security
new file mode 100644
index 0000000..be9b375
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-content-security
@@ -0,0 +1,8 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'"]
+  },
+  "content_security": {
+    "policies": ["img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-policies b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-policies
new file mode 100644
index 0000000..2e625c5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-double-policies
@@ -0,0 +1,6 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'"],
+    "policies": ["img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg
new file mode 100644
index 0000000..cd57b7b2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": ["img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg-report-only b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg-report-only
new file mode 100644
index 0000000..13c662ef
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-noimg-report-only
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies_report_only": ["img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-array b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-array
new file mode 100644
index 0000000..b96546c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-array
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": "script-src 'self' 'unsafe-inline'"
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-object b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-object
new file mode 100644
index 0000000..7f6e138
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-object
@@ -0,0 +1,3 @@
+{
+  "content_security": ["script-src 'self' 'unsafe-inline'"]
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-string b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-string
new file mode 100644
index 0000000..8649b17
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-non-string
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": [["script-src 'self' 'unsafe-inline'"]]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid
new file mode 100644
index 0000000..d4babb794
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-multi-item-array b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-multi-item-array
new file mode 100644
index 0000000..45ec322
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-multi-item-array
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'", "img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-semicolon b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-semicolon
new file mode 100644
index 0000000..e777d5c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-content-security-valid-with-semicolon
@@ -0,0 +1,5 @@
+{
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'; img-src 'none'"]
+  }
+}
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-1 b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-1
index adbfc362..d4babb794 100644
--- a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-1
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-1
@@ -1,3 +1,5 @@
 {
-  "content-security-policy": [{ "policy": "script-src 'self' 'unsafe-inline'" }]
+  "content_security": {
+    "policies": ["script-src 'self' 'unsafe-inline'"]
+  }
 }
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-2 b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-2
index e896da3..34a6c5c8 100644
--- a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-2
+++ b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-csp-2
@@ -1,5 +1,5 @@
 {
-  "content-security-policy": [{
-    "policy": "script-src 'self' 'nonce-test'"
-  }]
+  "content_security": {
+    "policies": ["script-src 'self' 'nonce-test'"]
+  }
 }
diff --git a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-noimg b/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-noimg
deleted file mode 100644
index fce2d40..0000000
--- a/third_party/blink/web_tests/external/wpt/.well-known/origin-policy/policy-noimg
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "content-security-policy": [{ "policy": "img-src 'none'" }]
-}
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt
deleted file mode 100644
index 85f81beb..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valid-expected.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-This is a testharness.js-based test.
-PASS [INPUT in TEXT status] validity.valid must be false if validity.patternMismatch is true
-FAIL [INPUT in TEXT status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in SEARCH status] validity.valid must be false if validity.patternMismatch is true
-FAIL [INPUT in SEARCH status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in TEL status] validity.valid must be false if validity.patternMismatch is true
-FAIL [INPUT in TEL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in PASSWORD status] validity.valid must be false if validity.patternMismatch is true
-FAIL [INPUT in PASSWORD status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in URL status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in URL status] validity.valid must be false if validity.typeMismatch is true
-FAIL [INPUT in URL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in EMAIL status] validity.valid must be false if validity.patternMismatch is true
-PASS [INPUT in EMAIL status] validity.valid must be false if validity.typeMismatch is true
-FAIL [INPUT in EMAIL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in DATETIME-LOCAL status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in DATE status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in DATE status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in DATE status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in DATE status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in MONTH status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in MONTH status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in MONTH status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in MONTH status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in WEEK status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in WEEK status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in WEEK status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in WEEK status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in TIME status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in TIME status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in TIME status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in TIME status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in NUMBER status] validity.valid must be false if validity.rangeOverflow is true
-PASS [INPUT in NUMBER status] validity.valid must be false if validity.rangeUnderflow is true
-PASS [INPUT in NUMBER status] validity.valid must be false if validity.stepMismatch is true
-FAIL [INPUT in NUMBER status] validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-PASS [INPUT in CHECKBOX status] validity.valid must be false if validity.valueMissing is true
-PASS [INPUT in RADIO status] validity.valid must be false if validity.valueMissing is true
-PASS [INPUT in FILE status] validity.valid must be false if validity.valueMissing is true
-PASS [select]  validity.valid must be false if validity.valueMissing is true
-FAIL [textarea]  validity.valid must be false if validity.valueMissing is true assert_true: The validity.valid should be true, when control is disabled. expected true got false
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
index 6e95bca..c596f6f9 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing-expected.txt
@@ -1,85 +1,85 @@
 This is a testharness.js-based test.
-Found 95 tests; 50 PASS, 45 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 95 tests; 93 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [INPUT in TEXT status] The required attribute is not set
 PASS [INPUT in TEXT status] The value is not empty and required is true
-FAIL [INPUT in TEXT status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in TEXT status] The value is empty and required is true
 PASS [INPUT in SEARCH status] The required attribute is not set
 PASS [INPUT in SEARCH status] The value is not empty and required is true
-FAIL [INPUT in SEARCH status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in SEARCH status] The value is empty and required is true
 PASS [INPUT in TEL status] The required attribute is not set
 PASS [INPUT in TEL status] The value is not empty and required is true
-FAIL [INPUT in TEL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in TEL status] The value is empty and required is true
 PASS [INPUT in URL status] The required attribute is not set
 PASS [INPUT in URL status] The value is not empty and required is true
-FAIL [INPUT in URL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in URL status] The value is empty and required is true
 PASS [INPUT in EMAIL status] The required attribute is not set
 PASS [INPUT in EMAIL status] The value is not empty and required is true
-FAIL [INPUT in EMAIL status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in EMAIL status] The value is empty and required is true
 PASS [INPUT in PASSWORD status] The required attribute is not set
 PASS [INPUT in PASSWORD status] The value is not empty and required is true
-FAIL [INPUT in PASSWORD status] The value is empty and required is true assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in PASSWORD status] The value is empty and required is true
 PASS [INPUT in DATETIME-LOCAL status] The required attribute is not set
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10T12:00:00)
 FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(2000-12-10 12:00) assert_false: The validity.valueMissing should be false. expected false got true
 PASS [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14T12:00:00.001)
-FAIL [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATETIME-LOCAL status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] The value attribute is a number(1234567)
+PASS [INPUT in DATETIME-LOCAL status] The value attribute is a Date object
+PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(1979-10-99 99:99)
 FAIL [INPUT in DATETIME-LOCAL status] Valid local date and time string(1979-10-14 12:00:00) assert_false: The validity.valueMissing should be false. expected false got true
-FAIL [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATETIME-LOCAL status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in DATETIME-LOCAL status] Invalid local date and time string(2001-12-21  12:00)-two white space
+PASS [INPUT in DATETIME-LOCAL status] the value attribute is a string(abc)
+PASS [INPUT in DATETIME-LOCAL status] The value attribute is empty string
 PASS [INPUT in DATE status] The required attribute is not set
 PASS [INPUT in DATE status] Valid date string(2000-12-10)
 PASS [INPUT in DATE status] Valid date string(9999-01-01)
-FAIL [INPUT in DATE status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATE status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATE status] Invalid date string(9999-99-99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATE status] Invalid date string(37-01-01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATE status] Invalid date string(2000/01/01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in DATE status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in DATE status] The value attribute is a number(1234567)
+PASS [INPUT in DATE status] The value attribute is a Date object
+PASS [INPUT in DATE status] Invalid date string(9999-99-99)
+PASS [INPUT in DATE status] Invalid date string(37-01-01)
+PASS [INPUT in DATE status] Invalid date string(2000/01/01)
+PASS [INPUT in DATE status] The value attribute is empty string
 PASS [INPUT in MONTH status] The required attribute is not set
 PASS [INPUT in MONTH status] Valid month string(2000-12)
 PASS [INPUT in MONTH status] Valid month string(9999-01)
-FAIL [INPUT in MONTH status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in MONTH status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in MONTH status] Invalid month string(2000-99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in MONTH status] Invalid month string(37-01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in MONTH status] Invalid month string(2000/01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in MONTH status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in MONTH status] The value attribute is a number(1234567)
+PASS [INPUT in MONTH status] The value attribute is a Date object
+PASS [INPUT in MONTH status] Invalid month string(2000-99)
+PASS [INPUT in MONTH status] Invalid month string(37-01)
+PASS [INPUT in MONTH status] Invalid month string(2000/01)
+PASS [INPUT in MONTH status] The value attribute is empty string
 PASS [INPUT in WEEK status] The required attribute is not set
 PASS [INPUT in WEEK status] Valid week string(2000-W12)
 PASS [INPUT in WEEK status] Valid week string(9999-W01)
-FAIL [INPUT in WEEK status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in WEEK status] The value attribute is a Date object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in WEEK status] Invalid week string(2000-W99) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in WEEK status] invalid week string(2000-W00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in WEEK status] invalid week string(2000-w01) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in WEEK status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in WEEK status] The value attribute is a number(1234567)
+PASS [INPUT in WEEK status] The value attribute is a Date object
+PASS [INPUT in WEEK status] Invalid week string(2000-W99)
+PASS [INPUT in WEEK status] invalid week string(2000-W00)
+PASS [INPUT in WEEK status] invalid week string(2000-w01)
+PASS [INPUT in WEEK status] The value attribute is empty string
 PASS [INPUT in TIME status] The required attribute is not set
 PASS [INPUT in TIME status] Validtime string(12:00:00)
 PASS [INPUT in TIME status] Validtime string(12:00)
 PASS [INPUT in TIME status] Valid time string(12:00:60.001)
 PASS [INPUT in TIME status] Valid time string(12:00:60.01)
 PASS [INPUT in TIME status] Valid time string(12:00:60.1)
-FAIL [INPUT in TIME status] The value attribute is a number(1234567) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] The value attribute is a time object assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] Invalid time string(25:00:00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] Invalid time string(12:60:00) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] Invalid time string(12:00:60) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] Invalid time string(12:00:00:001) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in TIME status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in TIME status] The value attribute is a number(1234567)
+PASS [INPUT in TIME status] The value attribute is a time object
+PASS [INPUT in TIME status] Invalid time string(25:00:00)
+PASS [INPUT in TIME status] Invalid time string(12:60:00)
+PASS [INPUT in TIME status] Invalid time string(12:00:60)
+PASS [INPUT in TIME status] Invalid time string(12:00:00:001)
+PASS [INPUT in TIME status] The value attribute is empty string
 PASS [INPUT in NUMBER status] The required attribute is not set
 PASS [INPUT in NUMBER status] Value is an integer with a leading symbol '+'
 PASS [INPUT in NUMBER status] Value is a number with a '-' symbol
 PASS [INPUT in NUMBER status] Value is a number in scientific notation form(e is in lowercase)
 PASS [INPUT in NUMBER status] Value is a number in scientific notation form(E is in uppercase)
 PASS [INPUT in NUMBER status] Value is -0
-FAIL [INPUT in NUMBER status] Value is a number with some white spaces assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in NUMBER status] Value is Math.pow(2, 1024) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in NUMBER status] Value is Math.pow(-2, 1024) assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in NUMBER status] Value is a string that cannot be converted to a number assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
-FAIL [INPUT in NUMBER status] The value attribute is empty string assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [INPUT in NUMBER status] Value is a number with some white spaces
+PASS [INPUT in NUMBER status] Value is Math.pow(2, 1024)
+PASS [INPUT in NUMBER status] Value is Math.pow(-2, 1024)
+PASS [INPUT in NUMBER status] Value is a string that cannot be converted to a number
+PASS [INPUT in NUMBER status] The value attribute is empty string
 PASS [INPUT in CHECKBOX status] The required attribute is not set
 PASS [INPUT in CHECKBOX status] The checked attribute is true
 PASS [INPUT in CHECKBOX status] The checked attribute is false
@@ -94,6 +94,6 @@
 PASS [select]  Selected the option with value equals to empty
 PASS [textarea]  The required attribute is not set
 PASS [textarea]  The value is not empty
-FAIL [textarea]  The value is empty assert_false: The validity.valueMissing should be false, when control is disabled. expected false got true
+PASS [textarea]  The value is empty
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
index 3229527..223d54ce 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
@@ -23,6 +23,10 @@
       tag: "input",
       types: ["datetime-local"],
       testData: [
+        // Note that several of these datetime strings use a ' ' separator, which
+        // is questionably spec-compliant. See:
+        //   - crbug.com/521871
+        //   - https://github.com/whatwg/html/issues/2276
         {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
         {conditions: {required: true, value: "2000-12-10T12:00:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10T12:00:00)"},
         {conditions: {required: true, value: "2000-12-10 12:00"}, expected: false, name: "[target] Valid local date and time string(2000-12-10 12:00)"},
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html
new file mode 100644
index 0000000..88d7244
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Commas in "content_security/policy" cause parse errors and thus no CSP</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html.headers
new file mode 100644
index 0000000..32e453a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/comma-in-policy.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-comma-in-policy
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html
new file mode 100644
index 0000000..9904680
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Of two "content_security" items only the second counts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true, img: false });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html.headers
new file mode 100644
index 0000000..a380b05
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-content-security.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-double-content-security
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html
new file mode 100644
index 0000000..925b9d5a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Of two "content_security/policies" items only the second counts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true, img: false });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html.headers
new file mode 100644
index 0000000..23f1d14
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/double-policies.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-double-policies
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/helper.js b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/helper.js
new file mode 100644
index 0000000..4875977
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/helper.js
@@ -0,0 +1,73 @@
+window.waitForOneSecurityPolicyViolationEvent = expectedBlockedURI => {
+  return new Promise(resolve => {
+    let eventCount = 0;
+    let blockedURI = null;
+
+    document.addEventListener("securitypolicyviolation", e => {
+      ++eventCount;
+      blockedURI = e.blockedURI;
+
+      // We want to test that only one event is fired, but we want to do so
+      // without waiting indefinitely. By waiting for one tick, we at least
+      // ensure that there's no bug that leads to two securitypolicyviolation
+      // events being fired at the same time, as a result of the one violation.
+      step_timeout(() => {
+        assert_equals(eventCount, 1);
+        resolve(blockedURI);
+      });
+    });
+  });
+};
+
+window.waitForImgFail = imgSrc => {
+  return new Promise((resolve, reject) => {
+    const img = document.createElement("img");
+    img.onload = () => reject(new Error("Must not load the image"));
+    img.onerror = () => resolve();
+
+    img.src = imgSrc;
+    document.body.append(img);
+  });
+};
+
+
+window.waitForImgSuccess = imgSrc => {
+  return new Promise((resolve, reject) => {
+    const img = document.createElement("img");
+    img.onload = () => resolve();
+    img.onerror = () => reject(new Error("Must load the image"));
+
+    img.src = imgSrc;
+    document.body.append(img);
+  });
+};
+
+// Both params are optional; if they are not given as booleans then we will not test that aspect.
+window.runCSPTest = ({ unsafeEval, img }) => {
+  if (unsafeEval === true) {
+    test(() => {
+      eval("window.evalAllowed = true;");
+      assert_equals(window.evalAllowed, true);
+    }, "eval must be allowed");
+  } else if (unsafeEval === false) {
+    test(() => {
+      try {
+        eval("window.evalAllowed = true;");
+      } catch (e) { }
+
+      assert_equals(window.evalAllowed, undefined);
+    }, "eval must be disallowed");
+  }
+
+  if (img === true) {
+    promise_test(
+      () => waitForImgSuccess("/common/security-features/subresource/image.py"),
+      "img loading must be allowed"
+    );
+  } else if (img === false) {
+    promise_test(
+      () => waitForImgFail("/common/security-features/subresource/image.py"),
+      "img loading must be disallowed"
+    );
+  }
+};
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html
new file mode 100644
index 0000000..78a67e16
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Non-array "content_security/policies" member must be ignored</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html.headers
new file mode 100644
index 0000000..31e6f37
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-array.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-non-array
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html
new file mode 100644
index 0000000..359c6c7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Non-object "content_security" member must be ignored</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html.headers
new file mode 100644
index 0000000..812ea9445
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-object.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-non-object
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html
new file mode 100644
index 0000000..8af3c1c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Non-string "content_security/policies" array member must be ignored</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: true });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html.headers
new file mode 100644
index 0000000..0b9ce2ee
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/non-string.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-non-string
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html
new file mode 100644
index 0000000..3e5038b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>CSP via origin policy must trigger a securitypolicyviolation event even when the CSP is report-only</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+
+promise_test(() => {
+  const imgURL = (new URL("/common/security-features/subresource/image.py", document.location)).href;
+
+  return Promise.all([
+    waitForOneSecurityPolicyViolationEvent(imgURL).then(blockedURI => {
+      assert_equals(blockedURI, imgURL);
+    }),
+    waitForImgSuccess(imgURL)
+  ]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html.headers
new file mode 100644
index 0000000..cb27e15
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report-report-only.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-noimg-report-only
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html
new file mode 100644
index 0000000..22beca5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>CSP via origin policy must trigger a securitypolicyviolation event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+
+promise_test(() => {
+  const imgURL = (new URL("/common/security-features/subresource/image.py", document.location)).href;
+
+  return Promise.all([
+    waitForOneSecurityPolicyViolationEvent(imgURL).then(blockedURI => {
+      assert_equals(blockedURI, imgURL);
+    }),
+    waitForImgFail(imgURL)
+  ]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html.headers
new file mode 100644
index 0000000..08bcb9f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/trigger-violation-report.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-noimg
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html
new file mode 100644
index 0000000..bc9ebd0c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>"content_security/policy" can contain multiple array items to enforce multiple CSPs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: false, img: false });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html.headers
new file mode 100644
index 0000000..eeddaba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-multi-item-array.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-valid-with-semicolon
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html
new file mode 100644
index 0000000..82158f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>"content_security/policy" array items can contain semicolons to enforce multiple CSP directives</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<body>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: false, img: false });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html.headers
new file mode 100644
index 0000000..eeddaba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid-with-semicolon.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-valid-with-semicolon
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html
new file mode 100644
index 0000000..36e5ddb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Valid "content_security" member disallows eval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="helper.js"></script>
+
+<script>
+"use strict";
+runCSPTest({ unsafeEval: false });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html.headers
new file mode 100644
index 0000000..78aeeacd9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/origin-policy/content-security/valid.https.html.headers
@@ -0,0 +1 @@
+Sec-Origin-Policy: policy=policy-content-security-valid
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html b/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html
deleted file mode 100644
index 24ee8999..0000000
--- a/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <script src='/resources/testharness.js'></script>
-  <script src='/resources/testharnessreport.js'></script>
-</head>
-<body>
-  <iframe id=frame></iframe>
-  <script>
-    async_test(t => {
-      let violations = [];
-      window.addEventListener("message", (e) => {
-        violations.push(e);
-        t.step_timeout(() => {
-          assert_equals(violations.length, 1);
-          t.done();
-        });
-      });
-
-      let forbidden_image = "<img src=https://127.0.0.1:1234/bla.jpg>";
-      let event_bouncer = "<script>document.addEventListener(" +
-          "'securitypolicyviolation'," +
-          "(e) => window.parent.postMessage(e.blockedURI, '*'));</sc" +
-          "ript>";
-      document.getElementById("frame").src =
-        "data:text/html;charset=utf-8," + event_bouncer + forbidden_image;
-    }, "Origin-Policy-based CSP violation should trigger 1 violation event");
-  </script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html.headers b/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html.headers
deleted file mode 100644
index 9456832..0000000
--- a/third_party/blink/web_tests/external/wpt/origin-policy/origin-policy-single-report.https.tentative.html.headers
+++ /dev/null
@@ -1 +0,0 @@
-Sec-Origin-Policy: policy=policy-noimg
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCDataChannel-close.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCDataChannel-close.html
index 9f43dc93..a417d66d 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCDataChannel-close.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCDataChannel-close.html
@@ -12,15 +12,23 @@
   let pc1 = new RTCPeerConnection();
   t.add_cleanup(() => pc1.close());
   let [channel1, channel2] = await createDataChannelPair(pc1);
-  let close_handler = new Promise(resolve => {
+  let closeHandler = new Promise(resolve => {
     channel2.onclose = event => {
       resolve();
     };
   });
+  let closingSeen = false;
+  channel1.onclosing = t.unreached_func();
+  channel2.onclosing = event => {
+    assert_equals(channel2.readyState, 'closing');
+    closingSeen = true;
+  }
   channel2.addEventListener('error', t.unreached_func());
   channel1.close();
-  await close_handler;
-}, 'Close datachannel causes onclose to be called');
+  await closeHandler;
+  assert_equals(channel2.readyState, 'closed');
+  assert_true(closingSeen, 'Closing event was seen');
+}, 'Close datachannel causes onclosing and onclose to be called');
 
 promise_test(async t => {
   // This is the same test as above, but using addEventListener
@@ -28,15 +36,23 @@
   let pc1 = new RTCPeerConnection();
   t.add_cleanup(() => pc1.close());
   let [channel1, channel2] = await createDataChannelPair(pc1);
-  let close_handler = new Promise(resolve => {
+  let closeHandler = new Promise(resolve => {
     channel2.addEventListener('close', event => {
       resolve();
     });
   });
+  let closingSeen = false;
+  channel1.addEventListener('closing', t.unreached_func());
+  channel2.addEventListener('closing', event => {
+    assert_equals(channel2.readyState, 'closing');
+    closingSeen = true;
+  });
   channel2.addEventListener('error', t.unreached_func());
   channel1.close();
-  await close_handler;
-}, 'Close datachannel causes close event to be called');
+  await closeHandler;
+  assert_equals(channel2.readyState, 'closed');
+  assert_true(closingSeen, 'Closing event was seen');
+}, 'Close datachannel causes closing and close event to be called');
 
 promise_test(async t => {
   let pc1 = new RTCPeerConnection();
@@ -44,13 +60,13 @@
   let [channel1, channel2] = await createDataChannelPair(pc1);
   let events = [];
   let error = null;
-  let close_handler = new Promise(resolve => {
+  let closeHandler = new Promise(resolve => {
     channel2.addEventListener('close', event => {
       events.push('close');
       resolve();
     });
   });
-  let error_handler = new Promise((resolve, reject) => {
+  let errorHandler = new Promise((resolve, reject) => {
     channel2.addEventListener('error', event => {
       events.push('error');
       try {
@@ -64,8 +80,8 @@
     });
   });
   pc1.close();
-  await error_handler;
-  await close_handler;
+  await errorHandler;
+  await closeHandler;
   // Error should fire before close.
   assert_array_equals(['error', 'close'], events);
   assert_true(error instanceof RTCError);
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
index 0d03127..9b2378f 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 496 tests; 466 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 496 tests; 468 PASS, 28 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Test driver for asyncInitCertificate
@@ -407,7 +407,7 @@
 PASS RTCDataChannel interface: attribute onopen
 PASS RTCDataChannel interface: attribute onbufferedamountlow
 PASS RTCDataChannel interface: attribute onerror
-FAIL RTCDataChannel interface: attribute onclosing assert_true: The prototype object must have a property "onclosing" expected true got false
+PASS RTCDataChannel interface: attribute onclosing
 PASS RTCDataChannel interface: attribute onclose
 PASS RTCDataChannel interface: operation close()
 PASS RTCDataChannel interface: attribute onmessage
@@ -431,7 +431,7 @@
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onopen" with the proper type
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onbufferedamountlow" with the proper type
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onerror" with the proper type
-FAIL RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclosing" with the proper type assert_inherits: property "onclosing" not found in prototype chain
+PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclosing" with the proper type
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclose" with the proper type
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "close()" with the proper type
 PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onmessage" with the proper type
diff --git a/third_party/blink/web_tests/fast/forms/color/input-color-onchange-event.html b/third_party/blink/web_tests/fast/forms/color/input-color-onchange-event.html
index 1e560cff..8057a1f9 100644
--- a/third_party/blink/web_tests/fast/forms/color/input-color-onchange-event.html
+++ b/third_party/blink/web_tests/fast/forms/color/input-color-onchange-event.html
@@ -27,9 +27,13 @@
     debug("input event dispatched - value is:  " + input.value);
 };
 
-eventSender.mouseMoveTo(10, 10);
-eventSender.mouseDown();
-eventSender.mouseUp();
+function openColorChooser() {
+  eventSender.mouseMoveTo(10, 10);
+  eventSender.mouseDown();
+  eventSender.mouseUp();
+}
+
+openColorChooser();
 
 // Test that incorrect element arguments are (not) handled.
 shouldThrow("internals.selectColorInColorChooser({}, '#ff0000');");
@@ -45,6 +49,7 @@
 
 function step2() {
     debug("change event dispatched - value changed to " + input.value);
+    openColorChooser();
     // input.onchange should not be called
     input.onchange = () => {
         testFailed("Change event should not be dispatched.");
@@ -57,6 +62,7 @@
 
 function step3() {
     debug('Change event is only dispatched, when color chooser is closed');
+    openColorChooser();
     input.onchange = step4;
     internals.selectColorInColorChooser(input, '#ff0002');
     internals.endColorChooser(input);
diff --git a/third_party/blink/web_tests/virtual/origin-policy/external/wpt/origin-policy/content-security/comma-in-policy.https-expected.txt b/third_party/blink/web_tests/virtual/origin-policy/external/wpt/origin-policy/content-security/comma-in-policy.https-expected.txt
new file mode 100644
index 0000000..117783a
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/origin-policy/external/wpt/origin-policy/content-security/comma-in-policy.https-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL eval must be allowed Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'".
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index c7e534b..6ab487e 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5106,6 +5106,7 @@
     getter negotiated
     getter onbufferedamountlow
     getter onclose
+    getter onclosing
     getter onerror
     getter onmessage
     getter onopen
@@ -5120,6 +5121,7 @@
     setter bufferedAmountLowThreshold
     setter onbufferedamountlow
     setter onclose
+    setter onclosing
     setter onerror
     setter onmessage
     setter onopen
diff --git a/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range-expected.txt b/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range-expected.txt
index 50b8158..8d60ace0 100644
--- a/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range-expected.txt
+++ b/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range-expected.txt
@@ -1,46 +1,52 @@
-CONSOLE WARNING: line 399: Delay.delayTime.value -1 outside nominal range [0, 1.5]; value will be clamped.
-CONSOLE WARNING: line 399: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1.5]; value will be clamped.
-CONSOLE WARNING: line 411: Delay.delayTime.value 4 outside nominal range [0, 1.5]; value will be clamped.
-CONSOLE WARNING: line 411: Delay.delayTime.setValueAtTime value 4 outside nominal range [0, 1.5]; value will be clamped.
-CONSOLE WARNING: line 399: StereoPanner.pan.value -3 outside nominal range [-1, 1]; value will be clamped.
-CONSOLE WARNING: line 399: StereoPanner.pan.setValueAtTime value -3 outside nominal range [-1, 1]; value will be clamped.
-CONSOLE WARNING: line 411: StereoPanner.pan.value 3 outside nominal range [-1, 1]; value will be clamped.
-CONSOLE WARNING: line 411: StereoPanner.pan.setValueAtTime value 3 outside nominal range [-1, 1]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.threshold.value -201 outside nominal range [-100, 0]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.threshold.setValueAtTime value -201 outside nominal range [-100, 0]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.threshold.value 1 outside nominal range [-100, 0]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.threshold.setValueAtTime value 1 outside nominal range [-100, 0]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.knee.value -1 outside nominal range [0, 40]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.knee.setValueAtTime value -1 outside nominal range [0, 40]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.knee.value 81 outside nominal range [0, 40]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.knee.setValueAtTime value 81 outside nominal range [0, 40]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.ratio.value 41 outside nominal range [1, 20]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.ratio.setValueAtTime value 41 outside nominal range [1, 20]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.attack.value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.attack.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.attack.value 3 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.attack.setValueAtTime value 3 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.release.value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 399: DynamicsCompressor.release.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.release.value 3 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 411: DynamicsCompressor.release.setValueAtTime value 3 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 399: BiquadFilter.frequency.value -1 outside nominal range [0, 24000]; value will be clamped.
-CONSOLE WARNING: line 399: BiquadFilter.frequency.setValueAtTime value -1 outside nominal range [0, 24000]; value will be clamped.
-CONSOLE WARNING: line 411: BiquadFilter.frequency.value 48001 outside nominal range [0, 24000]; value will be clamped.
-CONSOLE WARNING: line 411: BiquadFilter.frequency.setValueAtTime value 48001 outside nominal range [0, 24000]; value will be clamped.
-CONSOLE WARNING: line 399: Oscillator.frequency.value -48001 outside nominal range [-24000, 24000]; value will be clamped.
-CONSOLE WARNING: line 399: Oscillator.frequency.setValueAtTime value -48001 outside nominal range [-24000, 24000]; value will be clamped.
-CONSOLE WARNING: line 411: Oscillator.frequency.value 48001 outside nominal range [-24000, 24000]; value will be clamped.
-CONSOLE WARNING: line 411: Oscillator.frequency.setValueAtTime value 48001 outside nominal range [-24000, 24000]; value will be clamped.
-CONSOLE WARNING: line 399: Oscillator.detune.value -307201 outside nominal range [-153600, 153600]; value will be clamped.
-CONSOLE WARNING: line 399: Oscillator.detune.setValueAtTime value -307201 outside nominal range [-153600, 153600]; value will be clamped.
-CONSOLE WARNING: line 411: Oscillator.detune.value 307201 outside nominal range [-153600, 153600]; value will be clamped.
-CONSOLE WARNING: line 411: Oscillator.detune.setValueAtTime value 307201 outside nominal range [-153600, 153600]; value will be clamped.
-CONSOLE WARNING: line 327: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 328: Delay.delayTime.linearRampToValueAtTime value 2 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 329: Delay.delayTime.exponentialRampToValue value 3 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 330: Delay.delayTime.setTargetAtTime value -1 outside nominal range [0, 1]; value will be clamped.
-CONSOLE WARNING: line 331: Delay.delayTime.setValueCurveAtTime value 1.5 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 406: Delay.delayTime.value -1 outside nominal range [0, 1.5]; value will be clamped.
+CONSOLE WARNING: line 406: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1.5]; value will be clamped.
+CONSOLE WARNING: line 418: Delay.delayTime.value 4 outside nominal range [0, 1.5]; value will be clamped.
+CONSOLE WARNING: line 418: Delay.delayTime.setValueAtTime value 4 outside nominal range [0, 1.5]; value will be clamped.
+CONSOLE WARNING: line 406: StereoPanner.pan.value -3 outside nominal range [-1, 1]; value will be clamped.
+CONSOLE WARNING: line 406: StereoPanner.pan.setValueAtTime value -3 outside nominal range [-1, 1]; value will be clamped.
+CONSOLE WARNING: line 418: StereoPanner.pan.value 3 outside nominal range [-1, 1]; value will be clamped.
+CONSOLE WARNING: line 418: StereoPanner.pan.setValueAtTime value 3 outside nominal range [-1, 1]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.threshold.value -201 outside nominal range [-100, 0]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.threshold.setValueAtTime value -201 outside nominal range [-100, 0]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.threshold.value 1 outside nominal range [-100, 0]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.threshold.setValueAtTime value 1 outside nominal range [-100, 0]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.knee.value -1 outside nominal range [0, 40]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.knee.setValueAtTime value -1 outside nominal range [0, 40]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.knee.value 81 outside nominal range [0, 40]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.knee.setValueAtTime value 81 outside nominal range [0, 40]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.ratio.value 41 outside nominal range [1, 20]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.ratio.setValueAtTime value 41 outside nominal range [1, 20]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.attack.value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.attack.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.attack.value 3 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.attack.setValueAtTime value 3 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.release.value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 406: DynamicsCompressor.release.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.release.value 3 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 418: DynamicsCompressor.release.setValueAtTime value 3 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 406: BiquadFilter.frequency.value -1 outside nominal range [0, 24000]; value will be clamped.
+CONSOLE WARNING: line 406: BiquadFilter.frequency.setValueAtTime value -1 outside nominal range [0, 24000]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.frequency.value 48001 outside nominal range [0, 24000]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.frequency.setValueAtTime value 48001 outside nominal range [0, 24000]; value will be clamped.
+CONSOLE WARNING: line 406: BiquadFilter.detune.value -307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 406: BiquadFilter.detune.setValueAtTime value -307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.detune.value 307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.detune.setValueAtTime value 307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.gain.value 3083.55 outside nominal range [-3.40282e+38, 1541.27]; value will be clamped.
+CONSOLE WARNING: line 418: BiquadFilter.gain.setValueAtTime value 3083.55 outside nominal range [-3.40282e+38, 1541.27]; value will be clamped.
+CONSOLE WARNING: line 406: Oscillator.frequency.value -48001 outside nominal range [-24000, 24000]; value will be clamped.
+CONSOLE WARNING: line 406: Oscillator.frequency.setValueAtTime value -48001 outside nominal range [-24000, 24000]; value will be clamped.
+CONSOLE WARNING: line 418: Oscillator.frequency.value 48001 outside nominal range [-24000, 24000]; value will be clamped.
+CONSOLE WARNING: line 418: Oscillator.frequency.setValueAtTime value 48001 outside nominal range [-24000, 24000]; value will be clamped.
+CONSOLE WARNING: line 406: Oscillator.detune.value -307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 406: Oscillator.detune.setValueAtTime value -307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 418: Oscillator.detune.value 307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 418: Oscillator.detune.setValueAtTime value 307201 outside nominal range [-153600, 153600]; value will be clamped.
+CONSOLE WARNING: line 334: Delay.delayTime.setValueAtTime value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 335: Delay.delayTime.linearRampToValueAtTime value 2 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 336: Delay.delayTime.exponentialRampToValue value 3 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 337: Delay.delayTime.setTargetAtTime value -1 outside nominal range [0, 1]; value will be clamped.
+CONSOLE WARNING: line 338: Delay.delayTime.setValueCurveAtTime value 1.5 outside nominal range [0, 1]; value will be clamped.
 This is a testharness.js-based test.
 PASS # AUDIT TASK RUNNER STARTED.
 PASS > [initialize] 
@@ -65,7 +71,7 @@
 PASS   DelayNode.delayTime.maxValue is read-only is equal to true.
 PASS   Set DelayNode.delayTime.value = -1 is equal to 0.
 PASS   Set DelayNode.delayTime.value = 4 is equal to 1.5.
-PASS   DelayNode.delayTimewas clipped to lie within the nominal range is equal to true.
+PASS   DelayNode.delayTime was clipped to lie within the nominal range is equal to true.
 PASS   Nominal ranges for AudioParam(s) of DelayNode are correct
 PASS < [Offline createDelay] All assertions passed. (total 10 assertions)
 PASS > [Offline createBufferSource] 
@@ -92,7 +98,7 @@
 PASS   StereoPannerNode.pan.maxValue is read-only is equal to true.
 PASS   Set StereoPannerNode.pan.value = -3 is equal to -1.
 PASS   Set StereoPannerNode.pan.value = 3 is equal to 1.
-PASS   StereoPannerNode.panwas clipped to lie within the nominal range is equal to true.
+PASS   StereoPannerNode.pan was clipped to lie within the nominal range is equal to true.
 PASS   Nominal ranges for AudioParam(s) of StereoPannerNode are correct
 PASS < [Offline createStereoPanner] All assertions passed. (total 10 assertions)
 PASS > [Offline createDynamicsCompressor] 
@@ -104,7 +110,7 @@
 PASS   DynamicsCompressorNode.threshold.maxValue is read-only is equal to true.
 PASS   Set DynamicsCompressorNode.threshold.value = -201 is equal to -100.
 PASS   Set DynamicsCompressorNode.threshold.value = 1 is equal to 0.
-PASS   DynamicsCompressorNode.thresholdwas clipped to lie within the nominal range is equal to true.
+PASS   DynamicsCompressorNode.threshold was clipped to lie within the nominal range is equal to true.
 PASS   DynamicsCompressorNode.knee.minValue is equal to 0.
 PASS   DynamicsCompressorNode.knee.maxValue is equal to 40.
 PASS   DynamicsCompressorNode.knee.minValue = 42 is not equal to 42.
@@ -113,7 +119,7 @@
 PASS   DynamicsCompressorNode.knee.maxValue is read-only is equal to true.
 PASS   Set DynamicsCompressorNode.knee.value = -1 is equal to 0.
 PASS   Set DynamicsCompressorNode.knee.value = 81 is equal to 40.
-PASS   DynamicsCompressorNode.kneewas clipped to lie within the nominal range is equal to true.
+PASS   DynamicsCompressorNode.knee was clipped to lie within the nominal range is equal to true.
 PASS   DynamicsCompressorNode.ratio.minValue is equal to 1.
 PASS   DynamicsCompressorNode.ratio.maxValue is equal to 20.
 PASS   DynamicsCompressorNode.ratio.minValue = 42 is not equal to 42.
@@ -122,7 +128,7 @@
 PASS   DynamicsCompressorNode.ratio.maxValue is read-only is equal to true.
 PASS   Set DynamicsCompressorNode.ratio.value = 1 is equal to 1.
 PASS   Set DynamicsCompressorNode.ratio.value = 41 is equal to 20.
-PASS   DynamicsCompressorNode.ratiowas clipped to lie within the nominal range is equal to true.
+PASS   DynamicsCompressorNode.ratio was clipped to lie within the nominal range is equal to true.
 PASS   DynamicsCompressorNode.attack.minValue is equal to 0.
 PASS   DynamicsCompressorNode.attack.maxValue is equal to 1.
 PASS   DynamicsCompressorNode.attack.minValue = 42 is not equal to 42.
@@ -131,7 +137,7 @@
 PASS   DynamicsCompressorNode.attack.maxValue is read-only is equal to true.
 PASS   Set DynamicsCompressorNode.attack.value = -1 is equal to 0.
 PASS   Set DynamicsCompressorNode.attack.value = 3 is equal to 1.
-PASS   DynamicsCompressorNode.attackwas clipped to lie within the nominal range is equal to true.
+PASS   DynamicsCompressorNode.attack was clipped to lie within the nominal range is equal to true.
 PASS   DynamicsCompressorNode.release.minValue is equal to 0.
 PASS   DynamicsCompressorNode.release.maxValue is equal to 1.
 PASS   DynamicsCompressorNode.release.minValue = 42 is not equal to 42.
@@ -140,7 +146,7 @@
 PASS   DynamicsCompressorNode.release.maxValue is read-only is equal to true.
 PASS   Set DynamicsCompressorNode.release.value = -1 is equal to 0.
 PASS   Set DynamicsCompressorNode.release.value = 3 is equal to 1.
-PASS   DynamicsCompressorNode.releasewas clipped to lie within the nominal range is equal to true.
+PASS   DynamicsCompressorNode.release was clipped to lie within the nominal range is equal to true.
 PASS   Nominal ranges for AudioParam(s) of DynamicsCompressorNode are correct
 PASS < [Offline createDynamicsCompressor] All assertions passed. (total 46 assertions)
 PASS > [Offline createBiquadFilter] 
@@ -152,13 +158,16 @@
 PASS   BiquadFilterNode.frequency.maxValue is read-only is equal to true.
 PASS   Set BiquadFilterNode.frequency.value = -1 is equal to 0.
 PASS   Set BiquadFilterNode.frequency.value = 48001 is equal to 24000.
-PASS   BiquadFilterNode.frequencywas clipped to lie within the nominal range is equal to true.
-PASS   BiquadFilterNode.detune.minValue is equal to -3.4028234663852886e+38.
-PASS   BiquadFilterNode.detune.maxValue is equal to 3.4028234663852886e+38.
+PASS   BiquadFilterNode.frequency was clipped to lie within the nominal range is equal to true.
+PASS   BiquadFilterNode.detune.minValue is equal to -153600.
+PASS   BiquadFilterNode.detune.maxValue is equal to 153600.
 PASS   BiquadFilterNode.detune.minValue = 42 is not equal to 42.
 PASS   BiquadFilterNode.detune.minValue is read-only is equal to true.
 PASS   BiquadFilterNode.detune.maxValue = 42 is not equal to 42.
 PASS   BiquadFilterNode.detune.maxValue is read-only is equal to true.
+PASS   Set BiquadFilterNode.detune.value = -307201 is equal to -153600.
+PASS   Set BiquadFilterNode.detune.value = 307201 is equal to 153600.
+PASS   BiquadFilterNode.detune was clipped to lie within the nominal range is equal to true.
 PASS   BiquadFilterNode.Q.minValue is equal to -3.4028234663852886e+38.
 PASS   BiquadFilterNode.Q.maxValue is equal to 3.4028234663852886e+38.
 PASS   BiquadFilterNode.Q.minValue = 42 is not equal to 42.
@@ -166,13 +175,15 @@
 PASS   BiquadFilterNode.Q.maxValue = 42 is not equal to 42.
 PASS   BiquadFilterNode.Q.maxValue is read-only is equal to true.
 PASS   BiquadFilterNode.gain.minValue is equal to -3.4028234663852886e+38.
-PASS   BiquadFilterNode.gain.maxValue is equal to 3.4028234663852886e+38.
+PASS   BiquadFilterNode.gain.maxValue is equal to 1541.273681640625.
 PASS   BiquadFilterNode.gain.minValue = 42 is not equal to 42.
 PASS   BiquadFilterNode.gain.minValue is read-only is equal to true.
 PASS   BiquadFilterNode.gain.maxValue = 42 is not equal to 42.
 PASS   BiquadFilterNode.gain.maxValue is read-only is equal to true.
+PASS   Set BiquadFilterNode.gain.value = 3083.54736328125 is equal to 1541.273681640625.
+PASS   BiquadFilterNode.gain was clipped to lie within the nominal range is equal to true.
 PASS   Nominal ranges for AudioParam(s) of BiquadFilterNode are correct
-PASS < [Offline createBiquadFilter] All assertions passed. (total 28 assertions)
+PASS < [Offline createBiquadFilter] All assertions passed. (total 33 assertions)
 PASS > [Offline createOscillator] 
 PASS   OscillatorNode.frequency.minValue is equal to -24000.
 PASS   OscillatorNode.frequency.maxValue is equal to 24000.
@@ -182,7 +193,7 @@
 PASS   OscillatorNode.frequency.maxValue is read-only is equal to true.
 PASS   Set OscillatorNode.frequency.value = -48001 is equal to -24000.
 PASS   Set OscillatorNode.frequency.value = 48001 is equal to 24000.
-PASS   OscillatorNode.frequencywas clipped to lie within the nominal range is equal to true.
+PASS   OscillatorNode.frequency was clipped to lie within the nominal range is equal to true.
 PASS   OscillatorNode.detune.minValue is equal to -153600.
 PASS   OscillatorNode.detune.maxValue is equal to 153600.
 PASS   OscillatorNode.detune.minValue = 42 is not equal to 42.
@@ -191,7 +202,7 @@
 PASS   OscillatorNode.detune.maxValue is read-only is equal to true.
 PASS   Set OscillatorNode.detune.value = -307201 is equal to -153600.
 PASS   Set OscillatorNode.detune.value = 307201 is equal to 153600.
-PASS   OscillatorNode.detunewas clipped to lie within the nominal range is equal to true.
+PASS   OscillatorNode.detune was clipped to lie within the nominal range is equal to true.
 PASS   Nominal ranges for AudioParam(s) of OscillatorNode are correct
 PASS < [Offline createOscillator] All assertions passed. (total 19 assertions)
 PASS > [Offline createPanner] 
diff --git a/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range.html b/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range.html
index d9d09ed..ed466cb 100644
--- a/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range.html
+++ b/third_party/blink/web_tests/webaudio/AudioParam/audioparam-nominal-range.html
@@ -72,8 +72,7 @@
           limits: {
             playbackRate:
                 {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat},
-            detune:
-                {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat}
+            detune: {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat}
           }
         },
         {
@@ -101,11 +100,21 @@
           creator: 'createBiquadFilter',
           args: [],
           limits: {
-            gain: {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat},
+            gain: {
+              minValue: -mostPositiveFloat,
+              // This complicated expression is used to get all the arithmetic
+              // to round to the correct single-precision float value for the
+              // desired max.  This also assumes that the implication computes
+              // the limit as 40 * log10f(std::numeric_limits<float>::max()).
+              maxValue:
+                  Math.fround(40 * Math.fround(Math.log10(mostPositiveFloat)))
+            },
             Q: {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat},
             frequency: {minValue: 0, maxValue: sampleRate / 2},
-            detune:
-                {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat}
+            detune: {
+              minValue: -Math.fround(1200 * Math.log2(mostPositiveFloat)),
+              maxValue: Math.fround(1200 * Math.log2(mostPositiveFloat))
+            }
           }
         },
         {
@@ -114,9 +123,8 @@
           limits: {
             frequency: {minValue: -sampleRate / 2, maxValue: sampleRate / 2},
             detune: {
-              // 3.4028..e38 is the most positive single float value.
-              minValue: -Math.fround(1200 * Math.log2(3.4028234663852886e38)),
-              maxValue: Math.fround(1200 * Math.log2(3.4028234663852886e38))
+              minValue: -Math.fround(1200 * Math.log2(mostPositiveFloat)),
+              maxValue: Math.fround(1200 * Math.log2(mostPositiveFloat))
             }
           }
         },
@@ -154,8 +162,7 @@
           creator: 'createConstantSource',
           args: [],
           limits: {
-            offset:
-                {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat}
+            offset: {minValue: -mostPositiveFloat, maxValue: mostPositiveFloat}
           }
         },
         // These nodes don't have AudioParams, but we want to test them anyway.
@@ -420,7 +427,7 @@
           if (clippingTested) {
             should(
                 isClipped,
-                prefix + 'was clipped to lie within the nominal range')
+                prefix + ' was clipped to lie within the nominal range')
                 .beEqualTo(true);
           }
 
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 58e65b98..91eb655 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
@@ -6234,6 +6234,7 @@
     getter negotiated
     getter onbufferedamountlow
     getter onclose
+    getter onclosing
     getter onerror
     getter onmessage
     getter onopen
@@ -6248,6 +6249,7 @@
     setter bufferedAmountLowThreshold
     setter onbufferedamountlow
     setter onclose
+    setter onclosing
     setter onerror
     setter onmessage
     setter onopen
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/ar_dom_overlay.https.html
similarity index 97%
rename from third_party/blink/web_tests/wpt_internal/webxr/ar_dom_overlay.https.html
rename to third_party/blink/web_tests/wpt_internal/webxr/ar/ar_dom_overlay.https.html
index 17c6295..d7f6dad 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/ar_dom_overlay.https.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script>let additionalChromiumResources = ["resources/xr-internal-device-mocking.js"];</script>
+<script>let additionalChromiumResources = ["../resources/xr-internal-device-mocking.js"];</script>
 <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>
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/ar_hittest.https.html b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittest.https.html
similarity index 95%
rename from third_party/blink/web_tests/wpt_internal/webxr/ar_hittest.https.html
rename to third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittest.https.html
index b661a39..df384490 100644
--- a/third_party/blink/web_tests/wpt_internal/webxr/ar_hittest.https.html
+++ b/third_party/blink/web_tests/wpt_internal/webxr/ar/ar_hittest.https.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script>let additionalChromiumResources = ["resources/xr-internal-device-mocking.js"];</script>
+<script>let additionalChromiumResources = ["../resources/xr-internal-device-mocking.js"];</script>
 <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>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ee7164f..76477596 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -5426,6 +5426,8 @@
   <int value="220" label="NC_SAME_DOCUMENT_POST_COMMIT_ERROR"/>
   <int value="221" label="RFH_INVALID_WEB_UI_CONTROLLER"/>
   <int value="222" label="RFPH_ADVANCE_FOCUS_INTO_PORTAL"/>
+  <int value="223" label="RFH_UNEXPECTED_EMBEDDING_TOKEN"/>
+  <int value="224" label="RFH_MISSING_EMBEDDING_TOKEN"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions">
@@ -18488,30 +18490,6 @@
   </int>
 </enum>
 
-<enum name="EnterpriseMacMDMStatusNew">
-  <summary>
-    The Mac MDM enrollment status (new API). See
-    https://blog.fleetsmith.com/what-is-user-approved-mdm-uamdm/ for more
-    details.
-  </summary>
-  <int value="0" label="API unavailable"/>
-  <int value="1" label="Unable to parse result"/>
-  <int value="2" label="No enrollment"/>
-  <int value="3" label="MDM enrollment (limited management capabilities)"/>
-  <int value="4" label="UAMDM enrollment (full management capabilities)"/>
-  <int value="5"
-      label="DEP Enrollment (automatically grants UAMDM status / full
-             management capabilities)"/>
-</enum>
-
-<enum name="EnterpriseMacMDMStatusOld">
-  <summary>The Mac MDM enrollment status (old API).</summary>
-  <int value="0" label="API unavailable"/>
-  <int value="1" label="Unable to parse result"/>
-  <int value="2" label="No enrollment"/>
-  <int value="3" label="MDM enrollment"/>
-</enum>
-
 <enum name="EnterprisePolicies">
 <!-- Generated from components/policy/resources/policy_templates.json -->
 
@@ -38659,6 +38637,7 @@
   <int value="787385958" label="RegionalLocalesAsDisplayUI:enabled"/>
   <int value="799680074" label="ContextualSearchTranslationModel:enabled"/>
   <int value="803282885" label="PreferHtmlOverPlugins:disabled"/>
+  <int value="805661595" label="ChromeosVideoDecoder:enabled"/>
   <int value="806035639" label="EnableNeuralPalmDetectionFilter:disabled"/>
   <int value="806334184" label="AndroidSpellChecker:enabled"/>
   <int value="807447752" label="ChromeMemex:disabled"/>
@@ -39139,6 +39118,7 @@
   <int value="1393722373" label="SaveEditedPDFForm:disabled"/>
   <int value="1397069250" label="NetworkService:disabled"/>
   <int value="1399950951" label="AutofillTokenPrefixMatching:disabled"/>
+  <int value="1399992739" label="ChromeosVideoDecoder:disabled"/>
   <int value="1403195370" label="ArcCupsApi:enabled"/>
   <int value="1405459667" label="enable-fast-text-autosizing"/>
   <int value="1406046556" label="enable-slimming-paint-v175"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 56626df..1b79afe 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -29368,6 +29368,54 @@
 </histogram>
 
 <histogram
+    name="CryptAuth.DeviceSyncV2.FeatureStatusSetter.ApiCallResult.SetFeatureStatuses"
+    enum="CryptAuthApiCallResult" expires_after="2020-12-15">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records the result of the async BatchSetFeatureStatuses API call to
+    CryptAuth. Recorded when the async callback is invoked or when the call
+    times out.
+  </summary>
+</histogram>
+
+<histogram
+    name="CryptAuth.DeviceSyncV2.FeatureStatusSetter.AsyncTaskResult.ClientAppMetadataFetch"
+    enum="CryptAuthAsyncTaskResult" expires_after="2020-12-15">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records the result of the async ClientAppMetadata retrieval for the
+    CryptAuth feature status setter. Recorded when the async callback is invoked
+    or when the call times out.
+  </summary>
+</histogram>
+
+<histogram
+    name="CryptAuth.DeviceSyncV2.FeatureStatusSetter.ExecutionTime.ClientAppMetadataFetch"
+    units="ms" expires_after="2020-12-15">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records the execution time of the async ClientAppMetadata retrieval for the
+    CryptAuth feature status setter. Recorded when the async callback is invoked
+    or when the call times out.
+  </summary>
+</histogram>
+
+<histogram
+    name="CryptAuth.DeviceSyncV2.FeatureStatusSetter.ExecutionTime.SetFeatureStatuses"
+    units="ms" expires_after="2020-12-15">
+  <owner>nohle@chromium.org</owner>
+  <owner>better-together-dev@google.com</owner>
+  <summary>
+    Records the execution time of the async BatchSetFeatureStatuses API call to
+    CryptAuth. Recorded when the async callback is invoked or when the call
+    times out.
+  </summary>
+</histogram>
+
+<histogram
     name="CryptAuth.DeviceSyncV2.GroupPrivateKeySharer.ExecutionTime.GroupPrivateKeyEncryption"
     units="ms" expires_after="2020-12-15">
   <owner>nohle@chromium.org</owner>
@@ -42515,47 +42563,6 @@
   </summary>
 </histogram>
 
-<histogram name="EnterpriseCheck.Mac.IsCurrentUserDomainUser" enum="Boolean"
-    expires_after="2020-07-01">
-  <owner>avi@chromium.org</owner>
-  <owner>pastarmovj@chromium.org</owner>
-  <summary>
-    On the Mac: Whether the current user has an enterprise identity in Open
-    Directory. This check is performed once at start-up.
-  </summary>
-</histogram>
-
-<histogram name="EnterpriseCheck.Mac.IsDeviceDomainJoined" enum="Boolean"
-    expires_after="2020-07-01">
-  <owner>avi@chromium.org</owner>
-  <owner>pastarmovj@chromium.org</owner>
-  <summary>
-    On the Mac: Whether the machine is joined to a domain. This check is
-    performed once at start-up.
-  </summary>
-</histogram>
-
-<histogram name="EnterpriseCheck.Mac.IsDeviceMDMEnrolledNew"
-    enum="EnterpriseMacMDMStatusNew" expires_after="2020-07-01">
-  <owner>avi@chromium.org</owner>
-  <owner>pastarmovj@chromium.org</owner>
-  <summary>
-    On the Mac: Whether the machine is managed via MDM, with data obtained via a
-    new method (profiles) that is only available in 10.13.4 or later. This check
-    is performed once at start-up.
-  </summary>
-</histogram>
-
-<histogram name="EnterpriseCheck.Mac.IsDeviceMDMEnrolledOld"
-    enum="EnterpriseMacMDMStatusOld" expires_after="2020-07-01">
-  <owner>avi@chromium.org</owner>
-  <owner>pastarmovj@chromium.org</owner>
-  <summary>
-    On the Mac: Whether the machine is managed via MDM, with data obtained via
-    an old method (system_profiler). This check is performed once at start-up.
-  </summary>
-</histogram>
-
 <histogram name="EnterpriseCheck.NetGetJoinInformationAddress"
     enum="BooleanEnabled" expires_after="2020-06-18">
   <owner>rogerta@chromium.org</owner>
@@ -123416,8 +123423,9 @@
 </histogram>
 
 <histogram name="Quota.EvictedBytesPerRound" units="MB"
-    expires_after="2020-01-26">
+    expires_after="2021-01-26">
   <owner>jarrydg@chromium.org</owner>
+  <owner>chrome-owp-storage@google.com</owner>
   <summary>
     Amount of usage used by evicted origins in an eviction round.
   </summary>
@@ -187082,11 +187090,9 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="RasterTaskType" separator=".">
-  <suffix name="" label="This metric includes both gpu and software raster.">
-    <obsolete>
-      Deprecated as of 02/2018. Using suffix Gpu and Software instead.
-    </obsolete>
-  </suffix>
+  <suffix base="true" name=""
+      label="This metric includes both gpu and software raster. Deprecated as
+             of 02/2018. Using suffix Gpu and Software instead."/>
   <suffix name="Gpu" label="This metric is for only gpu raster."/>
   <suffix name="Software" label="This metric is for only software raster."/>
   <affected-histogram name="Compositing.Browser.CachedImagesCount"/>
diff --git a/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py b/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
index 8824e00a..0c7a1d2 100644
--- a/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
+++ b/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from benchmarks import memory
 from contrib.cluster_telemetry import ct_benchmarks_util, page_set
 from core import perf_benchmark
 import py_utils
@@ -24,24 +25,41 @@
   def AddBenchmarkCommandLineArgs(cls, parser):
     ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
     parser.add_option(
-        '--verbose-cpu-metrics-for-adtagging',
+        '--verbose-cpu-metrics',
         action='store_true',
-        help='Enables non-UMA CPU metrics for the ad_tagging.cluster_telemetry '
-        'benchmark.')
+        help='Enables non-UMA CPU metrics.')
+    parser.add_option(
+        '--verbose-memory-metrics',
+        action='store_true',
+        help='Enables non-UMA memory metrics.')
 
   @classmethod
   def ProcessCommandLineArgs(cls, parser, args):
     ct_benchmarks_util.ValidateCommandLineArgs(parser, args)
-    cls.enable_limited_cpu_time_metric = args.verbose_cpu_metrics_for_adtagging
+    cls.enable_limited_cpu_time_metric = args.verbose_cpu_metrics
+    cls.enable_memory_metric = args.verbose_memory_metrics
 
   def GetExtraOutDirectories(self):
     # The indexed filter list does not end up in a build directory on cluster
     # telemetry; so we add its location here.
     return ['/b/s/w/ir/out/telemetry_isolates']
 
+  def SetExtraBrowserOptions(self, options):
+    if self.enable_memory_metric:
+      memory.SetExtraBrowserOptionsForMemoryMeasurement(options)
+
   def CreateCoreTimelineBasedMeasurementOptions(self):
     category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
-    tbm_options = timeline_based_measurement.Options(category_filter)
+    if self.enable_memory_metric:
+      tbm_options = memory.CreateCoreTimelineBasedMemoryMeasurementOptions()
+
+      # The memory options only include the filters needed for memory
+      # measurement. We reintroduce the filters required for other metrics.
+      tbm_options.ExtendTraceCategoryFilter(
+          category_filter.filter_string.split(','))
+    else:
+      tbm_options = timeline_based_measurement.Options(category_filter)
+
     uma_histograms = [
         'Ads.ResourceUsage.Size.Network.Mainframe.AdResource',
         'Ads.ResourceUsage.Size.Network.Mainframe.VanillaResource',
@@ -58,14 +76,15 @@
     for histogram in uma_histograms:
       tbm_options.config.chrome_trace_config.EnableUMAHistograms(histogram)
 
-    timeline_based_metrics = ['umaMetric']
+    tbm_options.AddTimelineBasedMetric('umaMetric')
     if self.enable_limited_cpu_time_metric:
-      timeline_based_metrics.append('limitedCpuTimeMetric')
+      tbm_options.AddTimelineBasedMetric('limitedCpuTimeMetric')
 
-    tbm_options.SetTimelineBasedMetrics(timeline_based_metrics)
     return tbm_options
 
   def CreateStorySet(self, options):
+    enable_memory_metric = self.enable_memory_metric
+
     def NavigateToPageAndLeavePage(self, action_runner):
       url = self.file_path_url_with_scheme if self.is_file else self.url
       action_runner.Navigate(url,
@@ -77,6 +96,10 @@
       except py_utils.TimeoutException:
         pass
 
+      # We measure memory after the wait as we want a proxy for page memory.
+      if enable_memory_metric:
+        action_runner.MeasureMemory(deterministic_mode=True)
+
       # Navigate away to an untracked page to trigger recording of page load
       # metrics
       action_runner.Navigate('about:blank',
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 3f1e02cf..5767acf4 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -1082,16 +1082,16 @@
     # to shards perf benchmarks on Win builders, reduce this hard timeout limit
     # to ~2 hrs.
     # Note that the builder seems to time out after 7 hours (crbug.com/1036447),
-    # so we must timeout the shards within ~5.5 hours to allow for other
+    # so we must timeout the shards within ~6 hours to allow for other
     # overhead. If the overall builder times out then we
     # don't get data even from the passing shards.
-    'hard_timeout': int(5.5 * 60 * 60), # 5.5 hours timeout for full suite
+    'hard_timeout': int(6 * 60 * 60), # 6 hours timeout for full suite
     'ignore_task_failure': False,
     # 5.5 hour timeout. Note that this is effectively the timeout for a
     # benchmarking subprocess to run since we intentionally do not stream
     # subprocess output to the task stdout.
     # TODO(crbug.com/865538): Reduce this once we can reduce hard_timeout.
-    'io_timeout': int(5.5 * 60 * 60),
+    'io_timeout': int(6 * 60 * 60),
     'dimension_sets': [
       tester_config['dimension']
     ],
diff --git a/tools/perf/core/shard_maps/timing_data/android-pixel2-perf-aab-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/android-pixel2-perf-aab-fyi_timing.json
index 989fa72..0637a08 100644
--- a/tools/perf/core/shard_maps/timing_data/android-pixel2-perf-aab-fyi_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/android-pixel2-perf-aab-fyi_timing.json
@@ -1,42 +1 @@
-[
-    {
-        "duration": "31.0",
-        "name": "rendering.mobile/balls_javascript_canvas"
-    },
-    {
-        "duration": "29.0",
-        "name": "rendering.mobile/canvas_05000_pixels_per_second"
-    },
-    {
-        "duration": "28.0",
-        "name": "rendering.mobile/css_value_type_shadow"
-    },
-    {
-        "duration": "29.0",
-        "name": "rendering.mobile/extra_large_texture_uploads"
-    },
-    {
-        "duration": "31.0",
-        "name": "rendering.mobile/main_30fps_impl_60fps"
-    },
-    {
-        "duration": "31.0",
-        "name": "rendering.mobile/motion_mark_canvas_fill_shapes"
-    },
-    {
-        "duration": "37.0",
-        "name": "rendering.mobile/new_tilings"
-    },
-    {
-        "duration": "28.0",
-        "name": "rendering.mobile/text_10000_pixels_per_second"
-    },
-    {
-        "duration": "30.0",
-        "name": "rendering.mobile/transform_transitions_js_block"
-    },
-    {
-        "duration": "29.0",
-        "name": "rendering.mobile/web_animations_staggered_infinite_iterations"
-    }
-]
\ No newline at end of file
+[]
\ No newline at end of file
diff --git a/tools/perf/generate_perf_sharding.py b/tools/perf/generate_perf_sharding.py
index 79141a491..84fccf669 100755
--- a/tools/perf/generate_perf_sharding.py
+++ b/tools/perf/generate_perf_sharding.py
@@ -422,7 +422,7 @@
           '`./generate_perf_sharding.py update-timing --filter-only` '
           'to regenerate it.'.format(cycletimes=_CYCLETIME_CONTRIBUTION))
 
-    builders = _GetBuilderPlatforms(builders=None, waterfall='perf')
+    builders = _GetBuilderPlatforms(builders=None, waterfall='all')
     for builder in builders:
       output_file = os.path.join(
           tempdir, os.path.basename(builder.timing_file_path))
diff --git a/tools/traffic_annotation/scripts/update_annotations_sheet.py b/tools/traffic_annotation/scripts/update_annotations_sheet.py
index 16880eb6..0a613b4b 100755
--- a/tools/traffic_annotation/scripts/update_annotations_sheet.py
+++ b/tools/traffic_annotation/scripts/update_annotations_sheet.py
@@ -273,14 +273,6 @@
       file_row = file_contents[row]
       sheet_row = sheet_contents[row]
 
-      # If the last column of the file_row is empty, the row belongs to a
-      # platform different from the one that TSV file is generated on, hence it
-      # should be ignored.
-      if not file_row[-1]:
-        if self.verbose:
-          print("Ignored from other platforms: %s" % file_contents[row][0])
-        continue
-
       major_update = False
       for col in range(len(file_row)):
         # Ignore 'Last Update' column for now.
@@ -349,11 +341,12 @@
     yield line.encode("utf-8")
 
 
-def LoadTSVFile(file_path):
+def LoadTSVFile(file_path, verbose):
   """ Loads annotations TSV file.
 
   Args:
     file_path: str Path to the TSV file.
+    verbose: bool Whether to print messages about ignored rows.
 
   Returns:
     list of list Table of loaded annotations.
@@ -363,7 +356,14 @@
     # CSV library does not support unicode, so encoding to utf-8 and back.
     reader = csv.reader(utf_8_encoder(csvfile), delimiter='\t')
     for row in reader:
-      rows.append([unicode(col, 'utf-8') for col in row])
+      row = [unicode(col, 'utf-8') for col in row]
+      # If the last column of the file_row is empty, the row belongs to a
+      # platform different from the one that TSV file is generated on, hence it
+      # should be ignored.
+      if row[-1]:
+        rows.append(row)
+      elif verbose:
+        print("Ignored from other platforms: %s" % row[0])
   return rows
 
 
@@ -416,7 +416,7 @@
     config = json.load(config_file)
 
   # Load and parse annotations file.
-  file_content = LoadTSVFile(args.annotations_file)
+  file_content = LoadTSVFile(args.annotations_file, args.verbose)
   if not file_content:
     print("Could not read annotations file.")
     return -1
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index efc671b8..3aa6763 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -23,18 +23,14 @@
 set_sources_assignment_filter([])
 
 mojom_component("ax_enums_mojo") {
-  sources = [
-    "ax_enums.mojom",
-  ]
+  sources = [ "ax_enums.mojom" ]
 
   macro_prefix = "UI_ACCESSIBILITY_AX_MOJOM"
   output_prefix = "ui_accessibility_ax_mojom"
 }
 
 mojom("ax_constants_mojo") {
-  sources = [
-    "ax_constants.mojom",
-  ]
+  sources = [ "ax_constants.mojom" ]
 }
 
 jumbo_component("accessibility") {
@@ -171,9 +167,7 @@
 
   defines = [ "ACCESSIBILITY_IMPLEMENTATION" ]
 
-  deps = [
-    "//third_party/cld_3/src/src:cld_3",
-  ]
+  deps = [ "//third_party/cld_3/src/src:cld_3" ]
 
   public_deps = [
     ":ax_constants_mojo",
@@ -235,9 +229,7 @@
     "ax_assistant_structure.cc",
     "ax_assistant_structure.h",
   ]
-  deps = [
-    ":accessibility",
-  ]
+  deps = [ ":accessibility" ]
 }
 
 static_library("test_support") {
@@ -249,9 +241,7 @@
     "tree_generator.h",
   ]
 
-  deps = [
-    ":accessibility",
-  ]
+  deps = [ ":accessibility" ]
 }
 
 test("accessibility_unittests") {
@@ -340,32 +330,22 @@
 }
 
 fuzzer_test("ax_tree_fuzzer") {
-  sources = [
-    "ax_tree_fuzzer.cc",
-  ]
+  sources = [ "ax_tree_fuzzer.cc" ]
 
-  deps = [
-    ":accessibility",
-  ]
+  deps = [ ":accessibility" ]
 }
 
 fuzzer_test("ax_table_fuzzer") {
-  sources = [
-    "ax_table_fuzzer.cc",
-  ]
+  sources = [ "ax_table_fuzzer.cc" ]
 
-  deps = [
-    ":accessibility",
-  ]
+  deps = [ ":accessibility" ]
 
   seed_corpus = "fuzz_corpus"
 }
 
 test("accessibility_perftests") {
   testonly = true
-  sources = [
-    "ax_node_position_perftest.cc",
-  ]
+  sources = [ "ax_node_position_perftest.cc" ]
 
   deps = [
     "//base",
diff --git a/ui/accessibility/extensions/BUILD.gn b/ui/accessibility/extensions/BUILD.gn
index 1ab11f3a..d824a5b 100644
--- a/ui/accessibility/extensions/BUILD.gn
+++ b/ui/accessibility/extensions/BUILD.gn
@@ -17,9 +17,7 @@
 group("extension_tests") {
   testonly = true
   if (is_chromeos) {
-    deps = [
-      "chromevoxclassic:chromevox_tests",
-    ]
+    deps = [ "chromevoxclassic:chromevox_tests" ]
   }
 }
 
@@ -115,9 +113,7 @@
 
 copy("colorenhancer_copy") {
   sources = colorenhancer_files
-  outputs = [
-    "$root_out_dir/{{source_target_relative}}",
-  ]
+  outputs = [ "$root_out_dir/{{source_target_relative}}" ]
 }
 
 #
@@ -157,7 +153,5 @@
 
 copy("caretbrowsing_copy") {
   sources = caretbrowsing_files
-  outputs = [
-    "$root_out_dir/caretbrowsing/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/caretbrowsing/{{source_file_part}}" ]
 }
diff --git a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
index 11dc7ec..501aeeb 100644
--- a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
+++ b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
@@ -361,12 +361,8 @@
       version_file,
       version_script,
     ]
-    sources = [
-      template_file,
-    ]
-    outputs = [
-      output_file,
-    ]
+    sources = [ template_file ]
+    outputs = [ output_file ]
     args = [
       "--key=$key",
       "--version_file=" + rebase_path(version_file, root_build_dir),
@@ -394,9 +390,7 @@
     script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_deps.py"
     inputs = jsbundler_modules
     sources = invoker.sources
-    outputs = [
-      invoker.output_file,
-    ]
+    outputs = [ invoker.output_file ]
     args = [
       "-o",
       rebase_path(invoker.output_file, root_build_dir),
@@ -425,30 +419,22 @@
 }
 
 compress_js("chromevox_content_script") {
-  sources = [
-    chromevox_content_script_loader_file,
-  ]
+  sources = [ chromevox_content_script_loader_file ]
   output_file = "$chromevox_out_dir/chromeVoxChromePageScript.js"
 }
 
 compress_js("chromevox_kbexplorer_script") {
-  sources = [
-    chromevox_kbexplorer_loader_file,
-  ]
+  sources = [ chromevox_kbexplorer_loader_file ]
   output_file = "$chromevox_out_dir/chromeVoxKbExplorerScript.js"
 }
 
 compress_js("chromevox_options_script") {
-  sources = [
-    chromevox_options_script_loader_file,
-  ]
+  sources = [ chromevox_options_script_loader_file ]
   output_file = "$chromevox_out_dir/chromeVoxChromeOptionsScript.js"
 }
 
 compress_js("chromevox_background_script") {
-  sources = [
-    chromevox_background_script_loader_file,
-  ]
+  sources = [ chromevox_background_script_loader_file ]
   output_file = "$chromevox_out_dir/chromeVox2ChromeBackgroundScript.js"
 }
 
@@ -458,16 +444,10 @@
 
 action("chromevox_test_messages_js") {
   script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py"
-  sources = [
-    "$chromevox_out_dir/_locales/en/messages.json.gz",
-  ]
+  sources = [ "$chromevox_out_dir/_locales/en/messages.json.gz" ]
   output_file = "$root_out_dir/test_data/ui/accessibility/extensions/chromevoxclassic/host/testing/test_messages.js"
-  outputs = [
-    output_file,
-  ]
-  deps = [
-    ":chromevox_strings",
-  ]
+  outputs = [ output_file ]
+  deps = [ ":chromevox_strings" ]
   args = [
            "-o",
            rebase_path(output_file, root_build_dir),
@@ -491,15 +471,11 @@
     rebase_path("//", root_build_dir) + ":",
     rebase_path("$root_out_dir/test_data", root_build_dir) + ":",
   ]
-  deps = [
-    ":chromevox_test_messages_js",
-  ]
+  deps = [ ":chromevox_test_messages_js" ]
 }
 
 js_library("tree_walker") {
-  sources = [
-    "cvox2/background/tree_walker.js",
-  ]
+  sources = [ "cvox2/background/tree_walker.js" ]
   deps = [
     ":automation_predicate",
     ":constants",
@@ -511,12 +487,8 @@
 }
 
 js_library("automation_predicate") {
-  sources = [
-    "cvox2/background/automation_predicate.js",
-  ]
-  deps = [
-    ":constants",
-  ]
+  sources = [ "cvox2/background/automation_predicate.js" ]
+  deps = [ ":constants" ]
   externs_list = [
     "$externs_path/automation.js",
     "$externs_path/chrome_extensions.js",
@@ -524,9 +496,7 @@
 }
 
 js_library("constants") {
-  sources = [
-    "cvox2/background/constants.js",
-  ]
+  sources = [ "cvox2/background/constants.js" ]
 }
 
 test("chromevox_tests") {
@@ -623,8 +593,6 @@
 
   test_deps_js_outputs = get_target_outputs(":chromevox_test_deps_js")
   deps_js = test_deps_js_outputs[0]
-  deps = [
-    ":chromevox_test_deps_js",
-  ]
+  deps = [ ":chromevox_test_deps_js" ]
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 }
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
index 025a82c..d7b79feb 100644
--- a/ui/base/accelerators/accelerator.cc
+++ b/ui/base/accelerators/accelerator.cc
@@ -133,6 +133,10 @@
   return (modifiers_ & EF_ALT_DOWN) != 0;
 }
 
+bool Accelerator::IsAltGrDown() const {
+  return (modifiers_ & EF_ALTGR_DOWN) != 0;
+}
+
 bool Accelerator::IsCmdDown() const {
   return (modifiers_ & EF_COMMAND_DOWN) != 0;
 }
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
index 7083dc1..0949568d1 100644
--- a/ui/base/accelerators/accelerator.h
+++ b/ui/base/accelerators/accelerator.h
@@ -83,6 +83,7 @@
   bool IsShiftDown() const;
   bool IsCtrlDown() const;
   bool IsAltDown() const;
+  bool IsAltGrDown() const;
   bool IsCmdDown() const;
   bool IsRepeat() const;
 
diff --git a/ui/base/accelerators/mojom/BUILD.gn b/ui/base/accelerators/mojom/BUILD.gn
index a96f8ea7..03a7b86 100644
--- a/ui/base/accelerators/mojom/BUILD.gn
+++ b/ui/base/accelerators/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "accelerator.mojom",
-  ]
+  sources = [ "accelerator.mojom" ]
   public_deps = [
     "//mojo/public/mojom/base",
     "//ui/events/mojom",
@@ -15,9 +13,7 @@
 }
 
 source_set("mojom_traits") {
-  sources = [
-    "accelerator_mojom_traits.h",
-  ]
+  sources = [ "accelerator_mojom_traits.h" ]
   public_deps = [
     ":mojom_shared_cpp_sources",
     "//mojo/public/mojom/base",
@@ -28,9 +24,7 @@
 
 source_set("unittests") {
   testonly = true
-  sources = [
-    "accelerator_mojom_traits_unittest.cc",
-  ]
+  sources = [ "accelerator_mojom_traits_unittest.cc" ]
   deps = [
     ":mojom",
     ":mojom_traits",
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
index e87d38c2..d351168 100644
--- a/ui/base/idle/BUILD.gn
+++ b/ui/base/idle/BUILD.gn
@@ -22,9 +22,7 @@
   # All targets in this file are allowed to access any of the headers.
   friend = [ ":*" ]
 
-  public = [
-    "idle.h",
-  ]
+  public = [ "idle.h" ]
 
   deps = [
     "//base",
diff --git a/ui/base/mojom/BUILD.gn b/ui/base/mojom/BUILD.gn
index c36b9a5..0bc88eb 100644
--- a/ui/base/mojom/BUILD.gn
+++ b/ui/base/mojom/BUILD.gn
@@ -22,9 +22,7 @@
 
 source_set("unittests") {
   testonly = true
-  sources = [
-    "cursor_mojom_traits_unittest.cc",
-  ]
+  sources = [ "cursor_mojom_traits_unittest.cc" ]
   deps = [
     ":mojom",
     "//skia/public/mojom",
diff --git a/ui/content_accelerators/BUILD.gn b/ui/content_accelerators/BUILD.gn
index 74e8747a..ce101e7 100644
--- a/ui/content_accelerators/BUILD.gn
+++ b/ui/content_accelerators/BUILD.gn
@@ -15,7 +15,5 @@
     "//ui/events/blink",
   ]
 
-  public_deps = [
-    "//content/public/browser",
-  ]
+  public_deps = [ "//content/public/browser" ]
 }
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn
index 462a01c..97286c83 100644
--- a/ui/display/BUILD.gn
+++ b/ui/display/BUILD.gn
@@ -122,9 +122,7 @@
 
   defines = [ "DISPLAY_IMPLEMENTATION" ]
 
-  public_deps = [
-    "//ui/display/manager",
-  ]
+  public_deps = [ "//ui/display/manager" ]
 
   deps = [
     "//base",
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm
index b19c27f..494843e9 100644
--- a/ui/display/mac/screen_mac.mm
+++ b/ui/display/mac/screen_mac.mm
@@ -108,14 +108,6 @@
 
   display.set_color_depth(Display::kDefaultBitsPerPixel);
   display.set_depth_per_component(Display::kDefaultBitsPerComponent);
-  if ([screen respondsToSelector:@selector
-              (maximumPotentialExtendedDynamicRangeColorComponentValue)]) {
-    if ([screen maximumPotentialExtendedDynamicRangeColorComponentValue] >=
-        2.0) {
-      display.set_color_depth(Display::kHDR10BitsPerPixel);
-      display.set_depth_per_component(Display::kHDR10BitsPerComponent);
-    }
-  }
   display.set_is_monochrome(CGDisplayUsesForceToGray());
 
   if (auto display_link = ui::DisplayLinkMac::GetForDisplay(display_id))
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
index c158f65..d98485a 100644
--- a/ui/display/manager/BUILD.gn
+++ b/ui/display/manager/BUILD.gn
@@ -52,9 +52,7 @@
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  public_deps = [
-    "//ui/display",
-  ]
+  public_deps = [ "//ui/display" ]
 
   deps = [
     "//base",
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 7ab0113..7a904c3 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -32,12 +32,8 @@
   keycode_conversion_data_android_gen_path = "$target_gen_dir/keycodes/dom/keycode_conversion_data_android_generated.inc"
 
   copy("keycode_conversion_data_android") {
-    sources = [
-      keycode_conversion_data_android_path,
-    ]
-    outputs = [
-      keycode_conversion_data_android_gen_path,
-    ]
+    sources = [ keycode_conversion_data_android_path ]
+    outputs = [ keycode_conversion_data_android_gen_path ]
   }
 }
 
@@ -55,9 +51,7 @@
     "keycodes/dom/keycode_converter.cc",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   if (!is_ios) {
     deps += [ "//ipc:param_traits" ]
@@ -118,15 +112,11 @@
 }
 
 source_set("event_constants") {
-  sources = [
-    "event_constants.h",
-  ]
+  sources = [ "event_constants.h" ]
 }
 
 source_set("platform_event") {
-  sources = [
-    "platform_event.h",
-  ]
+  sources = [ "platform_event.h" ]
 }
 
 jumbo_component("events_base") {
@@ -645,9 +635,7 @@
       sources += [ "android/motion_event_android_unittest.cc" ]
       deps += [ "//ui/android:ui_full_java" ]
     } else {
-      data_deps = [
-        "//third_party/mesa_headers",
-      ]
+      data_deps = [ "//third_party/mesa_headers" ]
     }
 
     if (use_x11) {
@@ -724,9 +712,7 @@
 source_set("events_interactive_ui_tests") {
   testonly = true
   if (is_win) {
-    sources = [
-      "win/media_keyboard_hook_win_interactive_test.cc",
-    ]
+    sources = [ "win/media_keyboard_hook_win_interactive_test.cc" ]
 
     deps = [
       ":events",
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js
index 5117a5c..2954930 100644
--- a/ui/file_manager/integration_tests/file_manager/quick_view.js
+++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -1200,6 +1200,82 @@
   };
 
   /**
+   * Tests that Quick View opens with multiple files selected.
+   */
+  testcase.openQuickViewWithMultipleFiles = async () => {
+    const caller = getCaller();
+
+    /**
+     * The <webview> resides in the <files-safe-media type="image"> shadow DOM,
+     * which is a child of the #quick-view shadow DOM.
+     */
+    const webView =
+        ['#quick-view', 'files-safe-media[type="image"]', 'webview'];
+
+    // Open Files app on Downloads containing BASIC_LOCAL_ENTRY_SET.
+    const appId = await setupAndWaitUntilReady(
+        RootPath.DOWNLOADS, BASIC_LOCAL_ENTRY_SET, []);
+
+    // Add item 3 to the check-selection, ENTRIES.desktop.
+    const downKey = ['#file-list', 'ArrowDown', false, false, false];
+    for (let i = 0; i < 3; i++) {
+      chrome.test.assertTrue(
+          !!await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, downKey),
+          'ArrowDown failed');
+    }
+    const ctrlSpace = ['#file-list', ' ', true, false, false];
+    chrome.test.assertTrue(
+        !!await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, ctrlSpace),
+        'Ctrl+Space failed');
+
+    // Add item 5 to the check-selection, ENTRIES.hello.
+    const ctrlDown = ['#file-list', 'ArrowDown', true, false, false];
+    for (let i = 0; i < 2; i++) {
+      chrome.test.assertTrue(
+          !!await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, ctrlDown),
+          'Ctrl+ArrowDown failed');
+    }
+    chrome.test.assertTrue(
+        !!await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, ctrlSpace),
+        'Ctrl+Space failed');
+
+    // Check: both items should be selected.
+    const selectedRows = await remoteCall.callRemoteTestUtil(
+        'deepQueryAllElements', appId, ['#file-list li[selected]']);
+    chrome.test.assertEq(2, selectedRows.length);
+    chrome.test.assertTrue(
+        selectedRows[0].attributes['file-name'].includes(['Desktop']));
+    chrome.test.assertTrue(
+        selectedRows[1].attributes['file-name'].includes(['hello']));
+
+    // Open Quick View via its keyboard shortcut.
+    const space = ['#file-list', ' ', false, false, false];
+    await remoteCall.callRemoteTestUtil('fakeKeyDown', appId, space);
+
+    // Wait for the Quick View <webview> to load and display its content.
+    function checkWebViewImageLoaded(elements) {
+      let haveElements = Array.isArray(elements) && elements.length === 1;
+      if (haveElements) {
+        haveElements = elements[0].styles.display.includes('block');
+      }
+      if (!haveElements || elements[0].attributes.loaded !== '') {
+        return pending(caller, 'Waiting for <webview> to load.');
+      }
+      return;
+    }
+
+    // Check: ENTRIES.desktop should be displayed in the webview.
+    await repeatUntil(async () => {
+      return checkWebViewImageLoaded(await remoteCall.callRemoteTestUtil(
+          'deepQueryAllElements', appId, [webView, ['display']]));
+    });
+
+    // Check: the correct file mimeType should be displayed.
+    const mimeType = await getQuickViewMetadataBoxField(appId, 'Type');
+    chrome.test.assertEq('image/png', mimeType);
+  };
+
+  /**
    * Tests opening Quick View and closing with Escape key returns focus to file
    * list.
    */
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js
index 9d65335..3e33256 100644
--- a/ui/file_manager/integration_tests/remote_call.js
+++ b/ui/file_manager/integration_tests/remote_call.js
@@ -55,8 +55,8 @@
  * registerRemoteTestUtils in test_util_base.js.
  *
  * @param {string} func Function name.
- * @param {?string} appId Target window's App ID or null for functions
- *     not requiring a window.
+ * @param {?string} appId App window Id or null for functions not requiring a
+ *     window.
  * @param {Array<*>} args Array of arguments.
  * @param {function(*)=} opt_callback Callback handling the function's result.
  * @return {!Promise} Promise to be fulfilled with the result of the remote
@@ -130,15 +130,15 @@
 /**
  * Closes a window and waits until the window is closed.
  *
- * @param {string} windowId ID of the window to close.
+ * @param {string} appId App window Id.
  * @return {Promise} promise Promise to be fulfilled with the result (true:
  *     success, false: failed).
  */
-RemoteCall.prototype.closeWindowAndWait = async function(windowId) {
+RemoteCall.prototype.closeWindowAndWait = async function(appId) {
   const caller = getCaller();
 
   // Closes the window.
-  if (!await this.callRemoteTestUtil('closeWindow', null, [windowId])) {
+  if (!await this.callRemoteTestUtil('closeWindow', null, [appId])) {
     // Returns false when the closing is failed.
     return false;
   }
@@ -146,10 +146,10 @@
   return repeatUntil(async () => {
     const windows = await this.callRemoteTestUtil('getWindows', null, []);
     for (const id in windows) {
-      if (id === windowId) {
+      if (id === appId) {
         // Window is still available. Continues waiting.
         return pending(
-            caller, 'Window with the prefix %s is not found.', windowId);
+            caller, 'Window with the prefix %s is not found.', appId);
       }
     }
     // Window is not available. Closing is done successfully.
@@ -159,42 +159,42 @@
 
 /**
  * Waits until the window turns to the given size.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {number} width Requested width in pixels.
  * @param {number} height Requested height in pixels.
  */
-RemoteCall.prototype.waitForWindowGeometry = function(windowId, width, height) {
+RemoteCall.prototype.waitForWindowGeometry = function(appId, width, height) {
   const caller = getCaller();
   return repeatUntil(async () => {
     const windows = await this.callRemoteTestUtil('getWindows', null, []);
-    if (!windows[windowId]) {
-      return pending(caller, 'Window %s is not found.', windowId);
+    if (!windows[appId]) {
+      return pending(caller, 'Window %s is not found.', appId);
     }
-    if (windows[windowId].outerWidth !== width ||
-        windows[windowId].outerHeight !== height) {
+    if (windows[appId].outerWidth !== width ||
+        windows[appId].outerHeight !== height) {
       return pending(
           caller, 'Expected window size is %j, but it is %j',
-          {width: width, height: height}, windows[windowId]);
+          {width: width, height: height}, windows[appId]);
     }
   });
 };
 
 /**
  * Waits for the specified element appearing in the DOM.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
  *     the first element, and so on.
  * @return {Promise} Promise to be fulfilled when the element appears.
  */
-RemoteCall.prototype.waitForElement = function(windowId, query) {
-  return this.waitForElementStyles(windowId, query, []);
+RemoteCall.prototype.waitForElement = function(appId, query) {
+  return this.waitForElementStyles(appId, query, []);
 };
 
 /**
  * Waits for the specified element appearing in the DOM.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
@@ -204,12 +204,11 @@
  *     TODO(lucmult): Add a typedef for the returned object.
  * @return {Promise} Promise to be fulfilled when the element appears.
  */
-RemoteCall.prototype.waitForElementStyles = function(
-    windowId, query, styleNames) {
+RemoteCall.prototype.waitForElementStyles = function(appId, query, styleNames) {
   const caller = getCaller();
   return repeatUntil(async () => {
     const elements = await this.callRemoteTestUtil(
-        'deepQueryAllElements', windowId, [query, styleNames]);
+        'deepQueryAllElements', appId, [query, styleNames]);
     if (elements.length > 0) {
       return elements[0];
     }
@@ -221,9 +220,9 @@
  * Waits for a remote test function to return a specific result.
  *
  * @param {string} funcName Name of remote test function to be executed.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {function(Object): boolean|Object} expectedResult An value to be
- *     checked against the return value of |funcName| or a callabck that
+ *     checked against the return value of |funcName| or a callback that
  *     receives the return value of |funcName| and returns true if the result
  *     is the expected value.
  * @param {?Array<*>} args Arguments to be provided to |funcName| when executing
@@ -231,12 +230,11 @@
  * @return {Promise} Promise to be fulfilled when the |expectedResult| is
  *     returned from |funcName| execution.
  */
-RemoteCall.prototype.waitFor = function(
-    funcName, windowId, expectedResult, args) {
+RemoteCall.prototype.waitFor = function(funcName, appId, expectedResult, args) {
   const caller = getCaller();
   args = args || [];
   return repeatUntil(async () => {
-    const result = await this.callRemoteTestUtil(funcName, windowId, args);
+    const result = await this.callRemoteTestUtil(funcName, appId, args);
     if (typeof expectedResult === 'function' && expectedResult(result)) {
       return result;
     }
@@ -252,18 +250,18 @@
 
 /**
  * Waits for the specified element leaving from the DOM.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
  *     the first element, and so on.
  * @return {Promise} Promise to be fulfilled when the element is lost.
  */
-RemoteCall.prototype.waitForElementLost = function(windowId, query) {
+RemoteCall.prototype.waitForElementLost = function(appId, query) {
   const caller = getCaller();
   return repeatUntil(async () => {
-    const elements = await this.callRemoteTestUtil(
-        'deepQueryAllElements', windowId, [query]);
+    const elements =
+        await this.callRemoteTestUtil('deepQueryAllElements', appId, [query]);
     if (elements.length > 0) {
       return pending(caller, 'Elements %j is still exists.', elements);
     }
@@ -273,7 +271,7 @@
 
 /**
  * Sends a fake key down event.
- * @param {string} windowId Window ID.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
@@ -286,9 +284,9 @@
  *     result.
  */
 RemoteCall.prototype.fakeKeyDown =
-    async function(windowId, query, key, ctrlKey, shiftKey, altKey) {
+    async function(appId, query, key, ctrlKey, shiftKey, altKey) {
   const result = await this.callRemoteTestUtil(
-      'fakeKeyDown', windowId, [query, key, ctrlKey, shiftKey, altKey]);
+      'fakeKeyDown', appId, [query, key, ctrlKey, shiftKey, altKey]);
   if (result) {
     return true;
   } else {
@@ -327,7 +325,7 @@
 
 /**
  * Shorthand for clicking an element.
- * @param {string} windowId Window id.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
@@ -337,17 +335,17 @@
  * @return {Promise} Promise to be fulfilled with the clicked element.
  */
 RemoteCall.prototype.waitAndClickElement =
-    async function(windowId, query, opt_keyModifiers) {
-  const element = await this.waitForElement(windowId, query);
+    async function(appId, query, opt_keyModifiers) {
+  const element = await this.waitForElement(appId, query);
   const result = await this.callRemoteTestUtil(
-      'fakeMouseClick', windowId, [query, opt_keyModifiers]);
+      'fakeMouseClick', appId, [query, opt_keyModifiers]);
   chrome.test.assertTrue(result, 'mouse click failed.');
   return element;
 };
 
 /**
  * Shorthand for right-clicking an element.
- * @param {string} windowId Window id.
+ * @param {string} appId App window Id.
  * @param {string|!Array<string>} query Query to specify the element.
  *     If query is an array, |query[0]| specifies the first
  *     element(s), |query[1]| specifies elements inside the shadow DOM of
@@ -357,31 +355,31 @@
  * @return {Promise} Promise to be fulfilled with the clicked element.
  */
 RemoteCall.prototype.waitAndRightClick =
-    async function(windowId, query, opt_keyModifiers) {
-  const element = await this.waitForElement(windowId, query);
+    async function(appId, query, opt_keyModifiers) {
+  const element = await this.waitForElement(appId, query);
   const result = await this.callRemoteTestUtil(
-      'fakeMouseRightClick', windowId, [query, opt_keyModifiers]);
+      'fakeMouseRightClick', appId, [query, opt_keyModifiers]);
   chrome.test.assertTrue(result, 'mouse right-click failed.');
   return element;
 };
 
 /**
  * Shorthand for focusing an element.
- * @param {string} windowId Window id.
+ * @param {string} appId App window Id.
  * @param {!Array<string>} query Query to specify the element to be focused.
  * @return {Promise} Promise to be fulfilled with the focused element.
  */
-RemoteCall.prototype.focus = async function(windowId, query) {
-  const element = await this.waitForElement(windowId, query);
-  const result = await this.callRemoteTestUtil('focus', windowId, query);
+RemoteCall.prototype.focus = async function(appId, query) {
+  const element = await this.waitForElement(appId, query);
+  const result = await this.callRemoteTestUtil('focus', appId, query);
   chrome.test.assertTrue(result, 'focus failed.');
   return element;
 };
 
 /**
  * Simulate Click in the UI in the middle of the element.
- * @param{string} appId ID of the app that contains the element. NOTE: The click
- *     is simulated on most recent window in the window system.
+ * @param{string} appId App window ID contains the element. NOTE: The click is
+ * simulated on most recent window in the window system.
  * @param {string|!Array<string>} query Query to the element to be clicked.
  * @return {!Promise} A promise fulfilled after the click event.
  */
@@ -413,7 +411,7 @@
 
 /**
  * Waits for the file list turns to the given contents.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {Array<Array<string>>} expected Expected contents of file list.
  * @param {{orderCheck:?boolean, ignoreLastModifiedTime:?boolean}=} opt_options
  *     Options of the comparison. If orderCheck is true, it also compares the
@@ -423,11 +421,11 @@
  *     given contents.
  */
 RemoteCallFilesApp.prototype.waitForFiles = function(
-    windowId, expected, opt_options) {
+    appId, expected, opt_options) {
   const options = opt_options || {};
   const caller = getCaller();
   return repeatUntil(async () => {
-    const files = await this.callRemoteTestUtil('getFileList', windowId, []);
+    const files = await this.callRemoteTestUtil('getFileList', appId, []);
     if (!options.orderCheck) {
       files.sort();
       expected.sort();
@@ -459,15 +457,15 @@
  * number.
  * TODO(hirono): Remove the function.
  *
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {number} lengthBefore Number of items visible before.
  * @return {Promise} Promise to be fulfilled with the contents of files.
  */
 RemoteCallFilesApp.prototype.waitForFileListChange = function(
-    windowId, lengthBefore) {
+    appId, lengthBefore) {
   const caller = getCaller();
   return repeatUntil(async () => {
-    const files = await this.callRemoteTestUtil('getFileList', windowId, []);
+    const files = await this.callRemoteTestUtil('getFileList', appId, []);
     files.sort();
 
     const notReadyRows =
@@ -485,17 +483,16 @@
 
 /**
  * Waits until the given taskId appears in the executed task list.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string} taskId Task ID to watch.
  * @return {Promise} Promise to be fulfilled when the task appears in the
  *     executed task list.
  */
-RemoteCallFilesApp.prototype.waitUntilTaskExecutes = function(
-    windowId, taskId) {
+RemoteCallFilesApp.prototype.waitUntilTaskExecutes = function(appId, taskId) {
   const caller = getCaller();
   return repeatUntil(async () => {
     const executedTasks =
-        await this.callRemoteTestUtil('getExecutedTasks', windowId, []);
+        await this.callRemoteTestUtil('getExecutedTasks', appId, []);
     if (executedTasks.indexOf(taskId) === -1) {
       return pending(caller, 'Executed task is %j', executedTasks);
     }
@@ -504,20 +501,20 @@
 
 /**
  * Check if the next tabforcus'd element has the given ID or not.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string} elementId String of 'id' attribute which the next tabfocus'd
  *     element should have.
  * @return {Promise} Promise to be fulfilled with the result.
  */
 RemoteCallFilesApp.prototype.checkNextTabFocus =
-    async function(windowId, elementId) {
+    async function(appId, elementId) {
   const result = await sendTestMessage({name: 'dispatchTabKey'});
   chrome.test.assertEq(result, 'tabKeyDispatched', 'Tab key dispatch failure');
 
   const caller = getCaller();
   return repeatUntil(async () => {
     const element =
-        await this.callRemoteTestUtil('getActiveElement', windowId, []);
+        await this.callRemoteTestUtil('getActiveElement', appId, []);
     if (element && element.attributes['id'] === elementId) {
       return true;
     }
@@ -530,17 +527,16 @@
 
 /**
  * Waits until the current directory is changed.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string} expectedPath Path to be changed to.
  * @return {Promise} Promise to be fulfilled when the current directory is
  *     changed to expectedPath.
  */
 RemoteCallFilesApp.prototype.waitUntilCurrentDirectoryIsChanged = function(
-    windowId, expectedPath) {
+    appId, expectedPath) {
   const caller = getCaller();
   return repeatUntil(async () => {
-    const path =
-        await this.callRemoteTestUtil('getBreadcrumbPath', windowId, []);
+    const path = await this.callRemoteTestUtil('getBreadcrumbPath', appId, []);
     if (path !== expectedPath) {
       return pending(caller, 'Expected path is %s got %s', expectedPath, path);
     }
@@ -549,17 +545,17 @@
 
 /**
  * Expands tree item.
- * @param {string} windowId Target window ID.
+ * @param {string} appId App window Id.
  * @param {string} query Query to the <tree-item> element.
  */
 RemoteCallFilesApp.prototype.expandTreeItemInDirectoryTree =
-    async function(windowId, query) {
-  await this.waitForElement(windowId, query);
+    async function(appId, query) {
+  await this.waitForElement(appId, query);
   const elements = await this.callRemoteTestUtil(
-      'queryAllElements', windowId, [`${query}[expanded]`]);
+      'queryAllElements', appId, [`${query}[expanded]`]);
   // If it's already expanded just set the focus on directory tree.
   if (elements.length > 0) {
-    return this.callRemoteTestUtil('focus', windowId, ['#directory-tree']);
+    return this.callRemoteTestUtil('focus', appId, ['#directory-tree']);
   }
 
   // We must wait until <tree-item> has attribute [has-children=true]
@@ -568,59 +564,59 @@
   // operation since the [expanded] checks above.
   const expandIcon =
       query + ':not([expanded]) > .tree-row[has-children=true] > .expand-icon';
-  await this.waitAndClickElement(windowId, expandIcon);
+  await this.waitAndClickElement(appId, expandIcon);
   // Wait for the expansion to finish.
-  await this.waitForElement(windowId, query + '[expanded]');
+  await this.waitForElement(appId, query + '[expanded]');
   // Force the focus on directory tree.
-  await this.callRemoteTestUtil('focus', windowId, ['#directory-tree']);
+  await this.callRemoteTestUtil('focus', appId, ['#directory-tree']);
 };
 
 /**
  * Expands directory tree for specified path.
  */
 RemoteCallFilesApp.prototype.expandDirectoryTreeFor = function(
-    windowId, path, volumeType = 'downloads') {
+    appId, path, volumeType = 'downloads') {
   return this.expandDirectoryTreeForInternal_(
-      windowId, path.split('/'), 0, volumeType);
+      appId, path.split('/'), 0, volumeType);
 };
 
 /**
  * Internal function for expanding directory tree for specified path.
  */
 RemoteCallFilesApp.prototype.expandDirectoryTreeForInternal_ =
-    async function(windowId, components, index, volumeType) {
+    async function(appId, components, index, volumeType) {
   if (index >= components.length - 1) {
     return;
   }
 
   // First time we should expand the root/volume first.
   if (index === 0) {
-    await this.expandVolumeInDirectoryTree(windowId, volumeType);
+    await this.expandVolumeInDirectoryTree(appId, volumeType);
     return this.expandDirectoryTreeForInternal_(
-        windowId, components, index + 1, volumeType);
+        appId, components, index + 1, volumeType);
   }
   const path = '/' + components.slice(1, index + 1).join('/');
   await this.expandTreeItemInDirectoryTree(
-      windowId, `[full-path-for-testing="${path}"]`);
+      appId, `[full-path-for-testing="${path}"]`);
   await this.expandDirectoryTreeForInternal_(
-      windowId, components, index + 1, volumeType);
+      appId, components, index + 1, volumeType);
 };
 
 /**
  * Expands download volume in directory tree.
  */
 RemoteCallFilesApp.prototype.expandDownloadVolumeInDirectoryTree = function(
-    windowId) {
-  return this.expandVolumeInDirectoryTree(windowId, 'downloads');
+    appId) {
+  return this.expandVolumeInDirectoryTree(appId, 'downloads');
 };
 
 /**
  * Expands download volume in directory tree.
  */
 RemoteCallFilesApp.prototype.expandVolumeInDirectoryTree = function(
-    windowId, volumeType) {
+    appId, volumeType) {
   return this.expandTreeItemInDirectoryTree(
-      windowId, `[volume-type-for-testing="${volumeType}"]`);
+      appId, `[volume-type-for-testing="${volumeType}"]`);
 };
 
 /**
@@ -630,12 +626,12 @@
  * crbug.com/996626.
  */
 RemoteCallFilesApp.prototype.navigateWithDirectoryTree =
-    async function(windowId, path, rootLabel, volumeType = 'downloads') {
-  await this.expandDirectoryTreeFor(windowId, path, volumeType);
+    async function(appId, path, rootLabel, volumeType = 'downloads') {
+  await this.expandDirectoryTreeFor(appId, path, volumeType);
 
   // Select target path.
   await this.callRemoteTestUtil(
-      'fakeMouseClick', windowId, [`[full-path-for-testing="${path}"]`]);
+      'fakeMouseClick', appId, [`[full-path-for-testing="${path}"]`]);
 
   // Entries within Drive starts with /root/ but it isn't displayed in the
   // breadcrubms used by waitUntilCurrentDirectoryIsChanged.
@@ -651,8 +647,7 @@
   }
 
   // Wait until the Files app is navigated to the path.
-  return this.waitUntilCurrentDirectoryIsChanged(
-      windowId, `/${rootLabel}${path}`);
+  return this.waitUntilCurrentDirectoryIsChanged(appId, `/${rootLabel}${path}`);
 };
 
 /**
@@ -670,14 +665,14 @@
 /**
  * Waits until the expected image is shown.
  *
- * @param {string} windowId Window id.
+ * @param {string} appId App window Id.
  * @param {number} width Expected width of the image.
  * @param {number} height Expected height of the image.
  * @param {string|null} name Expected name of the image.
  * @return {Promise} Promsie to be fulfilled when the check is passed.
  */
 RemoteCallGallery.prototype.waitForSlideImage = function(
-    windowId, width, height, name) {
+    appId, width, height, name) {
   const expected = {};
   if (width) {
     expected.width = width;
@@ -693,8 +688,8 @@
   return repeatUntil(async () => {
     const query = '.gallery[mode="slide"] .image-container > .image';
     const [nameBox, image] = await Promise.all([
-      this.waitForElement(windowId, '#rename-input'),
-      this.waitForElementStyles(windowId, query, ['any'])
+      this.waitForElement(appId, '#rename-input'),
+      this.waitForElementStyles(appId, query, ['any'])
     ]);
     const actual = {};
     if (width && image) {
@@ -716,16 +711,15 @@
   });
 };
 
-RemoteCallGallery.prototype.changeNameAndWait =
-    async function(windowId, newName) {
-  await this.callRemoteTestUtil('changeName', windowId, [newName]);
-  return this.waitForSlideImage(windowId, 0, 0, newName);
+RemoteCallGallery.prototype.changeNameAndWait = async function(appId, newName) {
+  await this.callRemoteTestUtil('changeName', appId, [newName]);
+  return this.waitForSlideImage(appId, 0, 0, newName);
 };
 
 /**
  * Waits for the "Press Enter" message.
  *
- * @param {string} appId App id.
+ * @param {string} appId App window Id.
  * @return {Promise} Promise to be fulfilled when the element appears.
  */
 RemoteCallGallery.prototype.waitForPressEnterMessage = async function(appId) {
@@ -735,7 +729,7 @@
 
 /**
  * Shorthand for selecting an image in thumbnail mode.
- * @param {string} appId App id.
+ * @param {string} appId App window Id.
  * @param {string} name File name to be selected.
  * @return {!Promise<boolean>} A promise which will be resolved with true if the
  *     thumbnail has clicked. This method does not guarantee whether the
diff --git a/ui/file_manager/video_player/js/BUILD.gn b/ui/file_manager/video_player/js/BUILD.gn
index 726f6bd..bf91eecd 100644
--- a/ui/file_manager/video_player/js/BUILD.gn
+++ b/ui/file_manager/video_player/js/BUILD.gn
@@ -94,15 +94,11 @@
 }
 
 js_library("video_player_metrics") {
-  deps = [
-    "//ui/file_manager/file_manager/common/js:metrics_base",
-  ]
+  deps = [ "//ui/file_manager/file_manager/common/js:metrics_base" ]
 }
 
 js_test_gen_html("js_test_gen_html") {
-  deps = [
-    ":video_player_native_controls_unittest",
-  ]
+  deps = [ ":video_player_native_controls_unittest" ]
 }
 
 group("closure_compile") {
diff --git a/ui/file_manager/video_player/js/cast/BUILD.gn b/ui/file_manager/video_player/js/cast/BUILD.gn
index 246990ab..27243607 100644
--- a/ui/file_manager/video_player/js/cast/BUILD.gn
+++ b/ui/file_manager/video_player/js/cast/BUILD.gn
@@ -27,9 +27,7 @@
 }
 
 js_library("cast_extension_discoverer") {
-  deps = [
-    "//ui/file_manager/video_player/js:error_util",
-  ]
+  deps = [ "//ui/file_manager/video_player/js:error_util" ]
 }
 
 js_library("cast_video_element") {
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 26024a6..06bdd5d4 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -24,9 +24,7 @@
 # targets can all have a dependency for header checking purposes without
 # creating circular dependencies.
 source_set("gfx_export") {
-  sources = [
-    "gfx_export.h",
-  ]
+  sources = [ "gfx_export.h" ]
 }
 
 # Used for color generation at build time without importing all the gfx.
@@ -432,9 +430,7 @@
       "color_space_win.h",
     ]
   }
-  deps = [
-    "//skia:skcms",
-  ]
+  deps = [ "//skia:skcms" ]
   public_deps = [
     "//base",
     "//skia",
@@ -459,16 +455,12 @@
 # Depend on this to use image/resize_image_dimensions.h without pulling in
 # all of gfx.
 source_set("resize_image_dimensions") {
-  sources = [
-    "image/resize_image_dimensions.h",
-  ]
+  sources = [ "image/resize_image_dimensions.h" ]
 }
 
 # Depend on this to use native_widget_types.h without pulling in all of gfx.
 source_set("native_widget_types") {
-  public = [
-    "native_widget_types.h",
-  ]
+  public = [ "native_widget_types.h" ]
 
   public_deps = [
     ":gfx_export",
@@ -478,13 +470,9 @@
 
 group("selection_bound") {
   if (is_component_build) {
-    public_deps = [
-      ":gfx",
-    ]
+    public_deps = [ ":gfx" ]
   } else {
-    public_deps = [
-      ":selection_bound_sources",
-    ]
+    public_deps = [ ":selection_bound_sources" ]
   }
 }
 
@@ -511,9 +499,7 @@
 
 # Depend on this to use buffer_types.h without pulling in all of gfx.
 source_set("buffer_types") {
-  sources = [
-    "buffer_types.h",
-  ]
+  sources = [ "buffer_types.h" ]
 }
 
 # The GPU memory buffer stuff is separate from "gfx" to allow GPU-related
@@ -524,13 +510,9 @@
 # in the component build, but be a separate source set in a static build.
 group("memory_buffer") {
   if (is_component_build) {
-    public_deps = [
-      ":gfx",
-    ]
+    public_deps = [ ":gfx" ]
   } else {
-    public_deps = [
-      ":memory_buffer_sources",
-    ]
+    public_deps = [ ":memory_buffer_sources" ]
   }
 }
 
@@ -571,9 +553,7 @@
 
   defines = [ "GFX_IMPLEMENTATION" ]
 
-  public_deps = [
-    ":buffer_types",
-  ]
+  public_deps = [ ":buffer_types" ]
 
   deps = [
     ":gfx_switches",
@@ -631,9 +611,7 @@
 
   defines = [ "GFX_SWITCHES_IMPLEMENTATION" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 jumbo_static_library("test_support") {
@@ -660,9 +638,7 @@
     sources += [ "image/image_unittest_util_mac.mm" ]
   }
 
-  public_deps = [
-    ":gfx",
-  ]
+  public_deps = [ ":gfx" ]
 
   deps = [
     "//base",
@@ -722,9 +698,7 @@
 
   include_dirs = [ "//third_party/skia/include/private" ]
 
-  data = [
-    "test/data/",
-  ]
+  data = [ "test/data/" ]
 
   if (!is_ios) {
     sources += [
@@ -814,9 +788,7 @@
     deps += [ "//third_party:freetype_harfbuzz" ]
   }
 
-  data_deps = [
-    "//ui/resources:ui_test_pak_data",
-  ]
+  data_deps = [ "//ui/resources:ui_test_pak_data" ]
 
   if (is_mac || is_ios) {
     deps += [ "//ui/resources:ui_test_pak_bundle_data" ]
@@ -907,33 +879,23 @@
 }
 
 fuzzer_test("color_analysis_fuzzer") {
-  sources = [
-    "color_analysis_fuzzer.cc",
-  ]
+  sources = [ "color_analysis_fuzzer.cc" ]
 
-  deps = [
-    ":gfx",
-  ]
+  deps = [ ":gfx" ]
 }
 
 fuzzer_test("color_transform_fuzzer") {
-  sources = [
-    "color_transform_fuzzer.cc",
-  ]
+  sources = [ "color_transform_fuzzer.cc" ]
 
   dict = "//testing/libfuzzer/fuzzers/dicts/icc.dict"
 
-  deps = [
-    ":gfx",
-  ]
+  deps = [ ":gfx" ]
 
   libfuzzer_options = [ "max_len=4194304" ]
 }
 
 fuzzer_test("render_text_fuzzer") {
-  sources = [
-    "render_text_fuzzer.cc",
-  ]
+  sources = [ "render_text_fuzzer.cc" ]
 
   deps = [
     ":gfx",
@@ -945,9 +907,7 @@
 }
 
 fuzzer_test("render_text_api_fuzzer") {
-  sources = [
-    "render_text_api_fuzzer.cc",
-  ]
+  sources = [ "render_text_api_fuzzer.cc" ]
 
   deps = [
     ":gfx",
diff --git a/ui/gfx/geometry/BUILD.gn b/ui/gfx/geometry/BUILD.gn
index cbe9e952..2efaeb6 100644
--- a/ui/gfx/geometry/BUILD.gn
+++ b/ui/gfx/geometry/BUILD.gn
@@ -64,9 +64,7 @@
 
   defines = [ "GEOMETRY_IMPLEMENTATION" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   if (!is_debug) {
     configs -= [ "//build/config/compiler:default_optimization" ]
diff --git a/ui/gfx/geometry/mojom/BUILD.gn b/ui/gfx/geometry/mojom/BUILD.gn
index a45f5b9..4731f08 100644
--- a/ui/gfx/geometry/mojom/BUILD.gn
+++ b/ui/gfx/geometry/mojom/BUILD.gn
@@ -8,29 +8,21 @@
 # picking up a dependency on skia.
 mojom("mojom") {
   generate_java = true
-  sources = [
-    "geometry.mojom",
-  ]
+  sources = [ "geometry.mojom" ]
 
   check_includes_blink = false
 }
 
 mojom("test_interfaces") {
-  sources = [
-    "geometry_traits_test_service.mojom",
-  ]
+  sources = [ "geometry_traits_test_service.mojom" ]
 
-  public_deps = [
-    ":mojom",
-  ]
+  public_deps = [ ":mojom" ]
 }
 
 source_set("unit_test") {
   testonly = true
 
-  sources = [
-    "geometry_mojom_traits_unittest.cc",
-  ]
+  sources = [ "geometry_mojom_traits_unittest.cc" ]
 
   deps = [
     ":test_interfaces",
@@ -43,9 +35,7 @@
 }
 
 source_set("mojom_traits") {
-  sources = [
-    "geometry_mojom_traits.h",
-  ]
+  sources = [ "geometry_mojom_traits.h" ]
   public_deps = [
     ":mojom_shared_cpp_sources",
     "//ui/gfx/geometry",
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc
index 8696722..765a79f 100644
--- a/ui/gl/android/android_surface_control_compat.cc
+++ b/ui/gl/android/android_surface_control_compat.cc
@@ -5,10 +5,7 @@
 #include "ui/gl/android/android_surface_control_compat.h"
 
 #include <dlfcn.h>
-#include <android/ndk-version.h>
-#if __NDK_MAJOR__ >= 18
 #include <android/data_space.h>
-#endif
 
 #include "base/android/build_info.h"
 #include "base/atomic_sequence_num.h"
@@ -39,22 +36,6 @@
   ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
 };
 
-#if __NDK_MAJOR__ < 18
-enum {
-  ADATASPACE_UNKNOWN = 0,
-  ADATASPACE_SCRGB_LINEAR = 406913024,
-  ADATASPACE_SRGB = 142671872,
-  ADATASPACE_DISPLAY_P3 = 143261696,
-  ADATASPACE_BT2020_PQ = 163971072,
-};
-#endif
-
-#if __NDK_MAJOR__ < 20
-enum {
-  AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY = 1ULL << 11,
-};
-#endif
-
 // ASurfaceTransaction
 using pASurfaceTransaction_create = ASurfaceTransaction* (*)(void);
 using pASurfaceTransaction_delete = void (*)(ASurfaceTransaction*);
diff --git a/ui/latency/BUILD.gn b/ui/latency/BUILD.gn
index fba2dc6..13978ba 100644
--- a/ui/latency/BUILD.gn
+++ b/ui/latency/BUILD.gn
@@ -21,20 +21,14 @@
     "//ui/gfx",
   ]
 
-  public_deps = [
-    "//services/metrics/public/cpp:metrics_cpp",
-  ]
+  public_deps = [ "//services/metrics/public/cpp:metrics_cpp" ]
 }
 
 jumbo_source_set("test_support") {
   testonly = true
-  sources = [
-    "latency_info_test_support.cc",
-  ]
+  sources = [ "latency_info_test_support.cc" ]
 
-  public_deps = [
-    ":latency",
-  ]
+  public_deps = [ ":latency" ]
 }
 
 test("latency_unittests") {
diff --git a/ui/latency/ipc/BUILD.gn b/ui/latency/ipc/BUILD.gn
index 605a6380..19d5e4e5 100644
--- a/ui/latency/ipc/BUILD.gn
+++ b/ui/latency/ipc/BUILD.gn
@@ -11,9 +11,7 @@
     "latency_info_param_traits_macros.h",
   ]
 
-  public_deps = [
-    "//ui/latency",
-  ]
+  public_deps = [ "//ui/latency" ]
 
   deps = [
     "//base",
diff --git a/ui/latency/mojom/BUILD.gn b/ui/latency/mojom/BUILD.gn
index 5322cf97..607bc5e 100644
--- a/ui/latency/mojom/BUILD.gn
+++ b/ui/latency/mojom/BUILD.gn
@@ -6,22 +6,14 @@
 
 mojom("mojom") {
   generate_java = true
-  sources = [
-    "latency_info.mojom",
-  ]
+  sources = [ "latency_info.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
 
 mojom("test_interfaces") {
   testonly = true
-  sources = [
-    "traits_test_service.mojom",
-  ]
+  sources = [ "traits_test_service.mojom" ]
 
-  public_deps = [
-    ":mojom",
-  ]
+  public_deps = [ ":mojom" ]
 }
diff --git a/ui/native_theme/BUILD.gn b/ui/native_theme/BUILD.gn
index 5a68ba7..6de31e8 100644
--- a/ui/native_theme/BUILD.gn
+++ b/ui/native_theme/BUILD.gn
@@ -60,9 +60,7 @@
 
   defines = [ "NATIVE_THEME_IMPLEMENTATION" ]
 
-  public_deps = [
-    "//skia",
-  ]
+  public_deps = [ "//skia" ]
 
   deps = [
     "//base",
diff --git a/ui/platform_window/BUILD.gn b/ui/platform_window/BUILD.gn
index 0e38349..9565900 100644
--- a/ui/platform_window/BUILD.gn
+++ b/ui/platform_window/BUILD.gn
@@ -38,9 +38,7 @@
 }
 
 group("platform_impls") {
-  public_deps = [
-    "//ui/platform_window/stub",
-  ]
+  public_deps = [ "//ui/platform_window/stub" ]
   if (use_x11) {
     public_deps += [ "//ui/platform_window/x11" ]
   } else if (is_win) {
diff --git a/ui/platform_window/common/BUILD.gn b/ui/platform_window/common/BUILD.gn
index 09a6a2a5..54f3c8b8 100644
--- a/ui/platform_window/common/BUILD.gn
+++ b/ui/platform_window/common/BUILD.gn
@@ -11,9 +11,7 @@
 
   defines = [ "IS_PLATFORM_WINDOW_COMMON_IMPL" ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 
   sources = [
     "platform_window_defaults.cc",
diff --git a/ui/resources/BUILD.gn b/ui/resources/BUILD.gn
index a1be356..e674b42 100644
--- a/ui/resources/BUILD.gn
+++ b/ui/resources/BUILD.gn
@@ -39,9 +39,7 @@
   defines = [ "optimize_webui=$optimize_webui" ]
   source = "../webui/resources/webui_resources.grd"
 
-  deps = [
-    "//ui/webui/resources:modulize",
-  ]
+  deps = [ "//ui/webui/resources:modulize" ]
 
   # The .grd contains references to generated files.
   source_is_generated = true
@@ -60,15 +58,9 @@
 
 if (!is_mac) {
   copy("copy_ui_resources_100_percent") {
-    sources = [
-      "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
-    ]
-    outputs = [
-      "$root_out_dir/ui_resources_100_percent.pak",
-    ]
-    deps = [
-      "//ui/resources",
-    ]
+    sources = [ "$root_gen_dir/ui/resources/ui_resources_100_percent.pak" ]
+    outputs = [ "$root_out_dir/ui_resources_100_percent.pak" ]
+    deps = [ "//ui/resources" ]
   }
 }
 
@@ -88,43 +80,25 @@
   bundle_data("ui_test_pak_bundle_data_locale") {
     testonly = true
     visibility = [ ":ui_test_pak_bundle_data" ]
-    public_deps = [
-      ":ui_test_pak",
-    ]
-    sources = [
-      "$root_out_dir/ui_test.pak",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/en.lproj/locale.pak",
-    ]
+    public_deps = [ ":ui_test_pak" ]
+    sources = [ "$root_out_dir/ui_test.pak" ]
+    outputs = [ "{{bundle_resources_dir}}/en.lproj/locale.pak" ]
   }
 
   bundle_data("ui_test_pak_bundle_data_test_pak") {
     testonly = true
     visibility = [ ":ui_test_pak_bundle_data" ]
-    public_deps = [
-      ":ui_test_pak",
-    ]
-    sources = [
-      "$root_out_dir/ui_test.pak",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/ui_test.pak",
-    ]
+    public_deps = [ ":ui_test_pak" ]
+    sources = [ "$root_out_dir/ui_test.pak" ]
+    outputs = [ "{{bundle_resources_dir}}/ui_test.pak" ]
   }
 
   bundle_data("ui_test_pak_bundle_data_100_percent") {
     testonly = true
     visibility = [ ":ui_test_pak_bundle_data" ]
-    public_deps = [
-      ":ui_test_pak",
-    ]
-    sources = [
-      "$root_out_dir/ui_test.pak",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/chrome_100_percent.pak",
-    ]
+    public_deps = [ ":ui_test_pak" ]
+    sources = [ "$root_out_dir/ui_test.pak" ]
+    outputs = [ "{{bundle_resources_dir}}/chrome_100_percent.pak" ]
   }
 
   group("ui_test_pak_bundle_data") {
@@ -137,15 +111,9 @@
   }
 } else {
   copy("ui_test_pak") {
-    sources = [
-      "$root_out_dir/ui_test.pak",
-    ]
-    outputs = [
-      "$root_out_dir/ui/en-US.pak",
-    ]
-    public_deps = [
-      ":repack_ui_test_pak_100_percent",
-    ]
+    sources = [ "$root_out_dir/ui_test.pak" ]
+    outputs = [ "$root_out_dir/ui/en-US.pak" ]
+    public_deps = [ ":repack_ui_test_pak_100_percent" ]
   }
 }
 
@@ -153,15 +121,11 @@
 # build directory so it can be loaded for test purposes. If a target requires
 # 200 percent resources it should also depend on ui_test_pak_data_200_percent.
 group("ui_test_pak_data") {
-  data_deps = [
-    ":repack_ui_test_pak_100_percent",
-  ]
+  data_deps = [ ":repack_ui_test_pak_100_percent" ]
 }
 
 group("ui_test_pak_data_200_percent") {
-  data_deps = [
-    ":repack_ui_test_pak_200_percent",
-  ]
+  data_deps = [ ":repack_ui_test_pak_200_percent" ]
 }
 
 repack("repack_ui_test_pak_100_percent") {
@@ -228,15 +192,11 @@
 repack("repack_ui_test_pak_200_percent") {
   visibility = [ ":ui_test_pak_data_200_percent" ]
 
-  sources = [
-    "$root_gen_dir/ui/resources/ui_resources_200_percent.pak",
-  ]
+  sources = [ "$root_gen_dir/ui/resources/ui_resources_200_percent.pak" ]
 
   output = "$root_out_dir/ui_test_200_percent.pak"
 
-  deps = [
-    "//ui/resources",
-  ]
+  deps = [ "//ui/resources" ]
 
   if (toolkit_views) {
     deps += [ "//ui/views/resources" ]
@@ -259,7 +219,5 @@
 
   output = "$root_out_dir/ui/en.lproj/locale.pak"
 
-  deps = [
-    "//ui/strings",
-  ]
+  deps = [ "//ui/strings" ]
 }
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn
index 6501b6ea..0b233f07 100644
--- a/ui/shell_dialogs/BUILD.gn
+++ b/ui/shell_dialogs/BUILD.gn
@@ -153,10 +153,6 @@
     "fake_select_file_dialog.cc",
     "fake_select_file_dialog.h",
   ]
-  public_deps = [
-    ":shell_dialogs",
-  ]
-  deps = [
-    "//base",
-  ]
+  public_deps = [ ":shell_dialogs" ]
+  deps = [ "//base" ]
 }
diff --git a/ui/snapshot/BUILD.gn b/ui/snapshot/BUILD.gn
index 03728fa..cda06df 100644
--- a/ui/snapshot/BUILD.gn
+++ b/ui/snapshot/BUILD.gn
@@ -87,16 +87,12 @@
 }
 
 jumbo_source_set("snapshot_export") {
-  sources = [
-    "snapshot_export.h",
-  ]
+  sources = [ "snapshot_export.h" ]
   visibility = [ ":*" ]
 }
 
 test("snapshot_unittests") {
-  sources = [
-    "test/run_all_unittests.cc",
-  ]
+  sources = [ "test/run_all_unittests.cc" ]
 
   if (is_mac) {
     sources += [ "snapshot_mac_unittest.mm" ]
diff --git a/ui/strings/BUILD.gn b/ui/strings/BUILD.gn
index be2ce72..04a4650 100644
--- a/ui/strings/BUILD.gn
+++ b/ui/strings/BUILD.gn
@@ -16,9 +16,7 @@
 
 grit("ui_strings") {
   source = "ui_strings.grd"
-  outputs = [
-    "grit/ui_strings.h",
-  ]
+  outputs = [ "grit/ui_strings.h" ]
   foreach(locale, locales_with_fake_bidi) {
     outputs += [ "ui_strings_$locale.pak" ]
   }
@@ -26,9 +24,7 @@
 
 grit("app_locale_settings") {
   source = "app_locale_settings.grd"
-  outputs = [
-    "grit/app_locale_settings.h",
-  ]
+  outputs = [ "grit/app_locale_settings.h" ]
   foreach(locale, locales_with_fake_bidi) {
     outputs += [ "app_locale_settings_$locale.pak" ]
   }
diff --git a/ui/touch_selection/BUILD.gn b/ui/touch_selection/BUILD.gn
index b78053648..11c2b71 100644
--- a/ui/touch_selection/BUILD.gn
+++ b/ui/touch_selection/BUILD.gn
@@ -89,20 +89,14 @@
     "//ui/gfx:test_support",
   ]
 
-  data_deps = [
-    "//third_party/mesa_headers",
-  ]
+  data_deps = [ "//third_party/mesa_headers" ]
 }
 
 if (is_android) {
   java_cpp_enum("ui_touch_selection_enums_srcjar") {
-    sources = [
-      "selection_event_type.h",
-    ]
+    sources = [ "selection_event_type.h" ]
   }
   java_cpp_enum("ui_touch_handle_orientation_srcjar") {
-    sources = [
-      "touch_handle_orientation.h",
-    ]
+    sources = [ "touch_handle_orientation.h" ]
   }
 }
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index ab42767..c66b964 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -357,8 +357,8 @@
 
 bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
   // Escape should close the drop down list when it is active, not host UI.
-  if (e.key_code() != ui::VKEY_ESCAPE ||
-      e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) {
+  if (e.key_code() != ui::VKEY_ESCAPE || e.IsShiftDown() || e.IsControlDown() ||
+      e.IsAltDown() || e.IsAltGrDown()) {
     return false;
   }
   return !!menu_runner_;
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 32ab932..67a8ff4 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -553,7 +553,8 @@
 }
 
 bool FocusManager::ProcessArrowKeyTraversal(const ui::KeyEvent& event) {
-  if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown())
+  if (event.IsShiftDown() || event.IsControlDown() || event.IsAltDown() ||
+      event.IsAltGrDown())
     return false;
 
   const ui::KeyboardCode key = event.key_code();
diff --git a/ui/web_dialogs/BUILD.gn b/ui/web_dialogs/BUILD.gn
index d09fa063..b70a755 100644
--- a/ui/web_dialogs/BUILD.gn
+++ b/ui/web_dialogs/BUILD.gn
@@ -41,9 +41,7 @@
     "test/test_web_dialog_delegate.h",
   ]
 
-  public_deps = [
-    ":web_dialogs",
-  ]
+  public_deps = [ ":web_dialogs" ]
   deps = [
     "//base",
     "//content/public/browser",
@@ -56,9 +54,7 @@
 source_set("web_dialogs_unittests") {
   testonly = true
 
-  sources = [
-    "web_dialog_ui_unittest.cc",
-  ]
+  sources = [ "web_dialog_ui_unittest.cc" ]
 
   deps = [
     ":web_dialogs",
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_password_input.html b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
index 3afeef1..de9a413e 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator_mojo.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html">
 <link rel="import" href="network_config_element_behavior.html">
 <link rel="import" href="network_shared_css.html">
 
@@ -22,6 +23,13 @@
         flex: 1;
       }
 
+      paper-tooltip {
+        --paper-tooltip: {
+          @apply --cr-tooltip;
+          min-width: 0;
+        };
+      }
+
       cr-policy-network-indicator-mojo {
         --cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing);
       }
@@ -40,8 +48,12 @@
         <cr-icon-button id="icon" slot="suffix"
             class$="[[getIconClass_(showPassword)]]"
             on-click="onShowPasswordTap_"
-            title="[[getShowPasswordTitle_(showPassword)]]">
+            aria-describedby="tooltip">
         </cr-icon-button>
+        <paper-tooltip id="tooltip" for="icon" position="top"
+            fit-to-visible-bounds role="tooltip">
+          [[getShowPasswordTitle_(showPassword)]]
+        </paper-tooltip>
       </template>
       <template is="dom-if" if="[[showPolicyIndicator_]]" restamp>
         <cr-policy-network-indicator-mojo
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index c0cbb0d..5375761 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -46,7 +46,6 @@
     "cr_radio_button:closure_compile_module",
     "cr_radio_group:closure_compile_module",
     "cr_search_field:closure_compile_module",
-    "cr_splitter:closure_compile_module",
     "cr_tabs:closure_compile_module",
     "cr_toast:closure_compile_module",
     "cr_toggle:closure_compile_module",
@@ -75,15 +74,11 @@
 }
 
 js_library("cr_scrollable_behavior") {
-  deps = [
-    "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted",
-  ]
+  deps = [ "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted" ]
 }
 
 js_library("cr_container_shadow_behavior") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
 
 # Targets for auto-generating Polymer 3 JS Modules.
@@ -176,7 +171,6 @@
     "cr_radio_group:cr_radio_group_module",
     "cr_search_field:cr_search_field_module",
     "cr_search_field:modulize",
-    "cr_splitter:cr_splitter_module",
     "cr_tabs:cr_tabs_module",
     "cr_toast:cr_toast_manager_module",
     "cr_toast:cr_toast_module",
@@ -199,17 +193,11 @@
 
 js_type_check("cr_elements_module_resources") {
   uses_js_modules = true
-  deps = [
-    ":cr_container_shadow_behavior.m",
-  ]
+  deps = [ ":cr_container_shadow_behavior.m" ]
 }
 
 js_library("cr_container_shadow_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.js",
-  ]
-  deps = [
-    "//ui/webui/resources/js:assert.m",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_container_shadow_behavior.m.js" ]
+  deps = [ "//ui/webui/resources/js:assert.m" ]
   extra_deps = [ ":modulize" ]
 }
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_lottie/BUILD.gn b/ui/webui/resources/cr_elements/chromeos/cr_lottie/BUILD.gn
index d175d0f..e7927334 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_lottie/BUILD.gn
+++ b/ui/webui/resources/cr_elements/chromeos/cr_lottie/BUILD.gn
@@ -1,14 +1,10 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_lottie",
-  ]
+  deps = [ ":cr_lottie" ]
 }
 
 js_library("cr_lottie") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [ "$externs_path/pending.js" ]
 }
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn b/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
index cad6349..5b84d95c0 100644
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
+++ b/ui/webui/resources/cr_elements/chromeos/cr_picture/BUILD.gn
@@ -15,9 +15,7 @@
 }
 
 js_library("cr_camera") {
-  deps = [
-    ":cr_png_behavior",
-  ]
+  deps = [ ":cr_png_behavior" ]
 }
 
 js_library("cr_picture_list") {
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/BUILD.gn b/ui/webui/resources/cr_elements/cr_action_menu/BUILD.gn
index 0025d2d..c99dc12 100644
--- a/ui/webui/resources/cr_elements/cr_action_menu/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_action_menu/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_action_menu",
-  ]
+  deps = [ ":cr_action_menu" ]
 }
 
 js_library("cr_action_menu") {
@@ -44,15 +42,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_action_menu.m",
-  ]
+  deps = [ ":cr_action_menu.m" ]
 }
 
 js_library("cr_action_menu.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:assert.m",
diff --git a/ui/webui/resources/cr_elements/cr_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_button/BUILD.gn
index c224703c..aa1cc36 100644
--- a/ui/webui/resources/cr_elements/cr_button/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_button/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_button",
-  ]
+  deps = [ ":cr_button" ]
 }
 
 js_library("cr_button") {
@@ -26,9 +24,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_button.m",
-  ]
+  deps = [ ":cr_button.m" ]
 }
 
 js_library("cr_button.m") {
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/BUILD.gn b/ui/webui/resources/cr_elements/cr_checkbox/BUILD.gn
index 621cd2f2..74c4a13 100644
--- a/ui/webui/resources/cr_elements/cr_checkbox/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_checkbox/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_checkbox",
-  ]
+  deps = [ ":cr_checkbox" ]
 }
 
 js_library("cr_checkbox") {
-  deps = [
-    "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
-  ]
+  deps = [ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted" ]
 }
 
 polymer_modulizer("cr_checkbox") {
@@ -25,9 +21,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_checkbox.m",
-  ]
+  deps = [ ":cr_checkbox.m" ]
 }
 
 js_library("cr_checkbox.m") {
diff --git a/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn b/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn
index 032dd8f..930c63c 100644
--- a/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_dialog/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_dialog",
-  ]
+  deps = [ ":cr_dialog" ]
 }
 
 js_library("cr_dialog") {
@@ -30,9 +28,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_dialog.m",
-  ]
+  deps = [ ":cr_dialog.m" ]
 }
 
 js_library("cr_dialog.m") {
diff --git a/ui/webui/resources/cr_elements/cr_drawer/BUILD.gn b/ui/webui/resources/cr_elements/cr_drawer/BUILD.gn
index 816fcf36..fa80a445 100644
--- a/ui/webui/resources/cr_elements/cr_drawer/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_drawer/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_drawer",
-  ]
+  deps = [ ":cr_drawer" ]
 }
 
 js_library("cr_drawer") {
@@ -30,9 +28,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_drawer.m",
-  ]
+  deps = [ ":cr_drawer.m" ]
 }
 
 js_library("cr_drawer.m") {
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_expand_button/BUILD.gn
index 96a0f362..3b71606 100644
--- a/ui/webui/resources/cr_elements/cr_expand_button/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_expand_button/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_expand_button",
-  ]
+  deps = [ ":cr_expand_button" ]
 }
 
 js_library("cr_expand_button") {
-  deps = [
-    "//ui/webui/resources/js/cr/ui:focus_without_ink",
-  ]
+  deps = [ "//ui/webui/resources/js/cr/ui:focus_without_ink" ]
 }
 
 polymer_modulizer("cr_expand_button") {
@@ -28,15 +24,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_expand_button.m",
-  ]
+  deps = [ ":cr_expand_button.m" ]
 }
 
 js_library("cr_expand_button.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
diff --git a/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn b/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn
index 999c12e..72184bc 100644
--- a/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_fingerprint/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_fingerprint_progress_arc",
-  ]
+  deps = [ ":cr_fingerprint_progress_arc" ]
 }
 
 js_library("cr_fingerprint_progress_arc") {
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_icon_button/BUILD.gn
index cfce53c..fa12081 100644
--- a/ui/webui/resources/cr_elements/cr_icon_button/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_icon_button/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_icon_button",
-  ]
+  deps = [ ":cr_icon_button" ]
 }
 
 js_library("cr_icon_button") {
-  deps = [
-    "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
-  ]
+  deps = [ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted" ]
 }
 
 polymer_modulizer("cr_icon_button") {
@@ -25,15 +21,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_icon_button.m",
-  ]
+  deps = [ ":cr_icon_button.m" ]
 }
 
 js_library("cr_icon_button.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/ui/webui/resources/cr_elements/cr_input/BUILD.gn b/ui/webui/resources/cr_elements/cr_input/BUILD.gn
index 70979b46..0024808 100644
--- a/ui/webui/resources/cr_elements/cr_input/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_input/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_input",
-  ]
+  deps = [ ":cr_input" ]
 }
 
 js_library("cr_input") {
@@ -33,15 +31,12 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_input.m",
-  ]
+  deps = [ ":cr_input.m" ]
 }
 
 js_library("cr_input.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_input/cr_input.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_input/cr_input.m.js" ]
   deps = [
     "../../js:assert.m",
     "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
diff --git a/ui/webui/resources/cr_elements/cr_lazy_render/BUILD.gn b/ui/webui/resources/cr_elements/cr_lazy_render/BUILD.gn
index 2829d5f..f04a480 100644
--- a/ui/webui/resources/cr_elements/cr_lazy_render/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_lazy_render/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_lazy_render",
-  ]
+  deps = [ ":cr_lazy_render" ]
 }
 
 js_library("cr_lazy_render") {
@@ -25,15 +23,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_lazy_render.m",
-  ]
+  deps = [ ":cr_lazy_render.m" ]
 }
 
 js_library("cr_lazy_render.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
diff --git a/ui/webui/resources/cr_elements/cr_link_row/BUILD.gn b/ui/webui/resources/cr_elements/cr_link_row/BUILD.gn
index 02fcd1d..7e22f87 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_link_row/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_link_row",
-  ]
+  deps = [ ":cr_link_row" ]
 }
 
 js_library("cr_link_row") {
-  deps = [
-    "../cr_icon_button:cr_icon_button",
-  ]
+  deps = [ "../cr_icon_button:cr_icon_button" ]
 }
 
 polymer_modulizer("cr_link_row") {
@@ -25,17 +21,13 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_link_row.m",
-  ]
+  deps = [ ":cr_link_row.m" ]
 }
 
 js_library("cr_link_row.m") {
   sources = [
     "$root_gen_dir/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.m.js",
   ]
-  deps = [
-    "../cr_icon_button:cr_icon_button.m",
-  ]
+  deps = [ "../cr_icon_button:cr_icon_button.m" ]
   extra_deps = [ ":cr_link_row_module" ]
 }
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn b/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
index 50c62df1..7256669 100644
--- a/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_radio_button/BUILD.gn
@@ -7,30 +7,22 @@
 import("../../tools/js_modulizer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_radio_button",
-  ]
+  deps = [ ":cr_radio_button" ]
 }
 
 js_library("cr_radio_button") {
-  deps = [
-    ":cr_radio_button_behavior",
-  ]
+  deps = [ ":cr_radio_button_behavior" ]
 }
 
 js_library("cr_radio_button_behavior") {
-  deps = [
-    "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
-  ]
+  deps = [ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted" ]
 }
 
 # Targets for auto-generating and typechecking Polymer 3 JS modules
 
 js_modulizer("modulize") {
   input_files = [ "cr_radio_button_behavior.js" ]
-  deps = [
-    "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
-  ]
+  deps = [ "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior" ]
   namespace_rewrites = [ "Polymer.PaperRippleBehavior|PaperRippleBehavior" ]
 }
 
@@ -56,9 +48,7 @@
 }
 
 js_library("cr_radio_button.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button.m.js" ]
   deps = [
     ":cr_radio_button_behavior.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
@@ -67,11 +57,7 @@
 }
 
 js_library("cr_radio_button_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js",
-  ]
-  deps = [
-    "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js" ]
+  deps = [ "//third_party/polymer/v3_0/components-chromium/paper-behaviors:paper-ripple-behavior" ]
   extra_deps = [ ":modulize" ]
 }
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn b/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn
index 2148e7f..0485ad82 100644
--- a/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_radio_group/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_radio_group",
-  ]
+  deps = [ ":cr_radio_group" ]
 }
 
 js_library("cr_radio_group") {
@@ -33,15 +31,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_radio_group.m",
-  ]
+  deps = [ ":cr_radio_group.m" ]
 }
 
 js_library("cr_radio_group.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m",
diff --git a/ui/webui/resources/cr_elements/cr_search_field/BUILD.gn b/ui/webui/resources/cr_elements/cr_search_field/BUILD.gn
index 5771b0f..fb735b7 100644
--- a/ui/webui/resources/cr_elements/cr_search_field/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_search_field/BUILD.gn
@@ -48,9 +48,7 @@
 }
 
 js_library("cr_search_field.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.m.js" ]
   deps = [
     ":cr_search_field_behavior.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
@@ -61,9 +59,7 @@
 }
 
 js_library("cr_search_field_behavior.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.m.js" ]
   deps = []
   extra_deps = [ ":modulize" ]
 }
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn
index cba270d4..0eafe64 100644
--- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_searchable_drop_down",
-  ]
+  deps = [ ":cr_searchable_drop_down" ]
 }
 
 js_library("cr_searchable_drop_down") {
@@ -28,15 +26,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_searchable_drop_down.m",
-  ]
+  deps = [ ":cr_searchable_drop_down.m" ]
 }
 
 js_library("cr_searchable_drop_down.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/iron-dropdown",
     "//third_party/polymer/v3_0/components-chromium/iron-icon",
diff --git a/ui/webui/resources/cr_elements/cr_splitter/BUILD.gn b/ui/webui/resources/cr_elements/cr_splitter/BUILD.gn
index 679307c..d69daf0 100644
--- a/ui/webui/resources/cr_elements/cr_splitter/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_splitter/BUILD.gn
@@ -3,36 +3,14 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_splitter",
-  ]
+  is_polymer3 = true
+  deps = [ ":cr_splitter" ]
 }
 
 js_library("cr_splitter") {
-}
-
-polymer_modulizer("cr_splitter") {
-  js_file = "cr_splitter.js"
-  html_file = "cr_splitter.html"
-  html_type = "dom-module"
-}
-
-js_type_check("closure_compile_module") {
-  is_polymer3 = true
-  deps = [
-    ":cr_splitter.m",
-  ]
-}
-
-js_library("cr_splitter.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.m.js",
-  ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
-  extra_deps = [ ":cr_splitter_module" ]
 }
diff --git a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.html b/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.html
deleted file mode 100644
index 1ee1aa1..0000000
--- a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<link rel="import" href="../../html/polymer.html">
-
-<dom-module id="cr-splitter">
-  <template>
-  </template>
-  <script src="cr_splitter.js"></script>
-</dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js b/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
index da79cc56..25951c8c 100644
--- a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
+++ b/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(function() {
+import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 // TODO(arv): Currently this only supports horizontal layout.
 // TODO(arv): This ignores min-width and max-width of the elements to the
@@ -40,6 +40,8 @@
 Polymer({
   is: 'cr-splitter',
 
+  _template: null,
+
   properties: {
     resizeNextElement: {
       type: Boolean,
@@ -266,4 +268,3 @@
     this.classList.remove('splitter-active');
   },
 });
-})();
diff --git a/ui/webui/resources/cr_elements/cr_tabs/BUILD.gn b/ui/webui/resources/cr_elements/cr_tabs/BUILD.gn
index 2174f73..ab8059d 100644
--- a/ui/webui/resources/cr_elements/cr_tabs/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_tabs/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_tabs",
-  ]
+  deps = [ ":cr_tabs" ]
 }
 
 js_library("cr_tabs") {
@@ -22,15 +20,12 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_tabs.m",
-  ]
+  deps = [ ":cr_tabs.m" ]
 }
 
 js_library("cr_tabs.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_tabs/cr_tabs.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
diff --git a/ui/webui/resources/cr_elements/cr_toast/BUILD.gn b/ui/webui/resources/cr_elements/cr_toast/BUILD.gn
index 74c81ddc..5d3faf9 100644
--- a/ui/webui/resources/cr_elements/cr_toast/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_toast/BUILD.gn
@@ -50,9 +50,8 @@
 }
 
 js_library("cr_toast.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.js",
-  ]
+  sources =
+      [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_toast/cr_toast.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
@@ -60,9 +59,7 @@
 }
 
 js_library("cr_toast_manager.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_toast/cr_toast_manager.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_toast/cr_toast_manager.m.js" ]
   deps = [
     ":cr_toast.m",
     "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
diff --git a/ui/webui/resources/cr_elements/cr_toggle/BUILD.gn b/ui/webui/resources/cr_elements/cr_toggle/BUILD.gn
index 76dc309c..07edfe5 100644
--- a/ui/webui/resources/cr_elements/cr_toggle/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_toggle/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_toggle",
-  ]
+  deps = [ ":cr_toggle" ]
 }
 
 js_library("cr_toggle") {
-  deps = [
-    "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
-  ]
+  deps = [ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted" ]
 }
 
 polymer_modulizer("cr_toggle") {
@@ -25,9 +21,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_toggle.m",
-  ]
+  deps = [ ":cr_toggle.m" ]
 }
 
 js_library("cr_toggle.m") {
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/BUILD.gn b/ui/webui/resources/cr_elements/cr_toolbar/BUILD.gn
index 3f70aca..7dbb1c5 100644
--- a/ui/webui/resources/cr_elements/cr_toolbar/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_toolbar/BUILD.gn
@@ -23,9 +23,7 @@
 }
 
 js_library("cr_toolbar") {
-  deps = [
-    ":cr_toolbar_search_field",
-  ]
+  deps = [ ":cr_toolbar_search_field" ]
 }
 
 polymer_modulizer("cr_toolbar") {
@@ -72,9 +70,7 @@
 }
 
 js_library("cr_toolbar_search_field.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field_behavior.m",
@@ -83,9 +79,7 @@
 }
 
 js_library("cr_toolbar_selection_overlay.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
diff --git a/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn b/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn
index 0ca0c51..8e2ab87 100644
--- a/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn
@@ -6,15 +6,11 @@
 import("//tools/polymer/polymer.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_view_manager",
-  ]
+  deps = [ ":cr_view_manager" ]
 }
 
 js_library("cr_view_manager") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
 
 polymer_modulizer("cr_view_manager") {
@@ -26,15 +22,11 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_view_manager.m",
-  ]
+  deps = [ ":cr_view_manager.m" ]
 }
 
 js_library("cr_view_manager.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.m.js" ]
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:assert.m",
diff --git a/ui/webui/resources/cr_elements/policy/BUILD.gn b/ui/webui/resources/cr_elements/policy/BUILD.gn
index 4ca00093..c1c2741 100644
--- a/ui/webui/resources/cr_elements/policy/BUILD.gn
+++ b/ui/webui/resources/cr_elements/policy/BUILD.gn
@@ -29,22 +29,16 @@
 }
 
 js_library("cr_policy_indicator_behavior") {
-  deps = [
-    "//ui/webui/resources/js:assert",
-  ]
+  deps = [ "//ui/webui/resources/js:assert" ]
 }
 
 js_library("cr_policy_pref_behavior") {
-  deps = [
-    ":cr_policy_indicator_behavior",
-  ]
+  deps = [ ":cr_policy_indicator_behavior" ]
   externs_list = [ "$externs_path/settings_private.js" ]
 }
 
 js_library("cr_policy_pref_indicator") {
-  deps = [
-    ":cr_policy_indicator_behavior",
-  ]
+  deps = [ ":cr_policy_indicator_behavior" ]
   externs_list = [ "$externs_path/settings_private.js" ]
 }
 
@@ -79,9 +73,7 @@
 
 js_type_check("closure_compile_module") {
   is_polymer3 = true
-  deps = [
-    ":cr_tooltip_icon.m",
-  ]
+  deps = [ ":cr_tooltip_icon.m" ]
 }
 
 js_library("cr_tooltip_icon.m") {
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp
index 77951d4..a798a40 100644
--- a/ui/webui/resources/cr_elements_resources.grdp
+++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -154,14 +154,6 @@
              file="cr_elements/cr_slider/cr_slider.js"
              type="chrome_html"
              compress="gzip" />
-  <structure name="IDR_CR_ELEMENTS_CR_SPLITTER_HTML"
-             file="cr_elements/cr_splitter/cr_splitter.html"
-             type="chrome_html"
-             compress="gzip" />
-  <structure name="IDR_CR_ELEMENTS_CR_SPLITTER_JS"
-             file="cr_elements/cr_splitter/cr_splitter.js"
-             type="chrome_html"
-             compress="gzip" />
   <if expr="chromeos">
     <structure name="IDR_CR_ELEMENTS_CR_SEARCHABLE_DROP_DOWN_HTML"
                file="cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html"
diff --git a/ui/webui/resources/cr_elements_resources_v3.grdp b/ui/webui/resources/cr_elements_resources_v3.grdp
index 48ecf73..5e665e4 100644
--- a/ui/webui/resources/cr_elements_resources_v3.grdp
+++ b/ui/webui/resources/cr_elements_resources_v3.grdp
@@ -116,9 +116,8 @@
          use_base_dir="false"
          type="BINDATA"
          compress="gzip" />
-  <include name="IDR_CR_ELEMENTS_CR_SPLITTER_M_JS"
-         file="${root_gen_dir}/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.m.js"
-         use_base_dir="false"
+  <include name="IDR_CR_ELEMENTS_CR_SPLITTER_JS"
+         file="cr_elements/cr_splitter/cr_splitter.js"
          type="BINDATA"
          compress="gzip" />
   <include name="IDR_CR_ELEMENTS_CR_TABS_M_JS"
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index a057c8a..ed26790 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -159,9 +159,7 @@
     "//ui/wm/public",
   ]
 
-  data_deps = [
-    "//ui/resources:ui_test_pak_data",
-  ]
+  data_deps = [ "//ui/resources:ui_test_pak_data" ]
 
   if (is_chromeos) {
     sources += [ "core/ime_util_chromeos_unittest.cc" ]