diff --git a/.eslintrc.js b/.eslintrc.js
index bfdfc712..90d65cb 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -44,11 +44,6 @@
         'property': '__defineSetter__',
         'message': 'Use Object.defineProperty',
       },
-      {
-        'object': 'cr',
-        'property': 'exportPath',
-        'message': 'Use ES modules or cr.define() instead',
-      },
     ],
     'no-var': 'error',
     'prefer-const': 'error',
diff --git a/BUILD.gn b/BUILD.gn
index f928c3d..54d49f9d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1101,10 +1101,7 @@
     }
 
     if (is_fuchsia) {
-      data_deps += [
-        "//build/fuchsia/layout_test_proxy:layout_test_proxy_runner",
-        "//content/shell:content_shell_fuchsia",
-      ]
+      data_deps += [ "//content/shell:content_shell_fuchsia" ]
     }
 
     data = [
diff --git a/DEPS b/DEPS
index bd72661..8bd52986 100644
--- a/DEPS
+++ b/DEPS
@@ -312,7 +312,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '15c442e941fbabc6bf0055ef3583cf5bfabbaa11',
+  'dawn_revision': 'e5cb8f2eff7e2b0f672c0d20fb97ca17fe28e94a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1297,7 +1297,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '557f55b92b7c29a36c1e28b32af335d92d65f15f',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '97292c37ad67ba47478e4ca58dbe4b2238554b0e',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
diff --git a/ash/app_list/BUILD.gn b/ash/app_list/BUILD.gn
index 36147f1..c0d6767 100644
--- a/ash/app_list/BUILD.gn
+++ b/ash/app_list/BUILD.gn
@@ -190,9 +190,7 @@
 executable("app_list_demo") {
   testonly = true
 
-  sources = [
-    "demo/app_list_demo_views.cc",
-  ]
+  sources = [ "demo/app_list_demo_views.cc" ]
 
   deps = [
     ":app_list",
diff --git a/ash/app_list/OWNERS b/ash/app_list/OWNERS
index 692b2aa..b51ecc5 100644
--- a/ash/app_list/OWNERS
+++ b/ash/app_list/OWNERS
@@ -2,7 +2,6 @@
 jennyz@chromium.org
 khmel@chromium.org
 newcomer@chromium.org
-stevenjb@chromium.org
 xiyuan@chromium.org
 
 # COMPONENT: UI>Shell>Launcher
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 8dcbaad..38dab3f 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -621,7 +621,9 @@
 }
 
 bool AppListControllerImpl::ShouldHomeLauncherBeVisible() const {
-  return IsTabletMode() && !HasVisibleWindows();
+  return IsTabletMode() && (!HasVisibleWindows() ||
+                            home_launcher_transition_state_ ==
+                                HomeLauncherTransitionState::kMostlyShown);
 }
 
 void AppListControllerImpl::OnShelfAlignmentChanged(
@@ -1631,17 +1633,7 @@
   aura::Window* parent_window = GetContainerForDisplayId(display_id);
   if (parent_window && !parent_window->Contains(window)) {
     parent_window->AddChild(window);
-    bool is_showing_app_window = false;
-    for (auto* app_window :
-         Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(
-             kActiveDesk)) {
-      if (!parent_window->Contains(app_window) &&
-          !WindowState::Get(app_window)->IsMinimized()) {
-        is_showing_app_window = true;
-        break;
-      }
-    }
-    if (ShouldLauncherShowBehindApps() && is_showing_app_window) {
+    if (!ShouldHomeLauncherBeVisible()) {
       // When move launcher back to behind apps, and there is app window
       // showing, we release focus.
       Shell::Get()->activation_client()->DeactivateWindow(window);
@@ -1656,11 +1648,14 @@
 
 aura::Window* AppListControllerImpl::GetContainerForDisplayId(
     base::Optional<int64_t> display_id) {
-  aura::Window* root_window =
-      display_id.has_value()
-          ? Shell::GetRootWindowForDisplayId(display_id.value())
-          : presenter_.GetWindow()->GetRootWindow();
-  return root_window->GetChildById(GetContainerId());
+  aura::Window* root_window = nullptr;
+  if (display_id.has_value()) {
+    root_window = Shell::GetRootWindowForDisplayId(display_id.value());
+  } else if (presenter_.GetWindow()) {
+    root_window = presenter_.GetWindow()->GetRootWindow();
+  }
+
+  return root_window ? root_window->GetChildById(GetContainerId()) : nullptr;
 }
 
 bool AppListControllerImpl::ShouldLauncherShowBehindApps() const {
diff --git a/ash/app_list/resources/BUILD.gn b/ash/app_list/resources/BUILD.gn
index 030e69a8..b755915 100644
--- a/ash/app_list/resources/BUILD.gn
+++ b/ash/app_list/resources/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/grit/repack.gni")
 
 group("resources") {
-  public_deps = [
-    ":resources_grd",
-  ]
+  public_deps = [ ":resources_grd" ]
 }
 
 grit("resources_grd") {
diff --git a/ash/app_menu/OWNERS b/ash/app_menu/OWNERS
index a566dec7..03ab7ff3 100644
--- a/ash/app_menu/OWNERS
+++ b/ash/app_menu/OWNERS
@@ -1,5 +1,4 @@
 newcomer@chromium.org
-stevenjb@chromium.org
 xiyuan@chromium.org
 
 # COMPONENT: UI>Shell>Shelf
diff --git a/ash/assistant/ui/BUILD.gn b/ash/assistant/ui/BUILD.gn
index f122b12..a24337a 100644
--- a/ash/assistant/ui/BUILD.gn
+++ b/ash/assistant/ui/BUILD.gn
@@ -91,6 +91,8 @@
     "main_stage/assistant_text_element_view.h",
     "main_stage/assistant_ui_element_view.cc",
     "main_stage/assistant_ui_element_view.h",
+    "main_stage/assistant_ui_element_view_factory.cc",
+    "main_stage/assistant_ui_element_view_factory.h",
     "main_stage/element_animator.cc",
     "main_stage/element_animator.h",
     "main_stage/suggestion_chip_view.cc",
diff --git a/ash/assistant/ui/main_stage/assistant_text_element_view.cc b/ash/assistant/ui/main_stage/assistant_text_element_view.cc
index a252ade5..167baf5 100644
--- a/ash/assistant/ui/main_stage/assistant_text_element_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_text_element_view.cc
@@ -29,6 +29,12 @@
 }
 
 ui::Layer* AssistantTextElementView::GetLayerForAnimating() {
+  if (!layer()) {
+    // We'll be animating this view on its own layer so we need to initialize
+    // the layer for the view if we haven't done so already.
+    SetPaintToLayer();
+    layer()->SetFillsBoundsOpaquely(false);
+  }
   return layer();
 }
 
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc
new file mode 100644
index 0000000..9d1e176
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc
@@ -0,0 +1,35 @@
+// 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 "ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h"
+
+#include "ash/assistant/model/ui/assistant_card_element.h"
+#include "ash/assistant/model/ui/assistant_text_element.h"
+#include "ash/assistant/model/ui/assistant_ui_element.h"
+#include "ash/assistant/ui/assistant_view_delegate.h"
+#include "ash/assistant/ui/main_stage/assistant_card_element_view.h"
+#include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
+#include "ash/assistant/ui/main_stage/assistant_ui_element_view.h"
+
+namespace ash {
+
+AssistantUiElementViewFactory::AssistantUiElementViewFactory(
+    AssistantViewDelegate* delegate)
+    : delegate_(delegate) {}
+
+AssistantUiElementViewFactory::~AssistantUiElementViewFactory() = default;
+
+std::unique_ptr<AssistantUiElementView> AssistantUiElementViewFactory::Create(
+    AssistantUiElement* ui_element) const {
+  switch (ui_element->type()) {
+    case AssistantUiElementType::kCard:
+      return std::make_unique<AssistantCardElementView>(
+          delegate_, static_cast<AssistantCardElement*>(ui_element));
+    case AssistantUiElementType::kText:
+      return std::make_unique<AssistantTextElementView>(
+          static_cast<AssistantTextElement*>(ui_element));
+  }
+}
+
+}  // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h
new file mode 100644
index 0000000..bcdf6fb
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h
@@ -0,0 +1,38 @@
+// 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 ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_FACTORY_H_
+#define ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_FACTORY_H_
+
+#include <memory>
+
+#include "base/component_export.h"
+
+namespace ash {
+
+class AssistantUiElement;
+class AssistantUiElementView;
+class AssistantViewDelegate;
+
+// Factory class which creates Assistant views for modeled UI elements.
+class COMPONENT_EXPORT(ASSISTANT_UI) AssistantUiElementViewFactory {
+ public:
+  explicit AssistantUiElementViewFactory(AssistantViewDelegate* delegate);
+  AssistantUiElementViewFactory(AssistantViewDelegate& copy) = delete;
+  AssistantUiElementViewFactory operator=(
+      AssistantUiElementViewFactory& assign) = delete;
+  ~AssistantUiElementViewFactory();
+
+  // Creates a view for the specified |ui_element|.
+  std::unique_ptr<AssistantUiElementView> Create(
+      AssistantUiElement* ui_element) const;
+
+ private:
+  // Owned by AssistantController.
+  AssistantViewDelegate* const delegate_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_UI_ELEMENT_VIEW_FACTORY_H_
diff --git a/ash/assistant/ui/main_stage/ui_element_container_view.cc b/ash/assistant/ui/main_stage/ui_element_container_view.cc
index a0b206e..66e03d70 100644
--- a/ash/assistant/ui/main_stage/ui_element_container_view.cc
+++ b/ash/assistant/ui/main_stage/ui_element_container_view.cc
@@ -9,14 +9,13 @@
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
 #include "ash/assistant/model/assistant_response.h"
 #include "ash/assistant/model/ui/assistant_card_element.h"
-#include "ash/assistant/model/ui/assistant_text_element.h"
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/assistant/ui/assistant_view_delegate.h"
 #include "ash/assistant/ui/assistant_view_ids.h"
 #include "ash/assistant/ui/main_stage/animated_container_view.h"
 #include "ash/assistant/ui/main_stage/assistant_card_element_view.h"
-#include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
+#include "ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h"
 #include "ash/assistant/ui/main_stage/element_animator.h"
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "base/callback.h"
@@ -54,7 +53,8 @@
 // UiElementContainerView ------------------------------------------------------
 
 UiElementContainerView::UiElementContainerView(AssistantViewDelegate* delegate)
-    : AnimatedContainerView(delegate) {
+    : AnimatedContainerView(delegate),
+      view_factory_(std::make_unique<AssistantUiElementViewFactory>(delegate)) {
   SetID(AssistantViewID::kUiElementContainer);
   InitLayout();
 }
@@ -110,19 +110,23 @@
 
 void UiElementContainerView::HandleResponse(const AssistantResponse& response) {
   for (const auto& ui_element : response.GetUiElements()) {
-    switch (ui_element->type()) {
-      case AssistantUiElementType::kCard:
-        OnCardElementAdded(
-            static_cast<const AssistantCardElement*>(ui_element.get()));
-        break;
-      case AssistantUiElementType::kText:
-        OnTextElementAdded(
-            static_cast<const AssistantTextElement*>(ui_element.get()));
-        break;
+    // TODO(dmblack): Remove after deprecating standalone UI.
+    if (ui_element->type() == AssistantUiElementType::kCard) {
+      OnCardElementAdded(
+          static_cast<const AssistantCardElement*>(ui_element.get()));
+      continue;
     }
+    // Add a new view for the |ui_element| to the view hierarchy, bind an
+    // animator to handle all of its animations, and prepare its animation layer
+    // for the initial fade-in.
+    auto view = view_factory_->Create(ui_element.get());
+    auto* view_ptr = content_view()->AddChildView(std::move(view));
+    AddElementAnimator(view_ptr->CreateAnimator());
+    view_ptr->GetLayerForAnimating()->SetOpacity(0.f);
   }
 }
 
+// TODO(dmblack): Remove after deprecating standalone UI.
 void UiElementContainerView::OnCardElementAdded(
     const AssistantCardElement* card_element) {
   // The card, for some reason, is not embeddable so we'll have to ignore it.
@@ -156,22 +160,6 @@
   AddElementAnimator(card_element_view->CreateAnimator());
 }
 
-void UiElementContainerView::OnTextElementAdded(
-    const AssistantTextElement* text_element) {
-  auto* text_element_view = new AssistantTextElementView(text_element);
-
-  // The view will be animated on its own layer, so we need to do some initial
-  // layer setup. We're going to fade the view in, so hide it.
-  text_element_view->SetPaintToLayer();
-  text_element_view->layer()->SetFillsBoundsOpaquely(false);
-  text_element_view->layer()->SetOpacity(0.f);
-
-  content_view()->AddChildView(text_element_view);
-
-  // We set the animator to handle all animations for this view.
-  AddElementAnimator(text_element_view->CreateAnimator());
-}
-
 void UiElementContainerView::OnAllViewsRemoved() {
   // Reset state for the next response.
   is_first_card_ = true;
diff --git a/ash/assistant/ui/main_stage/ui_element_container_view.h b/ash/assistant/ui/main_stage/ui_element_container_view.h
index 2e098a15..134aa4f 100644
--- a/ash/assistant/ui/main_stage/ui_element_container_view.h
+++ b/ash/assistant/ui/main_stage/ui_element_container_view.h
@@ -20,12 +20,12 @@
 
 class AssistantResponse;
 class AssistantCardElement;
-class AssistantTextElement;
+class AssistantUiElementViewFactory;
 class AssistantViewDelegate;
 
 // UiElementContainerView is the child of AssistantMainView concerned with
-// laying out text views and embedded card views in response to Assistant
-// interaction model UI element events.
+// laying out Assistant UI element views in response to Assistant interaction
+// model events.
 class COMPONENT_EXPORT(ASSISTANT_UI) UiElementContainerView
     : public AnimatedContainerView {
  public:
@@ -49,7 +49,9 @@
   void OnAllViewsAnimatedIn() override;
 
   void OnCardElementAdded(const AssistantCardElement* card_element);
-  void OnTextElementAdded(const AssistantTextElement* text_element);
+
+  // Factory instance used to construct views for modeled UI elements.
+  std::unique_ptr<AssistantUiElementViewFactory> view_factory_;
 
   // Whether or not the card we are adding is the first card for the current
   // Assistant response. The first card requires the addition of a top margin.
diff --git a/ash/home_screen/home_screen_controller.cc b/ash/home_screen/home_screen_controller.cc
index a80ba65..f91a8c34 100644
--- a/ash/home_screen/home_screen_controller.cc
+++ b/ash/home_screen/home_screen_controller.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <vector>
 
+#include "ash/app_list/app_list_controller_impl.h"
 #include "ash/home_screen/home_launcher_gesture_handler.h"
 #include "ash/home_screen/home_screen_delegate.h"
 #include "ash/home_screen/window_scale_animation.h"
@@ -91,6 +92,10 @@
 bool HomeScreenController::GoHome(int64_t display_id) {
   DCHECK(Shell::Get()->tablet_mode_controller()->InTabletMode());
 
+  auto* app_list_controller = Shell::Get()->app_list_controller();
+  if (app_list_controller->IsShowingEmbeddedAssistantUI()) {
+    app_list_controller->presenter()->ShowEmbeddedAssistantUI(false);
+  }
   OverviewController* overview_controller = Shell::Get()->overview_controller();
   SplitViewController* split_view_controller =
       SplitViewController::Get(Shell::GetPrimaryRootWindow());
@@ -239,6 +244,12 @@
 void HomeScreenController::OnWindowDragStarted() {
   in_window_dragging_ = true;
   UpdateVisibility();
+
+  // Dismiss Assistant if it's running when a window drag starts.
+  if (Shell::Get()->app_list_controller()->IsShowingEmbeddedAssistantUI()) {
+    Shell::Get()->app_list_controller()->presenter()->ShowEmbeddedAssistantUI(
+        false);
+  }
 }
 
 void HomeScreenController::OnWindowDragEnded(bool animate) {
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index fce0b11..b732bb8 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -1257,7 +1257,6 @@
        overview_mode_will_start_) &&
       !overview_controller->IsCompletingShutdownAnimations();
   const bool app_list_visible =
-      app_list_controller->IsVisible() ||
       app_list_controller->GetTargetVisibility() ||
       (!in_overview && app_list_controller->ShouldHomeLauncherBeVisible());
 
@@ -1281,13 +1280,8 @@
         case AppListControllerImpl::HomeLauncherTransitionState::kMostlyHidden:
           return in_overview ? HotseatState::kExtended : HotseatState::kHidden;
         case AppListControllerImpl::HomeLauncherTransitionState::kFinished:
-          // Consider the AppList visible if it is beginning to show. Also
-          // detect the case where the last window is being minimized.
-          if (app_list_controller->GetTargetVisibility() ||
-              (!in_overview &&
-               app_list_controller->ShouldHomeLauncherBeVisible())) {
+          if (app_list_visible)
             return HotseatState::kShown;
-          }
 
           // Show the hotseat if the shelf view's context menu is showing.
           if (shelf_widget_->hotseat_widget()->IsShowingShelfMenu())
diff --git a/ash/system/OWNERS b/ash/system/OWNERS
index b14b091..057af8f 100644
--- a/ash/system/OWNERS
+++ b/ash/system/OWNERS
@@ -1,4 +1,3 @@
-stevenjb@chromium.org
 jennyz@chromium.org
 skuhne@chromium.org
 tetsui@chromium.org
diff --git a/ash/wm/drag_window_controller.cc b/ash/wm/drag_window_controller.cc
index 0705e1e..5fc65291 100644
--- a/ash/wm/drag_window_controller.cc
+++ b/ash/wm/drag_window_controller.cc
@@ -23,6 +23,7 @@
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/compositor/paint_context.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/compositor_extra/shadow.h"
 #include "ui/display/display.h"
 #include "ui/gfx/transform_util.h"
 #include "ui/views/view.h"
@@ -84,7 +85,9 @@
     DCHECK(!drag_window_);
   }
 
-  void Update(aura::Window* original_window, bool is_touch_dragging) {
+  void Update(aura::Window* original_window,
+              bool is_touch_dragging,
+              const base::Optional<gfx::Rect>& shadow_bounds) {
     const float opacity =
         GetDragWindowOpacity(root_window_, original_window, is_touch_dragging);
     if (opacity == 0.f) {
@@ -93,10 +96,11 @@
       // when it becomes necessary again.
       DCHECK(!drag_window_);
       layer_owner_.reset();
+      shadow_.reset();
       return;
     }
     if (!drag_window_)
-      CreateDragWindow(original_window);
+      CreateDragWindow(original_window, shadow_bounds);
 
     gfx::Rect bounds = original_window->bounds();
     aura::Window::ConvertRectToTarget(original_window->parent(),
@@ -109,7 +113,8 @@
  private:
   friend class DragWindowController;
 
-  void CreateDragWindow(aura::Window* original_window) {
+  void CreateDragWindow(aura::Window* original_window,
+                        const base::Optional<gfx::Rect>& shadow_bounds) {
     DCHECK(!drag_window_);
     drag_window_ = window_factory::NewWindow(this).release();
     int parent_id = original_window->parent()->id();
@@ -125,7 +130,16 @@
     drag_window_->SetProperty(aura::client::kAnimationsDisabledKey, true);
     container->AddChild(drag_window_);
     drag_window_->SetBounds(bounds);
-    ::wm::SetShadowElevation(drag_window_, ::wm::kShadowElevationActiveWindow);
+
+    if (shadow_bounds) {
+      shadow_ = std::make_unique<ui::Shadow>();
+      shadow_->Init(::wm::kShadowElevationActiveWindow);
+      shadow_->SetContentBounds(*shadow_bounds);
+      drag_window_->layer()->Add(shadow_->layer());
+    } else {
+      ::wm::SetShadowElevation(drag_window_,
+                               ::wm::kShadowElevationActiveWindow);
+    }
 
     RecreateWindowLayers(original_window);
     drag_window_->layer()->Add(layer_owner_->root());
@@ -195,13 +209,18 @@
   // The copy of window_->layer() and its descendants.
   std::unique_ptr<ui::LayerTreeOwner> layer_owner_;
 
+  std::unique_ptr<ui::Shadow> shadow_;
+
   DISALLOW_COPY_AND_ASSIGN(DragWindowDetails);
 };
 
-DragWindowController::DragWindowController(aura::Window* window,
-                                           bool is_touch_dragging)
+DragWindowController::DragWindowController(
+    aura::Window* window,
+    bool is_touch_dragging,
+    const base::Optional<gfx::Rect>& shadow_bounds)
     : window_(window),
       is_touch_dragging_(is_touch_dragging),
+      shadow_bounds_(shadow_bounds),
       old_opacity_(window->layer()->opacity()) {
   DCHECK(drag_windows_.empty());
   display::Screen* screen = display::Screen::GetScreen();
@@ -229,7 +248,7 @@
   }
 
   for (std::unique_ptr<DragWindowDetails>& details : drag_windows_)
-    details->Update(window_, is_touch_dragging_);
+    details->Update(window_, is_touch_dragging_, shadow_bounds_);
 }
 
 int DragWindowController::GetDragWindowsCountForTest() const {
@@ -265,6 +284,18 @@
   return nullptr;
 }
 
+const ui::Shadow* DragWindowController::GetDragWindowShadowForTest(
+    size_t index) const {
+  for (const std::unique_ptr<DragWindowDetails>& details : drag_windows_) {
+    if (details->drag_window_) {
+      if (index == 0)
+        return details->shadow_.get();
+      index--;
+    }
+  }
+  return nullptr;
+}
+
 void DragWindowController::RequestLayerPaintForTest() {
   ui::PaintContext context(nullptr, 1.0f, gfx::Rect(),
                            window_->GetHost()->compositor()->is_pixel_canvas());
diff --git a/ash/wm/drag_window_controller.h b/ash/wm/drag_window_controller.h
index 82408703..e4067ef 100644
--- a/ash/wm/drag_window_controller.h
+++ b/ash/wm/drag_window_controller.h
@@ -11,6 +11,7 @@
 #include "ash/ash_export.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace aura {
@@ -19,6 +20,7 @@
 
 namespace ui {
 class LayerTreeOwner;
+class Shadow;
 }
 
 namespace ash {
@@ -27,7 +29,10 @@
 // Phantom windows called "drag windows" represent the window on other displays.
 class ASH_EXPORT DragWindowController {
  public:
-  DragWindowController(aura::Window* window, bool is_touch_dragging);
+  DragWindowController(
+      aura::Window* window,
+      bool is_touch_dragging,
+      const base::Optional<gfx::Rect>& shadow_bounds = base::nullopt);
   virtual ~DragWindowController();
 
   // Updates bounds and opacity for the drag windows, and creates/destroys each
@@ -40,6 +45,8 @@
   FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, DragWindowController);
   FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest,
                            DragWindowControllerAcrossThreeDisplays);
+  FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest,
+                           DragWindowControllerWithCustomShadowBounds);
 
   // Returns the currently active drag windows.
   int GetDragWindowsCountForTest() const;
@@ -48,6 +55,7 @@
   // currently active drag windows list.
   const aura::Window* GetDragWindowForTest(size_t index) const;
   const ui::LayerTreeOwner* GetDragLayerOwnerForTest(size_t index) const;
+  const ui::Shadow* GetDragWindowShadowForTest(size_t index) const;
 
   // Call Layer::OnPaintLayer on all layers under the drag_windows_.
   void RequestLayerPaintForTest();
@@ -58,6 +66,9 @@
   // Indicates touch dragging, as opposed to mouse dragging.
   const bool is_touch_dragging_;
 
+  // Used if the drag windows may need their shadows adjusted.
+  const base::Optional<gfx::Rect> shadow_bounds_;
+
   // |window_|'s opacity before the drag. Used to revert opacity after the drag.
   const float old_opacity_;
 
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc
index 2eda9fc..d4ea9237 100644
--- a/ash/wm/drag_window_resizer_unittest.cc
+++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -17,6 +17,7 @@
 #include "ash/wm/drag_window_controller.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_util.h"
+#include "base/optional.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "ui/aura/client/aura_constants.h"
@@ -26,6 +27,7 @@
 #include "ui/base/ui_base_types.h"
 #include "ui/compositor/layer_delegate.h"
 #include "ui/compositor/layer_tree_owner.h"
+#include "ui/compositor_extra/shadow.h"
 #include "ui/display/display_layout.h"
 #include "ui/display/display_layout_builder.h"
 #include "ui/display/manager/display_manager.h"
@@ -588,6 +590,77 @@
   EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
 }
 
+TEST_F(DragWindowResizerTest, DragWindowControllerWithCustomShadowBounds) {
+  UpdateDisplay("400x600,400x600,800x600");
+  aura::Window::Windows root_windows = Shell::GetAllRootWindows();
+
+  // Layout so that all three displays touch each other.
+  display::DisplayIdList list = display_manager()->GetCurrentDisplayIdList();
+  ASSERT_EQ(3u, list.size());
+  ASSERT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().id(), list[0]);
+  display::DisplayLayoutBuilder builder(list[0]);
+  builder.AddDisplayPlacement(list[1], list[0],
+                              display::DisplayPlacement::RIGHT, 0);
+  builder.AddDisplayPlacement(list[2], list[0],
+                              display::DisplayPlacement::BOTTOM, 0);
+  display_manager()->SetLayoutForCurrentDisplays(builder.Build());
+  const display::Display& display0 =
+      display_manager()->GetDisplayForId(list[0]);
+  const display::Display& display1 =
+      display_manager()->GetDisplayForId(list[1]);
+  const display::Display& display2 =
+      display_manager()->GetDisplayForId(list[2]);
+  // Sanity check.
+  ASSERT_EQ(gfx::Rect(0, 000, 400, 600), display0.bounds());
+  ASSERT_EQ(gfx::Rect(400, 0, 400, 600), display1.bounds());
+  ASSERT_EQ(gfx::Rect(0, 600, 800, 600), display2.bounds());
+
+  const gfx::Rect shadow_bounds(10, 10, 200, 200);
+  const auto update_controller_and_check_root_and_shadow =
+      [&shadow_bounds](DragWindowController* controller,
+                       aura::Window* root_window) {
+        controller->Update();
+        ASSERT_EQ(1, controller->GetDragWindowsCountForTest());
+        EXPECT_EQ(root_window,
+                  controller->GetDragWindowForTest(0)->GetRootWindow());
+        const ui::Shadow* shadow = controller->GetDragWindowShadowForTest(0);
+        ASSERT_TRUE(shadow);
+        ASSERT_TRUE(shadow->layer());
+        EXPECT_TRUE(shadow->layer()->visible());
+        EXPECT_EQ(shadow_bounds, shadow->content_bounds());
+      };
+  // Test mouse dragging.
+  {
+    wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
+    // Start on |display1|.
+    cursor_manager->SetDisplay(display1);
+    window_->SetBoundsInScreen(gfx::Rect(420, 20, 100, 100), display1);
+    DragWindowController controller(window_.get(), /*is_touch_dragging=*/false,
+                                    base::make_optional(shadow_bounds));
+    // Move to |display0|.
+    cursor_manager->SetDisplay(display0);
+    window_->SetBoundsInScreen(gfx::Rect(20, 20, 100, 100), display0);
+    update_controller_and_check_root_and_shadow(&controller, root_windows[0]);
+    // Move to |display2|.
+    cursor_manager->SetDisplay(display2);
+    window_->SetBoundsInScreen(gfx::Rect(20, 620, 100, 100), display2);
+    update_controller_and_check_root_and_shadow(&controller, root_windows[2]);
+  }
+  // Test touch dragging.
+  {
+    // Start on |display0|.
+    window_->SetBoundsInScreen(gfx::Rect(20, 20, 100, 100), display0);
+    DragWindowController controller(window_.get(), /*is_touch_dragging=*/true,
+                                    base::make_optional(shadow_bounds));
+    // Move the window so some is visible on |display1|.
+    window_->SetBoundsInScreen(gfx::Rect(380, 20, 100, 100), display0);
+    update_controller_and_check_root_and_shadow(&controller, root_windows[1]);
+    // Move the window so some is visible on |display2|.
+    window_->SetBoundsInScreen(gfx::Rect(20, 580, 100, 100), display0);
+    update_controller_and_check_root_and_shadow(&controller, root_windows[2]);
+  }
+}
+
 // Verifies if the resizer sets and resets
 // MouseCursorEventFilter::mouse_warp_mode_ as expected.
 TEST_F(DragWindowResizerTest, WarpMousePointer) {
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index 3fa61f9..35f94b3 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -712,10 +712,13 @@
   DCHECK(AreMultiDisplayOverviewAndSplitViewEnabled());
   DCHECK_GT(Shell::GetAllRootWindows().size(), 1u);
   if (!phantoms_for_dragging_) {
-    phantoms_for_dragging_ = std::make_unique<DragWindowController>(
-        transform_window_.IsMinimized() ? item_widget_->GetNativeWindow()
-                                        : GetWindow(),
-        is_touch_dragging);
+    phantoms_for_dragging_ =
+        transform_window_.IsMinimized()
+            ? std::make_unique<DragWindowController>(
+                  item_widget_->GetNativeWindow(), is_touch_dragging,
+                  base::make_optional(shadow_->content_bounds()))
+            : std::make_unique<DragWindowController>(GetWindow(),
+                                                     is_touch_dragging);
   }
   phantoms_for_dragging_->Update();
 }
diff --git a/ash/wm/overview/overview_item.h b/ash/wm/overview/overview_item.h
index f8dc3ae..0be8e6eb 100644
--- a/ash/wm/overview/overview_item.h
+++ b/ash/wm/overview/overview_item.h
@@ -14,6 +14,7 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/base/allocator/partition_allocator/page_allocator.cc b/base/allocator/partition_allocator/page_allocator.cc
index b2e8cf3..28d90fe 100644
--- a/base/allocator/partition_allocator/page_allocator.cc
+++ b/base/allocator/partition_allocator/page_allocator.cc
@@ -239,14 +239,21 @@
   return false;
 }
 
-void ReleaseReservation() {
+bool ReleaseReservation() {
   // To avoid deadlock, call only FreePages.
   subtle::SpinLock::Guard guard(GetReserveLock());
-  if (s_reservation_address != nullptr) {
-    FreePages(s_reservation_address, s_reservation_size);
-    s_reservation_address = nullptr;
-    s_reservation_size = 0;
-  }
+  if (!s_reservation_address)
+    return false;
+
+  FreePages(s_reservation_address, s_reservation_size);
+  s_reservation_address = nullptr;
+  s_reservation_size = 0;
+  return true;
+}
+
+bool HasReservationForTesting() {
+  subtle::SpinLock::Guard guard(GetReserveLock());
+  return s_reservation_address != nullptr;
 }
 
 uint32_t GetAllocPageErrorCode() {
diff --git a/base/allocator/partition_allocator/page_allocator.h b/base/allocator/partition_allocator/page_allocator.h
index a93694b..da070bc 100644
--- a/base/allocator/partition_allocator/page_allocator.h
+++ b/base/allocator/partition_allocator/page_allocator.h
@@ -182,7 +182,12 @@
 
 // Releases any reserved address space. |AllocPages| calls this automatically on
 // an allocation failure. External allocators may also call this on failure.
-BASE_EXPORT void ReleaseReservation();
+//
+// Returns true when an existing reservation was released.
+BASE_EXPORT bool ReleaseReservation();
+
+// Returns true if there is currently an address space reservation.
+BASE_EXPORT bool HasReservationForTesting();
 
 // Returns |errno| (POSIX) or the result of |GetLastError| (Windows) when |mmap|
 // (POSIX) or |VirtualAlloc| (Windows) fails.
diff --git a/base/android/jni_generator/BUILD.gn b/base/android/jni_generator/BUILD.gn
index 89e32d2..8e95c35 100644
--- a/base/android/jni_generator/BUILD.gn
+++ b/base/android/jni_generator/BUILD.gn
@@ -29,9 +29,7 @@
 }
 
 android_library("jni_annotation_sample_java") {
-  sources = [
-    "java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java",
-  ]
+  sources = [ "java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java" ]
   deps = [
     "//base:base_java",
     "//base:jni_java",
@@ -86,9 +84,7 @@
 
 java_cpp_template("processor_args_java") {
   package_path = "org/chromium/jni_generator"
-  sources = [
-    "ProcessorArgs.template",
-  ]
+  sources = [ "ProcessorArgs.template" ]
   defines = [ "HASH_JNI_NAMES_VALUE=$use_hashed_jni_names" ]
 }
 
diff --git a/base/process/memory_linux.cc b/base/process/memory_linux.cc
index 483168b..1e82812 100644
--- a/base/process/memory_linux.cc
+++ b/base/process/memory_linux.cc
@@ -10,6 +10,7 @@
 
 #include "base/allocator/allocator_shim.h"
 #include "base/allocator/buildflags.h"
+#include "base/allocator/partition_allocator/page_allocator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
@@ -37,10 +38,18 @@
   LOG(FATAL) << "Out of memory.";
 }
 
-void OnNoMemory() {
+// NOINLINE as base::`anonymous namespace`::OnNoMemory() is recognized by the
+// crash server.
+NOINLINE void OnNoMemory() {
   OnNoMemorySize(0);
 }
 
+void ReleaseReservationOrTerminate() {
+  if (ReleaseReservation())
+    return;
+  OnNoMemory();
+}
+
 }  // namespace
 
 void EnableTerminationOnHeapCorruption() {
@@ -49,7 +58,7 @@
 
 void EnableTerminationOnOutOfMemory() {
   // Set the new-out of memory handler.
-  std::set_new_handler(&OnNoMemory);
+  std::set_new_handler(&ReleaseReservationOrTerminate);
   // If we're using glibc's allocator, the above functions will override
   // malloc and friends and make them die on out of memory.
 
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
index f45e98a..abce67e77 100644
--- a/base/process/memory_unittest.cc
+++ b/base/process/memory_unittest.cc
@@ -9,9 +9,11 @@
 #include <stddef.h>
 
 #include <limits>
+#include <vector>
 
 #include "base/allocator/allocator_check.h"
 #include "base/allocator/buildflags.h"
+#include "base/allocator/partition_allocator/page_allocator.h"
 #include "base/compiler_specific.h"
 #include "base/debug/alias.h"
 #include "base/memory/aligned_memory.h"
@@ -497,6 +499,66 @@
 }
 #endif  // OS_WIN
 
+#if defined(ARCH_CPU_32_BITS) && (defined(OS_WIN) || defined(OS_LINUX))
+
+void TestAllocationsReleaseReservation(void* (*alloc_fn)(size_t),
+                                       void (*free_fn)(void*)) {
+  base::ReleaseReservation();
+  base::EnableTerminationOnOutOfMemory();
+
+  constexpr size_t kMiB = 1 << 20;
+  constexpr size_t kReservationSize = 512 * kMiB;  // MiB.
+
+  size_t reservation_size = kReservationSize;
+  while (!base::ReserveAddressSpace(reservation_size)) {
+    reservation_size -= 16 * kMiB;
+  }
+  ASSERT_TRUE(base::HasReservationForTesting());
+  ASSERT_GT(reservation_size, 0u);
+
+  // Allocate a large area at a time to bump into address space exhaustion
+  // before other limits. It is important not to do a larger allocation, to
+  // verify that we can allocate without removing the reservation. On the other
+  // hand, must be large enough to make the underlying implementation call
+  // mmap()/VirtualAlloc().
+  size_t allocation_size = reservation_size / 2;
+
+  std::vector<void*> areas;
+  // Pre-reserve the vector to make sure that we don't hit the address space
+  // limit while resizing the array.
+  areas.reserve(((2 * 4096 * kMiB) / allocation_size) + 1);
+
+  while (true) {
+    void* area = alloc_fn(allocation_size / 2);
+    ASSERT_TRUE(area);
+    areas.push_back(area);
+
+    // Working as intended, the allocation was successful, and the reservation
+    // was dropped instead of crashing.
+    //
+    // Meaning that the test is either successful, or crashes.
+    if (!base::HasReservationForTesting())
+      break;
+  }
+
+  EXPECT_GE(areas.size(), 2u)
+      << "Should be able to allocate without releasing the reservation";
+
+  for (void* ptr : areas)
+    free_fn(ptr);
+}
+
+TEST_F(OutOfMemoryHandledTest, MallocReleasesReservation) {
+  TestAllocationsReleaseReservation(malloc, free);
+}
+
+TEST_F(OutOfMemoryHandledTest, NewReleasesReservation) {
+  TestAllocationsReleaseReservation(
+      [](size_t size) { return static_cast<void*>(new char[size]); },
+      [](void* ptr) { delete[] static_cast<char*>(ptr); });
+}
+#endif  // defined(ARCH_CPU_32_BITS) && (defined(OS_WIN) || defined(OS_LINUX))
+
 // TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work
 // on Windows as well.
 TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
diff --git a/base/process/memory_win.cc b/base/process/memory_win.cc
index 4fff911..aaa9494 100644
--- a/base/process/memory_win.cc
+++ b/base/process/memory_win.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/allocator/partition_allocator/page_allocator.h"
 #include "base/process/memory.h"
 #include "base/stl_util.h"
 
@@ -43,7 +44,7 @@
 #pragma warning(push)
 #pragma warning(disable: 4702)  // Unreachable code after the _exit.
 
-NOINLINE int OnNoMemory(size_t size) {
+[[noreturn]] NOINLINE int OnNoMemory(size_t size) {
   // Kill the process. This is important for security since most of code
   // does not check the result of memory allocation.
   // https://msdn.microsoft.com/en-us/library/het71c37.aspx
@@ -54,11 +55,18 @@
 
   // Safety check, make sure process exits here.
   _exit(win::kOomExceptionCode);
-  return 0;
 }
 
 #pragma warning(pop)
 
+// Return a non-0 value to retry the allocation.
+int ReleaseReservationOrTerminate(size_t size) {
+  constexpr int kRetryAllocation = 1;
+  if (ReleaseReservation())
+    return kRetryAllocation;
+  OnNoMemory(size);
+}
+
 }  // namespace
 
 void TerminateBecauseOutOfMemory(size_t size) {
@@ -71,8 +79,9 @@
 }
 
 void EnableTerminationOnOutOfMemory() {
-  _set_new_handler(&OnNoMemory);
-  _set_new_mode(1);
+  constexpr int kCallNewHandlerOnAllocationFailure = 1;
+  _set_new_handler(&ReleaseReservationOrTerminate);
+  _set_new_mode(kCallNewHandlerOnAllocationFailure);
 }
 
 // Implemented using a weak symbol.
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index e83c2f3b..7a58bc33 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -25,9 +25,7 @@
       # to add the ldflags here as well as in default_sanitizer_flags.
       ":default_sanitizer_ldflags",
     ]
-    deps = [
-      ":options_sources",
-    ]
+    deps = [ ":options_sources" ]
     if (is_win) {
       exe = ".exe"
     } else {
@@ -47,14 +45,10 @@
     # used (Chromium version of clang versus Xcode version of clang). Only copy
     # the ASAN runtime on iOS if building with Chromium clang.
     if (is_win || is_mac || (is_ios && !use_xcode_clang)) {
-      data_deps = [
-        ":copy_asan_runtime",
-      ]
+      data_deps = [ ":copy_asan_runtime" ]
     }
     if (is_mac || (is_ios && !use_xcode_clang)) {
-      public_deps = [
-        ":asan_runtime_bundle_data",
-      ]
+      public_deps = [ ":asan_runtime_bundle_data" ]
     }
   }
 }
@@ -76,24 +70,16 @@
 
   if (!is_ios) {
     copy("copy_asan_runtime") {
-      sources = [
-        _clang_rt_dso_full_path,
-      ]
-      outputs = [
-        "$root_out_dir/{{source_file_part}}",
-      ]
+      sources = [ _clang_rt_dso_full_path ]
+      outputs = [ "$root_out_dir/{{source_file_part}}" ]
     }
   } else {
     # On iOS, the runtime library need to be code signed (adhoc signature)
     # starting with Xcode 8, so use an action instead of a copy on iOS.
     action("copy_asan_runtime") {
       script = "//build/config/ios/codesign.py"
-      sources = [
-        _clang_rt_dso_full_path,
-      ]
-      outputs = [
-        "$root_out_dir/" + get_path_info(sources[0], "file"),
-      ]
+      sources = [ _clang_rt_dso_full_path ]
+      outputs = [ "$root_out_dir/" + get_path_info(sources[0], "file") ]
       args = [
         "code-sign-file",
         "--identity=" + ios_code_signing_identity,
@@ -106,12 +92,8 @@
   if (is_mac || is_ios) {
     bundle_data("asan_runtime_bundle_data") {
       sources = get_target_outputs(":copy_asan_runtime")
-      outputs = [
-        "{{bundle_executable_dir}}/{{source_file_part}}",
-      ]
-      public_deps = [
-        ":copy_asan_runtime",
-      ]
+      outputs = [ "{{bundle_executable_dir}}/{{source_file_part}}" ]
+      public_deps = [ ":copy_asan_runtime" ]
     }
   }
 }
@@ -131,9 +113,7 @@
     ":deps",
     "//:gn_visibility",
   ]
-  sources = [
-    "//build/sanitizers/sanitizer_options.cc",
-  ]
+  sources = [ "//build/sanitizers/sanitizer_options.cc" ]
 
   # Don't compile this target with any sanitizer code. It can be called from
   # the sanitizer runtimes, so instrumenting these functions could cause
diff --git a/build/fuchsia/layout_test_proxy/BUILD.gn b/build/fuchsia/layout_test_proxy/BUILD.gn
deleted file mode 100644
index ad06507..0000000
--- a/build/fuchsia/layout_test_proxy/BUILD.gn
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_fuchsia)
-
-import("//testing/test.gni")
-
-# Binary used to proxy TCP connections from a Fuchsia process. Potentially SSH
-# can be used to forward TCP, but this feature is currently broken on Fuchsia,
-# see ZX-1555. layout_test_proxy can be removed once that issue with sshd is
-# fixed and layout tests are updated to use SSH.
-executable("layout_test_proxy") {
-  testonly = true
-  sources = [
-    "layout_test_proxy.cc",
-  ]
-  deps = [
-    "//net",
-    "//net:test_support",
-  ]
-}
-
-fuchsia_package("layout_test_proxy_pkg") {
-  testonly = true
-  binary = ":layout_test_proxy"
-  package_name_override = "layout_test_proxy"
-}
-
-fuchsia_package_runner("layout_test_proxy_runner") {
-  testonly = true
-  package = ":layout_test_proxy_pkg"
-  package_name_override = "layout_test_proxy"
-}
diff --git a/build/fuchsia/layout_test_proxy/DEPS b/build/fuchsia/layout_test_proxy/DEPS
deleted file mode 100644
index 8fa9d48..0000000
--- a/build/fuchsia/layout_test_proxy/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+net",
-]
diff --git a/build/fuchsia/layout_test_proxy/layout_test_proxy.cc b/build/fuchsia/layout_test_proxy/layout_test_proxy.cc
deleted file mode 100644
index bc36a4a..0000000
--- a/build/fuchsia/layout_test_proxy/layout_test_proxy.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/message_loop/message_pump_type.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/task/single_thread_task_executor.h"
-#include "net/base/ip_endpoint.h"
-#include "net/test/tcp_socket_proxy.h"
-
-const char kPortsSwitch[] = "ports";
-const char kRemoteAddressSwitch[] = "remote-address";
-
-int main(int argc, char** argv) {
-  base::CommandLine::Init(argc, argv);
-
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-
-  if (!command_line->HasSwitch(kPortsSwitch)) {
-    LOG(ERROR) << "--" << kPortsSwitch << " was not specified.";
-    return 1;
-  }
-
-  std::vector<std::string> ports_strings =
-      base::SplitString(command_line->GetSwitchValueASCII(kPortsSwitch), ",",
-                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
-  if (ports_strings.empty()) {
-    LOG(ERROR) << "At least one port must be specified with --" << kPortsSwitch;
-    return 1;
-  }
-
-  std::vector<int> ports;
-  for (auto& port_string : ports_strings) {
-    int port;
-    if (!base::StringToInt(port_string, &port) || port <= 0 || port > 65535) {
-      LOG(ERROR) << "Invalid value specified for --" << kPortsSwitch << ": "
-                 << port_string;
-      return 1;
-    }
-    ports.push_back(port);
-  }
-
-  if (!command_line->HasSwitch(kRemoteAddressSwitch)) {
-    LOG(ERROR) << "--" << kRemoteAddressSwitch << " was not specified.";
-    return 1;
-  }
-
-  std::string remote_address_str =
-      command_line->GetSwitchValueASCII(kRemoteAddressSwitch);
-  net::IPAddress remote_address;
-  if (!remote_address.AssignFromIPLiteral(remote_address_str)) {
-    LOG(ERROR) << "Invalid value specified for --" << kRemoteAddressSwitch
-               << ": " << remote_address_str;
-    return 1;
-  }
-
-  base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
-
-  std::vector<std::unique_ptr<net::TcpSocketProxy>> proxies;
-
-  for (int port : ports) {
-    auto test_server_proxy =
-        std::make_unique<net::TcpSocketProxy>(io_task_executor.task_runner());
-    if (!test_server_proxy->Initialize(port)) {
-      LOG(ERROR) << "Can't bind proxy to port " << port;
-      return 1;
-    }
-    LOG(INFO) << "Listening on port " << test_server_proxy->local_port();
-    test_server_proxy->Start(net::IPEndPoint(remote_address, port));
-    proxies.push_back(std::move(test_server_proxy));
-  }
-
-  // Run the task executor indefinitely.
-  base::RunLoop().Run();
-
-  return 0;
-}
diff --git a/build/fuchsia/run_package.py b/build/fuchsia/run_package.py
index c8304ad..699828e9 100644
--- a/build/fuchsia/run_package.py
+++ b/build/fuchsia/run_package.py
@@ -120,19 +120,15 @@
   symbolizer_config: A newline delimited list of source files contained
       in the package. Omitting this parameter will disable symbolization.
   system_logging: If set, connects a system log reader to the target.
-  target_staging_path: Path to which package FARs will be staged, during
-      installation. Defaults to staging into '/data'.
   """
   def __init__(self):
     self.symbolizer_config = None
     self.system_logging = False
-    self.target_staging_path = '/data'
 
   @staticmethod
   def FromCommonArgs(args):
     run_package_args = RunPackageArgs()
     run_package_args.system_logging = args.include_system_logs
-    run_package_args.target_staging_path = args.target_staging_path
     return run_package_args
 
 
diff --git a/build/mac/tweak_info_plist.gni b/build/mac/tweak_info_plist.gni
index 9f4cbb3..2a79b0d5e 100644
--- a/build/mac/tweak_info_plist.gni
+++ b/build/mac/tweak_info_plist.gni
@@ -34,9 +34,7 @@
       forward_variables_from(invoker, [ "testonly" ])
       script = "//build/config/mac/plist_util.py"
       sources = invoker.info_plists
-      outputs = [
-        _source_name,
-      ]
+      outputs = [ _source_name ]
       args = [
                "merge",
                "-f=xml1",
@@ -64,12 +62,8 @@
       lastchange_file,
       "//chrome/VERSION",
     ]
-    sources = [
-      _source_name,
-    ]
-    outputs = [
-      _output_name,
-    ]
+    sources = [ _source_name ]
+    outputs = [ _output_name ]
     if (!defined(args)) {
       args = []
     }
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index fdf783c..d78946e 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -209,9 +209,7 @@
       command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "CC {{output}}"
-      outputs = [
-        "$object_subdir/{{source_name_part}}.o",
-      ]
+      outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }
 
     tool("cxx") {
@@ -220,9 +218,7 @@
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "CXX {{output}}"
-      outputs = [
-        "$object_subdir/{{source_name_part}}.o",
-      ]
+      outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }
 
     tool("asm") {
@@ -231,9 +227,7 @@
       command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "ASM {{output}}"
-      outputs = [
-        "$object_subdir/{{source_name_part}}.o",
-      ]
+      outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }
 
     tool("objc") {
@@ -242,9 +236,7 @@
       command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objc}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "OBJC {{output}}"
-      outputs = [
-        "$object_subdir/{{source_name_part}}.o",
-      ]
+      outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }
 
     tool("objcxx") {
@@ -253,9 +245,7 @@
       command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_objcc}} -c {{source}} -o {{output}}"
       depsformat = "gcc"
       description = "OBJCXX {{output}}"
-      outputs = [
-        "$object_subdir/{{source_name_part}}.o",
-      ]
+      outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }
 
     tool("alink") {
@@ -277,9 +267,7 @@
       libtool = mac_bin_path + "libtool"
       command = "rm -f {{output}} && TOOL_VERSION=${tool_versions.filter_libtool} python $script $libtool -static {{arflags}} -o {{output}} -filelist $rspfile"
       description = "LIBTOOL-STATIC {{output}}"
-      outputs = [
-        "{{output_dir}}/{{target_output_name}}{{output_extension}}",
-      ]
+      outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
       default_output_dir = "{{target_out_dir}}"
       default_output_extension = ".a"
       output_prefix = "lib"
@@ -379,9 +367,7 @@
       default_output_dir = "{{root_out_dir}}"
       default_output_extension = ".so"
 
-      outputs = [
-        sofile,
-      ]
+      outputs = [ sofile ]
 
       if (_enable_dsyms) {
         outputs += dsym_output
@@ -407,9 +393,7 @@
       command = "$linker_driver $ld $dsym_switch {{ldflags}} -o \"$outfile\" -Wl,-filelist,\"$rspfile\" {{solibs}} {{libs}}"
       description = "LINK $outfile"
       rspfile_content = "{{inputs_newline}}"
-      outputs = [
-        outfile,
-      ]
+      outputs = [ outfile ]
 
       if (_enable_dsyms) {
         outputs += dsym_output
diff --git a/cc/input/browser_controls_offset_manager.cc b/cc/input/browser_controls_offset_manager.cc
index fb59212a..80c45af 100644
--- a/cc/input/browser_controls_offset_manager.cc
+++ b/cc/input/browser_controls_offset_manager.cc
@@ -23,6 +23,8 @@
 // These constants were chosen empirically for their visually pleasant behavior.
 // Contact tedchoc@chromium.org for questions about changing these values.
 const int64_t kShowHideMaxDurationMs = 200;
+// TODO(sinansahin): Temporary value, pending UX guidance probably.
+const int64_t kHeightChangeDurationMs = 200;
 }
 
 // static
@@ -48,6 +50,7 @@
       pinch_gesture_active_(false),
       constraint_changed_since_commit_(false) {
   CHECK(client_);
+  UpdateOldBrowserControlsParams();
 }
 
 BrowserControlsOffsetManager::~BrowserControlsOffsetManager() = default;
@@ -101,6 +104,24 @@
   return client_->CurrentBottomControlsShownRatio();
 }
 
+std::pair<float, float>
+BrowserControlsOffsetManager::TopControlsShownRatioRange() {
+  if (top_controls_animation_.IsInitialized())
+    return std::make_pair(top_controls_animation_.min_value(),
+                          top_controls_animation_.max_value());
+
+  return std::make_pair(0.f, 1.f);
+}
+
+std::pair<float, float>
+BrowserControlsOffsetManager::BottomControlsShownRatioRange() {
+  if (bottom_controls_animation_.IsInitialized())
+    return std::make_pair(bottom_controls_animation_.min_value(),
+                          bottom_controls_animation_.max_value());
+
+  return std::make_pair(0.f, 1.f);
+}
+
 void BrowserControlsOffsetManager::UpdateBrowserControlsState(
     BrowserControlsState constraints,
     BrowserControlsState current,
@@ -145,13 +166,13 @@
     return;
   }
 
-  if (animate) {
+  ResetAnimations();
+
+  if (animate)
     SetupAnimation(direction);
-  } else {
-    ResetAnimations();
+  else
     client_->SetCurrentBrowserControlsShownRatio(final_top_shown_ratio,
                                                  final_bottom_shown_ratio);
-  }
 }
 
 BrowserControlsState BrowserControlsOffsetManager::PullConstraintForMainThread(
@@ -164,9 +185,122 @@
 
 void BrowserControlsOffsetManager::OnBrowserControlsParamsChanged(
     bool animate_changes) {
-  // TODO(sinansahin): We should decide how to animate the controls at this
-  // point. If no animation is needed, we will need to snap to the final ratio,
-  // e.g. old min-height to 0.
+  if (old_browser_controls_params_.top_controls_height == TopControlsHeight() &&
+      old_browser_controls_params_.top_controls_min_height ==
+          TopControlsMinHeight() &&
+      old_browser_controls_params_.bottom_controls_height ==
+          BottomControlsHeight() &&
+      old_browser_controls_params_.bottom_controls_min_height ==
+          BottomControlsMinHeight()) {
+    return;
+  }
+
+  float old_top_height = old_browser_controls_params_.top_controls_height;
+  float new_top_ratio =
+      TopControlsHeight()
+          ? TopControlsShownRatio() * old_top_height / TopControlsHeight()
+          : 0.f;
+
+  float old_bottom_height = old_browser_controls_params_.bottom_controls_height;
+  float new_bottom_ratio = BottomControlsHeight()
+                               ? BottomControlsShownRatio() *
+                                     old_bottom_height / BottomControlsHeight()
+                               : 0.f;
+
+  if (!animate_changes) {
+    // If the min-heights changed when the controls were at the min-height, the
+    // shown ratios need to be snapped to the new min-shown-ratio to keep the
+    // controls at the min height. If the controls were fully shown, we want to
+    // keep them fully shown even after the heights changed. For any other
+    // cases, we should update the shown ratio so the visible height remains the
+    // same.
+    if (TopControlsShownRatio() == OldTopControlsMinShownRatio())
+      new_top_ratio = TopControlsMinShownRatio();
+    else if (TopControlsShownRatio() == 1.f)
+      new_top_ratio = 1.f;
+
+    if (BottomControlsShownRatio() == OldBottomControlsMinShownRatio())
+      new_bottom_ratio = BottomControlsMinShownRatio();
+    else if (BottomControlsShownRatio() == 1.f)
+      new_bottom_ratio = 1.f;
+  }
+
+  // Browser controls height change animations
+  // If the browser controls heights (and/or min-heights) changed and need to be
+  // animated, the setup is done here. All the animations done in this class
+  // involve changing the shown ratios smoothly.
+  //
+  // There are several cases to handle:
+  // 1- The controls shown ratio was at the minimum ratio
+  //    - If the min-height changed, we will run an animation from
+  //      old-min-height / new-total-height to new-min-height / new-total-height
+  //    - If the min-height didn't change, we should update the shown ratio to
+  //      min-height / new-total-height so that the controls keep the same
+  //      visible height and don't jump. No animation needed in this case.
+  // 2- The controls shown ratio was at the highest ratio (should be 1 here)
+  //    - If the total height changed, we will run an animation from
+  //      old-total-height / new-total-height to 1.
+  //    - If the total height didn't change, we don't need to do anything.
+  // 3- The controls shown ratio is between the minimum and the maximum. This
+  //    would be the case if there is a show/hide animation running or there is
+  //    a scroll event and the controls are half-shown. In this case, we won't
+  //    run an animation--but update the shown ratio so the visible height
+  //    remains the same (See updated_{top,bottom}_ratio above).
+  //
+  // When this method is called as a result of a height change,
+  // TopControlsHeight(), TopControlsMinHeight(), BottomControlsHeight(), and
+  // BottomControlsMinHeight() will already be returning the new values.
+  // However, the shown ratios aren't updated.
+
+  bool top_controls_need_animation = animate_changes;
+  bool bottom_controls_need_animation = animate_changes;
+
+  float top_target_ratio;
+  // If the top controls height changed when they were fully shown.
+  if (TopControlsShownRatio() == 1.f && TopControlsHeight() != old_top_height) {
+    top_target_ratio = 1.f;  // i.e. new_height / new_height
+
+    // If the top controls min-height changed when they were at the minimum
+    // shown ratio. For example, the min height changed from 0 to a positive
+    // value while the top controls were completely hidden.
+  } else if (TopControlsShownRatio() == OldTopControlsMinShownRatio() &&
+             TopControlsMinHeight() !=
+                 old_browser_controls_params_.top_controls_min_height) {
+    top_target_ratio = TopControlsMinShownRatio();
+  } else {
+    top_controls_need_animation = false;
+  }
+
+  float bottom_target_ratio;
+  // If the bottom controls height changed when they were fully shown.
+  if (BottomControlsShownRatio() == 1.f &&
+      BottomControlsHeight() != old_bottom_height) {
+    bottom_target_ratio = 1.f;  // i.e. new_height / new_height
+
+    // If the bottom controls min-height changed when they were at the minimum
+    // shown ratio.
+  } else if (BottomControlsShownRatio() == OldBottomControlsMinShownRatio() &&
+             BottomControlsMinHeight() !=
+                 old_browser_controls_params_.bottom_controls_min_height) {
+    bottom_target_ratio = BottomControlsMinShownRatio();
+  } else {
+    bottom_controls_need_animation = false;
+  }
+
+  if (top_controls_need_animation)
+    InitAnimationForHeightChange(&top_controls_animation_, new_top_ratio,
+                                 top_target_ratio);
+
+  if (bottom_controls_need_animation)
+    InitAnimationForHeightChange(&bottom_controls_animation_, new_bottom_ratio,
+                                 bottom_target_ratio);
+
+  // We won't run any animations if the controls are in an in-between state.
+  // Examples: a show/hide animation is running, shown ratio is some value
+  // between min-shown-ratio and 1 because of a scroll event.
+
+  UpdateOldBrowserControlsParams();
+  client_->SetCurrentBrowserControlsShownRatio(new_top_ratio, new_bottom_ratio);
 }
 
 void BrowserControlsOffsetManager::ScrollBegin() {
@@ -265,23 +399,20 @@
   ScrollBegin();
 }
 
-void BrowserControlsOffsetManager::MainThreadHasStoppedFlinging() {
-  StartAnimationIfNecessary();
-}
-
 gfx::Vector2dF BrowserControlsOffsetManager::Animate(
     base::TimeTicks monotonic_time) {
   if (!HasAnimation() || !client_->HaveRootScrollNode())
     return gfx::Vector2dF();
 
   float old_offset = ContentTopOffset();
-  float new_top_ratio = top_controls_animation_.Tick(monotonic_time);
-  if (new_top_ratio < 0)
+  auto new_top_ratio = top_controls_animation_.Tick(monotonic_time);
+  if (!new_top_ratio.has_value())
     new_top_ratio = TopControlsShownRatio();
-  float new_bottom_ratio = bottom_controls_animation_.Tick(monotonic_time);
-  if (new_bottom_ratio < 0)
+  auto new_bottom_ratio = bottom_controls_animation_.Tick(monotonic_time);
+  if (!new_bottom_ratio.has_value())
     new_bottom_ratio = BottomControlsShownRatio();
-  client_->SetCurrentBrowserControlsShownRatio(new_top_ratio, new_bottom_ratio);
+  client_->SetCurrentBrowserControlsShownRatio(new_top_ratio.value(),
+                                               new_bottom_ratio.value());
 
   gfx::Vector2dF scroll_delta(0.f, ContentTopOffset() - old_offset);
   return scroll_delta;
@@ -293,8 +424,16 @@
 }
 
 void BrowserControlsOffsetManager::ResetAnimations() {
-  top_controls_animation_.Reset();
-  bottom_controls_animation_.Reset();
+  // If the animation doesn't need to jump to the end, Animation::Reset() will
+  // return |base::nullopt|.
+  auto top_ratio = top_controls_animation_.Reset();
+  auto bottom_ratio = bottom_controls_animation_.Reset();
+
+  if (top_ratio.has_value() || bottom_ratio.has_value())
+    client_->SetCurrentBrowserControlsShownRatio(
+        top_ratio.has_value() ? top_ratio.value() : TopControlsShownRatio(),
+        bottom_ratio.has_value() ? bottom_ratio.value()
+                                 : BottomControlsShownRatio());
 }
 
 void BrowserControlsOffsetManager::SetupAnimation(
@@ -315,21 +454,22 @@
     return;
   }
 
-  top_controls_animation_.SetBounds(TopControlsMinShownRatio(), 1.f);
-  bottom_controls_animation_.SetBounds(BottomControlsMinShownRatio(), 1.f);
-
   // Providing artificially larger/smaller stop ratios to make the animation
   // faster if the start ratio is closer to stop ratio.
   const float max_stop_ratio = direction == SHOWING_CONTROLS ? 1 : -1;
   float top_start_ratio = TopControlsShownRatio();
   float top_stop_ratio = top_start_ratio + max_stop_ratio;
-  top_controls_animation_.Initialize(direction, top_start_ratio,
-                                     top_stop_ratio);
+  top_controls_animation_.Initialize(direction, top_start_ratio, top_stop_ratio,
+                                     kShowHideMaxDurationMs,
+                                     /*jump_to_end_on_reset=*/false);
+  top_controls_animation_.SetBounds(TopControlsMinShownRatio(), 1.f);
 
   float bottom_start_ratio = BottomControlsShownRatio();
   float bottom_stop_ratio = bottom_start_ratio + max_stop_ratio;
-  bottom_controls_animation_.Initialize(direction, bottom_start_ratio,
-                                        bottom_stop_ratio);
+  bottom_controls_animation_.Initialize(
+      direction, bottom_start_ratio, bottom_stop_ratio, kShowHideMaxDurationMs,
+      /*jump_to_end_on_reset=*/false);
+  bottom_controls_animation_.SetBounds(BottomControlsMinShownRatio(), 1.f);
 
   client_->DidChangeBrowserControlsPosition();
 }
@@ -365,27 +505,68 @@
   baseline_bottom_content_offset_ = ContentBottomOffset();
 }
 
+void BrowserControlsOffsetManager::InitAnimationForHeightChange(
+    Animation* animation,
+    float start_ratio,
+    float stop_ratio) {
+  AnimationDirection direction =
+      start_ratio < stop_ratio ? SHOWING_CONTROLS : HIDING_CONTROLS;
+  animation->Initialize(direction, start_ratio, stop_ratio,
+                        kHeightChangeDurationMs, /*jump_to_end_on_reset=*/true);
+}
+
+float BrowserControlsOffsetManager::OldTopControlsMinShownRatio() {
+  return old_browser_controls_params_.top_controls_height
+             ? old_browser_controls_params_.top_controls_min_height /
+                   old_browser_controls_params_.top_controls_height
+             : 0.f;
+}
+
+float BrowserControlsOffsetManager::OldBottomControlsMinShownRatio() {
+  return old_browser_controls_params_.bottom_controls_height
+             ? old_browser_controls_params_.bottom_controls_min_height /
+                   old_browser_controls_params_.bottom_controls_height
+             : 0.f;
+}
+
+void BrowserControlsOffsetManager::UpdateOldBrowserControlsParams() {
+  // No need to update the other two bool members as they aren't useful for this
+  // class.
+  old_browser_controls_params_.top_controls_height = TopControlsHeight();
+  old_browser_controls_params_.top_controls_min_height = TopControlsMinHeight();
+  old_browser_controls_params_.bottom_controls_height = BottomControlsHeight();
+  old_browser_controls_params_.bottom_controls_min_height =
+      BottomControlsMinHeight();
+}
+
 // class Animation
 
+BrowserControlsOffsetManager::Animation::Animation() {}
+
 void BrowserControlsOffsetManager::Animation::Initialize(
     AnimationDirection direction,
     float start_value,
-    float stop_value) {
+    float stop_value,
+    int64_t duration,
+    bool jump_to_end_on_reset) {
   direction_ = direction;
   start_value_ = start_value;
   stop_value_ = stop_value;
+  duration_ = base::TimeDelta::FromMilliseconds(duration);
   initialized_ = true;
+  jump_to_end_on_reset_ = jump_to_end_on_reset;
+  SetBounds(std::min(start_value_, stop_value_),
+            std::max(start_value_, stop_value_));
 }
 
-float BrowserControlsOffsetManager::Animation::Tick(
+base::Optional<float> BrowserControlsOffsetManager::Animation::Tick(
     base::TimeTicks monotonic_time) {
   if (!IsInitialized())
-    return -1;
+    return base::nullopt;
 
   if (!started_) {
     start_time_ = monotonic_time;
-    stop_time_ =
-        start_time_ + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs);
+    stop_time_ = start_time_ + duration_;
     started_ = true;
   }
 
@@ -393,10 +574,11 @@
       monotonic_time, start_time_, start_value_, stop_time_, stop_value_);
 
   if (IsComplete(value)) {
-    value = stop_value_;
+    value = base::ClampToRange(stop_value_, min_value_, max_value_);
     Reset();
   }
-  return base::ClampToRange(value, min_value_, max_value_);
+
+  return value;
 }
 
 void BrowserControlsOffsetManager::Animation::SetBounds(float min, float max) {
@@ -404,7 +586,11 @@
   max_value_ = max;
 }
 
-void BrowserControlsOffsetManager::Animation::Reset() {
+base::Optional<float> BrowserControlsOffsetManager::Animation::Reset() {
+  auto ret = jump_to_end_on_reset_ ? base::make_optional(base::ClampToRange(
+                                         stop_value_, min_value_, max_value_))
+                                   : base::nullopt;
+
   started_ = false;
   initialized_ = false;
   start_time_ = base::TimeTicks();
@@ -412,6 +598,12 @@
   stop_time_ = base::TimeTicks();
   stop_value_ = 0.f;
   direction_ = NO_ANIMATION;
+  duration_ = base::TimeDelta();
+  min_value_ = 0.f;
+  max_value_ = 1.f;
+  jump_to_end_on_reset_ = false;
+
+  return ret;
 }
 
 bool BrowserControlsOffsetManager::Animation::IsComplete(float value) {
diff --git a/cc/input/browser_controls_offset_manager.h b/cc/input/browser_controls_offset_manager.h
index 7e06c1e2..2d09cde 100644
--- a/cc/input/browser_controls_offset_manager.h
+++ b/cc/input/browser_controls_offset_manager.h
@@ -10,6 +10,7 @@
 #include "base/time/time.h"
 #include "cc/input/browser_controls_state.h"
 #include "cc/layers/layer_impl.h"
+#include "cc/trees/browser_controls_params.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
@@ -55,6 +56,13 @@
   // The minimum shown ratio bottom controls can have.
   float BottomControlsMinShownRatio() const;
 
+  // Valid shown ratio range for the top controls. The values will be (0, 1) if
+  // there is no animation running.
+  std::pair<float, float> TopControlsShownRatioRange();
+  // Valid shown ratio range for the bottom controls. The values will be (0, 1)
+  // if there is no animation running.
+  std::pair<float, float> BottomControlsShownRatioRange();
+
   bool HasAnimation();
 
   void UpdateBrowserControlsState(BrowserControlsState constraints,
@@ -75,8 +83,6 @@
   void PinchBegin();
   void PinchEnd();
 
-  void MainThreadHasStoppedFlinging();
-
   gfx::Vector2dF Animate(base::TimeTicks monotonic_time);
 
  protected:
@@ -85,10 +91,18 @@
                                float controls_hide_threshold);
 
  private:
+  class Animation;
+
   void ResetAnimations();
   void SetupAnimation(AnimationDirection direction);
   void StartAnimationIfNecessary();
   void ResetBaseline();
+  float OldTopControlsMinShownRatio();
+  float OldBottomControlsMinShownRatio();
+  void UpdateOldBrowserControlsParams();
+  void InitAnimationForHeightChange(Animation* animation,
+                                    float start_ratio,
+                                    float stop_ratio);
 
   // The client manages the lifecycle of this.
   BrowserControlsOffsetManagerClient* client_;
@@ -116,10 +130,14 @@
   // the changes to Blink.
   bool constraint_changed_since_commit_;
 
+  // The old browser controls params that are used to figure out how to animate
+  // the height and min-height changes.
+  BrowserControlsParams old_browser_controls_params_;
+
   // Class that holds and manages the state of the controls animations.
   class Animation {
    public:
-    Animation() = default;
+    Animation();
 
     // Whether the animation is initialized with a direction and start and stop
     // values.
@@ -127,13 +145,22 @@
     bool Direction() { return direction_; }
     void Initialize(AnimationDirection direction,
                     float start_value,
-                    float stop_value);
+                    float stop_value,
+                    int64_t duration,
+                    bool jump_to_end_on_reset);
     // Returns the animated value for the given monotonic time tick if the
-    // animation is initialized. Otherwise, returns -1.
-    float Tick(base::TimeTicks monotonic_time);
+    // animation is initialized. Otherwise, returns |base::nullopt|.
+    base::Optional<float> Tick(base::TimeTicks monotonic_time);
     // Set the minimum and maximum values the animation can have.
     void SetBounds(float min, float max);
-    void Reset();
+    // Reset the properties. If |skip_to_end_on_reset_| is false, this function
+    // will return |base::nullopt|. Otherwise, it will return the end value
+    // (clamped to min-max).
+    base::Optional<float> Reset();
+
+    // Return the bounds.
+    float min_value() { return min_value_; }
+    float max_value() { return max_value_; }
 
    private:
     bool IsComplete(float value);
@@ -147,6 +174,8 @@
     // Monotonic start and stop times.
     base::TimeTicks start_time_;
     base::TimeTicks stop_time_;
+    // Animation duration.
+    base::TimeDelta duration_;
     // Start and stop values.
     float start_value_ = 0.f;
     float stop_value_ = 0.f;
@@ -154,6 +183,10 @@
     // animation is complete.
     float min_value_ = 0.f;
     float max_value_ = 1.f;
+    // Whether to fast-forward to end when reset. It is still BCOM's
+    // responsibility to actually set the shown ratios using the value returned
+    // by ::Reset().
+    bool jump_to_end_on_reset_ = false;
   };
 
   Animation top_controls_animation_;
diff --git a/cc/input/browser_controls_offset_manager_unittest.cc b/cc/input/browser_controls_offset_manager_unittest.cc
index d838c4a0..13fd4a11 100644
--- a/cc/input/browser_controls_offset_manager_unittest.cc
+++ b/cc/input/browser_controls_offset_manager_unittest.cc
@@ -81,7 +81,6 @@
     ASSERT_FALSE(*ratio == std::numeric_limits<float>::infinity());
     ASSERT_FALSE(*ratio == -std::numeric_limits<float>::infinity());
     *ratio = std::max(*ratio, 0.f);
-    *ratio = std::min(*ratio, 1.f);
   }
 
   float CurrentBottomControlsShownRatio() const override {
@@ -107,6 +106,9 @@
 
   void SetBrowserControlsParams(BrowserControlsParams params) {
     browser_controls_params_ = params;
+
+    manager()->OnBrowserControlsParamsChanged(
+        params.animate_browser_controls_height_changes);
   }
 
  private:
@@ -170,6 +172,55 @@
   manager->ScrollEnd();
 }
 
+TEST(BrowserControlsOffsetManagerTest,
+     EnsureScrollThresholdAppliedWithMinHeight) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // First, set the min-height.
+  client.SetBrowserControlsParams({100.f, 20.f, 0.f, 0.f, false, false});
+
+  manager->ScrollBegin();
+
+  // Scroll down to hide the controls.
+  manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
+  EXPECT_FLOAT_EQ(-30.f, manager->ControlsTopOffset());
+
+  manager->ScrollBy(gfx::Vector2dF(0.f, 30.f));
+  EXPECT_FLOAT_EQ(-60.f, manager->ControlsTopOffset());
+
+  // Controls should stop scrolling when we hit the min-height.
+  manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
+  EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+
+  // Scroll back up a bit and ensure the controls don't move until we cross
+  // the threshold.
+  manager->ScrollBy(gfx::Vector2dF(0.f, -20.f));
+  EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+
+  manager->ScrollBy(gfx::Vector2dF(0.f, -60.f));
+  EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+
+  // After hitting the threshold, further scrolling up should result in the top
+  // controls starting to move.
+  manager->ScrollBy(gfx::Vector2dF(0.f, -10.f));
+  EXPECT_FLOAT_EQ(-70.f, manager->ControlsTopOffset());
+
+  manager->ScrollBy(gfx::Vector2dF(0.f, -50.f));
+  EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
+
+  // Reset the scroll threshold by going further up the page than the initial
+  // threshold.
+  manager->ScrollBy(gfx::Vector2dF(0.f, -100.f));
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+
+  // See that scrolling down the page now will result in the controls hiding.
+  manager->ScrollBy(gfx::Vector2dF(0.f, 20.f));
+  EXPECT_FLOAT_EQ(-20.f, manager->ControlsTopOffset());
+
+  manager->ScrollEnd();
+}
+
 TEST(BrowserControlsOffsetManagerTest, PartialShownHideAnimation) {
   MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
   BrowserControlsOffsetManager* manager = client.manager();
@@ -538,6 +589,209 @@
   EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
 }
 
+TEST(BrowserControlsOffsetManagerTest, HeightIncreaseWhenFullyShownAnimation) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Set the new height with animation.
+  client.SetBrowserControlsParams({150, 0, 0, 0, true, false});
+  EXPECT_TRUE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(150.f, manager->TopControlsHeight());
+  // Ratio should've been updated to avoid jumping to the new height.
+  EXPECT_FLOAT_EQ(100.f / 150.f, manager->TopControlsShownRatio());
+
+  base::TimeTicks time = base::TimeTicks::Now();
+
+  // First animate will establish the animaion.
+  float previous = manager->TopControlsShownRatio();
+  manager->Animate(time);
+  EXPECT_EQ(manager->TopControlsShownRatio(), previous);
+
+  while (manager->HasAnimation()) {
+    previous = manager->TopControlsShownRatio();
+    time = base::TimeDelta::FromMicroseconds(100) + time;
+    manager->Animate(time);
+    EXPECT_GT(manager->TopControlsShownRatio(), previous);
+  }
+  EXPECT_FALSE(manager->HasAnimation());
+  // Controls should be fully shown when the animation ends.
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(150.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest, HeightDecreaseWhenFullyShownAnimation) {
+  MockBrowserControlsOffsetManagerClient client(150.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Set the new height with animation.
+  client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
+  EXPECT_TRUE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
+  // Ratio should've been updated to avoid jumping to the new height.
+  // The ratio will be > 1 here.
+  EXPECT_FLOAT_EQ(150.f / 100.f, manager->TopControlsShownRatio());
+
+  base::TimeTicks time = base::TimeTicks::Now();
+
+  // First animate will establish the animaion.
+  float previous = manager->TopControlsShownRatio();
+  manager->Animate(time);
+  EXPECT_EQ(manager->TopControlsShownRatio(), previous);
+
+  while (manager->HasAnimation()) {
+    previous = manager->TopControlsShownRatio();
+    time = base::TimeDelta::FromMicroseconds(100) + time;
+    manager->Animate(time);
+    EXPECT_LT(manager->TopControlsShownRatio(), previous);
+  }
+  EXPECT_FALSE(manager->HasAnimation());
+  // Controls should be fully shown when the animation ends.
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest, MinHeightIncreaseWhenHiddenAnimation) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Scroll to hide.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+
+  // Set the new min-height with animation.
+  client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
+  EXPECT_TRUE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+
+  base::TimeTicks time = base::TimeTicks::Now();
+
+  // First animate will establish the animaion.
+  float previous = manager->TopControlsShownRatio();
+  manager->Animate(time);
+  EXPECT_EQ(manager->TopControlsShownRatio(), previous);
+
+  while (manager->HasAnimation()) {
+    previous = manager->TopControlsShownRatio();
+    time = base::TimeDelta::FromMicroseconds(100) + time;
+    manager->Animate(time);
+    EXPECT_GT(manager->TopControlsShownRatio(), previous);
+  }
+  EXPECT_FALSE(manager->HasAnimation());
+  // Controls should be at the new min-height when the animation ends.
+  EXPECT_FLOAT_EQ(20.f / 100.f, manager->TopControlsShownRatio());
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest,
+     MinHeightSetToZeroWhenAtMinHeightAnimation) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Set the min-height.
+  client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
+
+  // Scroll to min-height.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 80.f));
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+
+  // Set the new min-height with animation.
+  client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
+  EXPECT_TRUE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeight());
+  // The controls should still be at the min-height.
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+
+  base::TimeTicks time = base::TimeTicks::Now();
+
+  // First animate will establish the animaion.
+  float previous = manager->TopControlsShownRatio();
+  manager->Animate(time);
+  EXPECT_EQ(manager->TopControlsShownRatio(), previous);
+
+  while (manager->HasAnimation()) {
+    previous = manager->TopControlsShownRatio();
+    time = base::TimeDelta::FromMicroseconds(100) + time;
+    manager->Animate(time);
+    EXPECT_LT(manager->TopControlsShownRatio(), previous);
+  }
+  EXPECT_FALSE(manager->HasAnimation());
+  // Controls should be hidden when the animation ends.
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsShownRatio());
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest, EnsureNoAnimationCases) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // No animation should run if only the min-height changes when the controls
+  // are fully shown.
+  client.SetBrowserControlsParams({100, 20, 0, 0, true, false});
+  EXPECT_FALSE(manager->HasAnimation());
+
+  // Scroll to min-height.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 80.f));
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+
+  // No animation should run if only the height changes when the controls
+  // are at min-height.
+  client.SetBrowserControlsParams({150, 20, 0, 0, true, false});
+  EXPECT_FALSE(manager->HasAnimation());
+
+  // Set the min-height to 0 without animation.
+  client.SetBrowserControlsParams({150, 0, 0, 0, false, false});
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+
+  // No animation should run if only the height changes when the controls are
+  // fully hidden.
+  client.SetBrowserControlsParams({100, 0, 0, 0, true, false});
+  EXPECT_FALSE(manager->HasAnimation());
+}
+
+TEST(BrowserControlsOffsetManagerTest,
+     HeightChangeAnimationJumpsToEndOnScroll) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  EXPECT_FLOAT_EQ(100.f, manager->ContentTopOffset());
+
+  // Change the params to start an animation.
+  client.SetBrowserControlsParams({150, 30, 0, 0, true, false});
+  EXPECT_TRUE(manager->HasAnimation());
+
+  base::TimeTicks time = base::TimeTicks::Now();
+  // First animate will establish the animation.
+  float previous = manager->TopControlsShownRatio();
+  manager->Animate(time);
+  // Forward a little bit.
+  time = base::TimeDelta::FromMicroseconds(100) + time;
+  manager->Animate(time);
+
+  // Animation should be in progress.
+  EXPECT_GT(manager->TopControlsShownRatio(), previous);
+
+  manager->ScrollBegin();
+  // Scroll should cause the animation to jump to the end.
+  EXPECT_FLOAT_EQ(1.f, manager->TopControlsShownRatio());
+  EXPECT_FLOAT_EQ(150.f, manager->ContentTopOffset());
+  EXPECT_FALSE(manager->HasAnimation());
+  // Then, the scroll will move the controls as it would normally.
+  manager->ScrollBy(gfx::Vector2dF(0.f, 60.f));
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(90.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+}
+
 TEST(BrowserControlsOffsetManagerTest,
      HeightChangeMaintainsFullyVisibleControls) {
   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
@@ -578,6 +832,103 @@
   EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
 }
 
+TEST(BrowserControlsOffsetManagerTest,
+     HeightChangeWithAnimateFalseDoesNotTriggerAnimation) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  client.SetBrowserControlsParams({150, 0, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(150.f, manager->TopControlsHeight());
+  EXPECT_FLOAT_EQ(0, manager->ControlsTopOffset());
+
+  client.SetBrowserControlsParams({50, 0, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(50.f, manager->TopControlsHeight());
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest,
+     MinHeightChangeWithAnimateFalseSnapsToNewMinHeight) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  EXPECT_FLOAT_EQ(0.f, manager->ControlsTopOffset());
+
+  // Scroll to hide the controls.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
+  EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+
+  // Change the min-height from 0 to 20.
+  client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
+  // Top controls should snap to the new min-height.
+  EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+
+  // Change the min-height from 20 to 0.
+  client.SetBrowserControlsParams({100, 0, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(0.f, manager->TopControlsMinHeight());
+  // Top controls should snap to the new min-height, 0.
+  EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(0.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest, ControlsStayAtMinHeightOnHeightChange) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Set the min-height to 20.
+  client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
+
+  // Scroll the controls to min-height.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 100.f));
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+  manager->ScrollEnd();
+
+  // Change the height from 100 to 120.
+  client.SetBrowserControlsParams({120, 20, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(120.f, manager->TopControlsHeight());
+  EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
+  // Top controls should stay at the same visible height.
+  EXPECT_FLOAT_EQ(-100.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+
+  // Change the height from 120 back to 100.
+  client.SetBrowserControlsParams({100, 20, 0, 0, false, false});
+  EXPECT_FALSE(manager->HasAnimation());
+  EXPECT_FLOAT_EQ(100.f, manager->TopControlsHeight());
+  EXPECT_FLOAT_EQ(20.f, manager->TopControlsMinHeight());
+  // Top controls should still stay at the same visible height.
+  EXPECT_FLOAT_EQ(-80.f, manager->ControlsTopOffset());
+  EXPECT_FLOAT_EQ(20.f, manager->ContentTopOffset());
+}
+
+TEST(BrowserControlsOffsetManagerTest, ControlsAdjustToNewHeight) {
+  MockBrowserControlsOffsetManagerClient client(100.f, 0.5f, 0.5f);
+  BrowserControlsOffsetManager* manager = client.manager();
+
+  // Scroll the controls a little.
+  manager->ScrollBegin();
+  manager->ScrollBy(gfx::Vector2dF(0.f, 40.f));
+  EXPECT_FLOAT_EQ(60.f, manager->ContentTopOffset());
+
+  // Change the height from 100 to 120.
+  client.SetBrowserControlsParams({120, 0, 0, 0, false, false});
+
+  // The shown ratios should be adjusted to keep the shown height same.
+  EXPECT_FLOAT_EQ(60.f, manager->ContentTopOffset());
+
+  manager->ScrollEnd();
+}
+
 TEST(BrowserControlsOffsetManagerTest, ScrollByWithZeroHeightControlsIsNoop) {
   MockBrowserControlsOffsetManagerClient client(0.f, 0.5f, 0.5f);
   BrowserControlsOffsetManager* manager = client.manager();
@@ -671,12 +1022,14 @@
   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
 
+  // Controls don't hide completely and stop at the min-height.
   manager->ScrollBegin();
   manager->ScrollBy(gfx::Vector2dF(0, 150));
   EXPECT_FLOAT_EQ(30.f / 100, client.CurrentTopControlsShownRatio());
   EXPECT_FLOAT_EQ(0.f, client.CurrentBottomControlsShownRatio());
   manager->ScrollEnd();
 
+  // Controls scroll immediately from the min-height point.
   manager->ScrollBegin();
   manager->ScrollBy(gfx::Vector2dF(0, -70));
   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
@@ -691,6 +1044,7 @@
   EXPECT_FLOAT_EQ(1.f, client.CurrentTopControlsShownRatio());
   EXPECT_FLOAT_EQ(1.f, client.CurrentBottomControlsShownRatio());
 
+  // Controls don't hide completely and stop at the min-height.
   manager->ScrollBegin();
   manager->ScrollBy(gfx::Vector2dF(0, 150));
   EXPECT_FLOAT_EQ(30.f / 100, client.CurrentTopControlsShownRatio());
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 287ce4a..aa6bb16 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -45,6 +45,7 @@
       ancestor_property_changed_(false),
       contributes_to_drawn_surface_(false),
       is_render_surface_list_member_(false),
+      can_use_cached_backdrop_filtered_result_(false),
       nearest_occlusion_immune_ancestor_(nullptr) {
   damage_tracker_ = DamageTracker::Create();
 }
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h
index 545c840..351ad59 100644
--- a/cc/layers/render_surface_impl.h
+++ b/cc/layers/render_surface_impl.h
@@ -122,6 +122,15 @@
     return is_render_surface_list_member_;
   }
 
+  void set_can_use_cached_backdrop_filtered_result(
+      bool can_use_cached_backdrop_filtered_result) {
+    can_use_cached_backdrop_filtered_result_ =
+        can_use_cached_backdrop_filtered_result;
+  }
+  bool can_use_cached_backdrop_filtered_result() const {
+    return can_use_cached_backdrop_filtered_result_;
+  }
+
   void CalculateContentRectFromAccumulatedContentRect(int max_texture_size);
   void SetContentRectToViewport();
   void SetContentRectForTesting(const gfx::Rect& rect);
@@ -249,6 +258,7 @@
 
   bool contributes_to_drawn_surface_ : 1;
   bool is_render_surface_list_member_ : 1;
+  bool can_use_cached_backdrop_filtered_result_ : 1;
 
   Occlusion occlusion_in_content_space_;
 
diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc
index e56e331..712d584 100644
--- a/cc/trees/damage_tracker.cc
+++ b/cc/trees/damage_tracker.cc
@@ -105,6 +105,11 @@
     render_surface->damage_tracker()->PrepareForUpdate();
   }
 
+  // Surfaces with backdrop blur filter that might be potentially optimized with
+  // caching, paired with each's surface rect in target space.
+  std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>
+      surfaces_with_backdrop_blur_filter;
+
   EffectTree& effect_tree = layer_tree_impl->property_trees()->effect_tree;
   int current_target_effect_id = EffectTree::kContentsRootNodeId;
   DCHECK(effect_tree.GetRenderSurface(current_target_effect_id));
@@ -125,10 +130,11 @@
         // in draw order.
         RenderSurfaceImpl* current_target =
             effect_tree.GetRenderSurface(current_target_effect_id);
-        current_target->damage_tracker()->ComputeSurfaceDamage(current_target);
+        current_target->damage_tracker()->ComputeSurfaceDamage(
+            current_target, surfaces_with_backdrop_blur_filter);
         RenderSurfaceImpl* parent_target = current_target->render_target();
         parent_target->damage_tracker()->AccumulateDamageFromRenderSurface(
-            current_target);
+            current_target, surfaces_with_backdrop_blur_filter);
         current_target_effect_id =
             effect_tree.Node(current_target_effect_id)->target_id;
       }
@@ -149,17 +155,23 @@
   RenderSurfaceImpl* current_target =
       effect_tree.GetRenderSurface(current_target_effect_id);
   while (true) {
-    current_target->damage_tracker()->ComputeSurfaceDamage(current_target);
+    current_target->damage_tracker()->ComputeSurfaceDamage(
+        current_target, surfaces_with_backdrop_blur_filter);
     if (current_target->EffectTreeIndex() == EffectTree::kContentsRootNodeId)
       break;
     RenderSurfaceImpl* next_target = current_target->render_target();
     next_target->damage_tracker()->AccumulateDamageFromRenderSurface(
-        current_target);
+        current_target, surfaces_with_backdrop_blur_filter);
     current_target = next_target;
   }
+
+  DCHECK(surfaces_with_backdrop_blur_filter.empty());
 }
 
-void DamageTracker::ComputeSurfaceDamage(RenderSurfaceImpl* render_surface) {
+void DamageTracker::ComputeSurfaceDamage(
+    RenderSurfaceImpl* render_surface,
+    std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>&
+        surfaces_with_backdrop_blur_filter) {
   // All damage from contributing layers and surfaces must already have been
   // added to damage_for_this_update_ through calls to AccumulateDamageFromLayer
   // and AccumulateDamageFromRenderSurface.
@@ -195,6 +207,23 @@
   // Damage accumulates until we are notified that we actually did draw on that
   // frame.
   current_damage_.Union(damage_for_this_update_);
+
+  if (!surfaces_with_backdrop_blur_filter.empty()) {
+    gfx::Rect leftover_damage_rect;
+    bool valid = damage_from_leftover_rects.GetAsRect(&leftover_damage_rect);
+    std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>::iterator it =
+        surfaces_with_backdrop_blur_filter.begin();
+    while (it != surfaces_with_backdrop_blur_filter.end()) {
+      RenderSurfaceImpl* surface = it->first;
+      if (surface->render_target() == render_surface) {
+        surface->set_can_use_cached_backdrop_filtered_result(
+            !it->second.Intersects(leftover_damage_rect) && valid);
+        it = surfaces_with_backdrop_blur_filter.erase(it);
+      } else {
+        ++it;
+      }
+    }
+  }
 }
 
 bool DamageTracker::GetDamageRectIfValid(gfx::Rect* rect) {
@@ -397,7 +426,9 @@
 }
 
 void DamageTracker::AccumulateDamageFromRenderSurface(
-    RenderSurfaceImpl* render_surface) {
+    RenderSurfaceImpl* render_surface,
+    std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>&
+        surfaces_with_backdrop_blur_filter) {
   // There are two ways a "descendant surface" can damage regions of the "target
   // surface":
   //   1. Property change:
@@ -457,6 +488,20 @@
                                       backdrop_filters);
   }
 
+  if (!surface_is_new &&
+      backdrop_filters.HasFilterOfType(FilterOperation::BLUR)) {
+    gfx::Rect damage_on_target;
+    bool valid = damage_for_this_update_.GetAsRect(&damage_on_target);
+    if (!valid || damage_on_target.Intersects(surface_rect_in_target_space)) {
+      render_surface->set_can_use_cached_backdrop_filtered_result(false);
+    } else {
+      surfaces_with_backdrop_blur_filter.push_back(
+          std::make_pair(render_surface, surface_rect_in_target_space));
+    }
+  } else {
+    render_surface->set_can_use_cached_backdrop_filtered_result(false);
+  }
+
   // True if any changes from contributing render surface.
   has_damage_from_contributing_content_ |= !damage_for_this_update_.IsEmpty();
 }
diff --git a/cc/trees/damage_tracker.h b/cc/trees/damage_tracker.h
index 2515a56..d5b83be 100644
--- a/cc/trees/damage_tracker.h
+++ b/cc/trees/damage_tracker.h
@@ -94,8 +94,14 @@
   // These helper functions are used only during UpdateDamageTracking().
   void PrepareForUpdate();
   void AccumulateDamageFromLayer(LayerImpl* layer);
-  void AccumulateDamageFromRenderSurface(RenderSurfaceImpl* render_surface);
-  void ComputeSurfaceDamage(RenderSurfaceImpl* render_surface);
+  void AccumulateDamageFromRenderSurface(
+      RenderSurfaceImpl* render_surface,
+      std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>&
+          surfaces_with_backdrop_blur_filter);
+  void ComputeSurfaceDamage(
+      RenderSurfaceImpl* render_surface,
+      std::vector<std::pair<RenderSurfaceImpl*, gfx::Rect>>&
+          surfaces_with_backdrop_blur_filter);
   void ExpandDamageInsideRectWithFilters(const gfx::Rect& pre_filter_rect,
                                          const FilterOperations& filters);
 
diff --git a/cc/trees/damage_tracker_unittest.cc b/cc/trees/damage_tracker_unittest.cc
index 42d0fe8..a1c7002 100644
--- a/cc/trees/damage_tracker_unittest.cc
+++ b/cc/trees/damage_tracker_unittest.cc
@@ -14,12 +14,15 @@
 #include "cc/test/fake_raster_source.h"
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/layer_tree_impl_test_base.h"
+#include "cc/test/property_tree_test_utils.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "cc/trees/transform_node.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/geometry/quad_f.h"
 #include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/vector2d_f.h"
 
 namespace cc {
 namespace {
@@ -140,6 +143,78 @@
     return root;
   }
 
+  LayerImpl* CreateTestTreeWithFourSurfaces() {
+    // This test tree has four render surfaces: one each for the root, child1_,
+    // grand_child3_ and grand_child4_. child1_ has four children of its own.
+    // Additionally, the root has a second child layer.
+    // child1_ has a screen space rect 270,270 36x38, from
+    //   - grand_child1_ 300,300, 6x8
+    //   - grand_child2_ 290,290, 6x8
+    //   - grand_child3_ 270,270, 6x8
+    //   - grand_child4_ 280,280, 15x16
+    // child2_ has a screen space rect 11,11 18x18
+
+    ClearLayersAndProperties();
+
+    LayerImpl* root = root_layer();
+    root->SetBounds(gfx::Size(500, 500));
+    root->layer_tree_impl()->SetDeviceViewportRect(gfx::Rect(root->bounds()));
+    root->SetDrawsContent(true);
+    SetupRootProperties(root);
+
+    child1_ = AddLayer<TestLayerImpl>();
+    grand_child1_ = AddLayer<TestLayerImpl>();
+    grand_child2_ = AddLayer<TestLayerImpl>();
+    grand_child3_ = AddLayer<TestLayerImpl>();
+    grand_child4_ = AddLayer<TestLayerImpl>();
+    child2_ = AddLayer<TestLayerImpl>();
+    SetElementIdsForTesting();
+
+    child1_->SetBounds(gfx::Size(30, 30));
+    // With a child that draws_content, opacity will cause the layer to create
+    // its own RenderSurface. This layer does not draw, but is intended to
+    // create its own RenderSurface.
+    child1_->SetDrawsContent(false);
+    CopyProperties(root, child1_);
+    CreateTransformNode(child1_).post_translation =
+        gfx::Vector2dF(100.f, 100.f);
+    CreateEffectNode(child1_).render_surface_reason =
+        RenderSurfaceReason::kTest;
+
+    grand_child1_->SetBounds(gfx::Size(6, 8));
+    grand_child1_->SetDrawsContent(true);
+    CopyProperties(child1_, grand_child1_);
+    grand_child1_->SetOffsetToTransformParent(gfx::Vector2dF(200.f, 200.f));
+
+    grand_child2_->SetBounds(gfx::Size(6, 8));
+    grand_child2_->SetDrawsContent(true);
+    CopyProperties(child1_, grand_child2_);
+    grand_child2_->SetOffsetToTransformParent(gfx::Vector2dF(190.f, 190.f));
+
+    grand_child3_->SetBounds(gfx::Size(6, 8));
+    grand_child3_->SetDrawsContent(true);
+    CopyProperties(child1_, grand_child3_);
+    CreateEffectNode(grand_child3_).render_surface_reason =
+        RenderSurfaceReason::kTest;
+    CreateTransformNode(grand_child3_).post_translation =
+        gfx::Vector2dF(170.f, 170.f);
+
+    grand_child4_->SetBounds(gfx::Size(15, 16));
+    grand_child4_->SetDrawsContent(true);
+    CopyProperties(child1_, grand_child4_);
+    CreateEffectNode(grand_child4_).render_surface_reason =
+        RenderSurfaceReason::kTest;
+    CreateTransformNode(grand_child4_).post_translation =
+        gfx::Vector2dF(180.f, 180.f);
+
+    child2_->SetBounds(gfx::Size(18, 18));
+    child2_->SetDrawsContent(true);
+    CopyProperties(root, child2_);
+    child2_->SetOffsetToTransformParent(gfx::Vector2dF(11.f, 11.f));
+
+    return root;
+  }
+
   LayerImpl* CreateAndSetUpTestTreeWithOneSurface(int number_of_children = 1) {
     LayerImpl* root = CreateTestTreeWithOneSurface(number_of_children);
 
@@ -160,6 +235,16 @@
     return root;
   }
 
+  LayerImpl* CreateAndSetUpTestTreeWithFourSurfaces() {
+    LayerImpl* root = CreateTestTreeWithFourSurfaces();
+
+    // Setup includes going past the first frame which always damages
+    // everything, so that we can actually perform specific tests.
+    EmulateDrawingOneFrame(root);
+
+    return root;
+  }
+
   void EmulateDrawingOneFrame(LayerImpl* root,
                               float device_scale_factor = 1.f) {
     // This emulates only steps that are relevant to testing the damage tracker:
@@ -182,7 +267,8 @@
     host_impl()->active_tree()->DetachLayersKeepingRootLayerForTesting();
     host_impl()->active_tree()->property_trees()->clear();
     child_layers_.clear();
-    child1_ = child2_ = grand_child1_ = grand_child2_ = nullptr;
+    child1_ = child2_ = grand_child1_ = grand_child2_ = grand_child3_ =
+        grand_child4_ = nullptr;
   }
 
   // Stores result of CreateTestTreeWithOneSurface().
@@ -193,6 +279,8 @@
   TestLayerImpl* child2_ = nullptr;
   TestLayerImpl* grand_child1_ = nullptr;
   TestLayerImpl* grand_child2_ = nullptr;
+  TestLayerImpl* grand_child3_ = nullptr;
+  TestLayerImpl* grand_child4_ = nullptr;
 };
 
 TEST_F(DamageTrackerTest, SanityCheckTestTreeWithOneSurface) {
@@ -2053,5 +2141,199 @@
                   ->has_damage_from_contributing_content());
 }
 
+TEST_F(DamageTrackerTest, CanUseCachedBackdropFilterResultTest) {
+  LayerImpl* root = CreateAndSetUpTestTreeWithFourSurfaces();
+
+  // child1_ has a screen space rect of 270,270 36x38, from
+  //   - grand_child1_ 300,300, 6x8
+  //   - grand_child2_ 290,290, 6x8
+  //   - grand_child3_ 270,270, 6x8
+  //   - grand_child4_ 280,280, 15x16
+  // child2_ has a screen space rect 11,11 18x18
+
+  ClearDamageForAllSurfaces(root);
+
+  // Add a backdrop blur filter onto child1_
+  FilterOperations filters;
+  filters.Append(FilterOperation::CreateBlurFilter(2.f));
+  SetBackdropFilter(child1_, filters);
+  child1_->NoteLayerPropertyChanged();
+  // can_use_cached_backdrop_filtered_result_ is false by default.
+  EXPECT_FALSE(
+      GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result());
+
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(
+      GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result());
+
+  // Let run for one update and there should be no damage left.
+  ClearDamageForAllSurfaces(root);
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(
+      GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result());
+
+  // CASE 1.1: Setting a non-intersecting update rect on the root
+  // doesn't invalidate child1_'s cached backdrop-filtered result.
+  // Damage rect at 0,0 20x20 (expanded to -6,-6 32x32) doesn't intersect
+  // 270,270 36x38.
+  ClearDamageForAllSurfaces(root);
+  root->UnionUpdateRect(gfx::Rect(0, 0, 20, 20));
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(
+      GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result());
+
+  // CASE 1.2: Setting an intersecting update rect on the root invalidates
+  // child1_'s cached backdrop-filtered result.
+  // Damage rect at 260,260 20x20 (expanded to 254,254 32x32) intersects 270,270
+  // 36x38.
+  ClearDamageForAllSurfaces(root);
+  root->UnionUpdateRect(gfx::Rect(260, 260, 20, 20));
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(
+      GetRenderSurface(child1_)->can_use_cached_backdrop_filtered_result());
+
+  // CASE 1.3: Damage on layers above the surface with the backdrop filter
+  // doesn't invalidate cached backdrop-filtered result. Move child2_ to overlap
+  // with child1_.
+  ClearDamageForAllSurfaces(root);
+  child2_->SetOffsetToTransformParent(gfx::Vector2dF(180.f, 180.f));
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child1_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 2: Adding or removing a backdrop filter would invalidate cached
+  // backdrop-filtered result of the corresponding render surfaces.
+  ClearDamageForAllSurfaces(root);
+  // Remove the backdrop filter on child1_
+  SetBackdropFilter(child1_, FilterOperations());
+  grand_child1_->NoteLayerPropertyChanged();
+  // Add a backdrop blur filtre to grand_child4_
+  SetBackdropFilter(grand_child4_, filters);
+  grand_child4_->NoteLayerPropertyChanged();
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(GetRenderSurface(grand_child4_)
+                   ->can_use_cached_backdrop_filtered_result());
+  EXPECT_FALSE(GetRenderSurface(grand_child1_)
+                   ->can_use_cached_backdrop_filtered_result());
+
+  // Let run for one update and there should be no damage left.
+  ClearDamageForAllSurfaces(root);
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child4_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 3.1: Adding a non-intersecting damage rect to a sibling layer under
+  // the render surface with the backdrop filter doesn't invalidate cached
+  // backdrop-filtered result. Damage rect on grand_child1_ at 302,302 1x1
+  // expanded by a 6-pixel spread (296,296 13x13)
+  // doesn't intersect 280,280 15x16.
+  ClearDamageForAllSurfaces(root);
+  grand_child1_->AddDamageRect(gfx::Rect(2, 2, 1.f, 1.f));
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child4_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 3.2: Adding an intersecting damage rect to a sibling layer under the
+  // render surface with the backdrop filter invalidates cached
+  // backdrop-filtered result. Damage rect on grand_child2_ at 290,290 1x1
+  // expanded by a 6-pixel spread (284,284 13x13)
+  // intersects 280,280 15x16.
+  ClearDamageForAllSurfaces(root);
+  grand_child2_->AddDamageRect(gfx::Rect(0, 0, 1.f, 1.f));
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(GetRenderSurface(grand_child4_)
+                   ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 4.1: Non-intersecting damage rect on a sibling surface under the
+  // render surface with the backdrop filter doesn't invalidate cached
+  // backdrop-filtered result.
+  ClearDamageForAllSurfaces(root);
+  grand_child3_->AddDamageRect(gfx::Rect(0, 0, 1.f, 1.f));
+  EmulateDrawingOneFrame(root);
+  gfx::Rect damage_rect;
+  EXPECT_TRUE(GetRenderSurface(grand_child3_)
+                  ->damage_tracker()
+                  ->GetDamageRectIfValid(&damage_rect));
+  EXPECT_EQ(gfx::Rect(170, 170, 1.f, 1.f), damage_rect);
+  // Damage rect at 170,170 1x1 (expanded to 164,164 13x13) in render target
+  // local space doesn't intersect 180,180 15x16.
+  EXPECT_TRUE(GetRenderSurface(grand_child4_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 4.2: Intersecting damage rect on a sibling surface under the render
+  // surface with the backdrop filter invalidates cached backdrop-filtered
+  // result.
+  ClearDamageForAllSurfaces(root);
+  grand_child3_->SetBounds(gfx::Size(11.f, 11.f));
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child3_)
+                  ->damage_tracker()
+                  ->GetDamageRectIfValid(&damage_rect));
+  EXPECT_EQ(gfx::Rect(170, 170, 11.f, 11.f), damage_rect);
+  // Damage rect at 170,170 11x11 (expanded to 164,164 23x23) in render target
+  // local space intersects 180,180 15x16
+  EXPECT_FALSE(GetRenderSurface(grand_child4_)
+                   ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 5.1: Removing a non-intersecting sibling layer under the render
+  // surface with the backdrop filter doesn't invalidate cached
+  // backdrop-filtered result. Removing grand_child1_ at 300,300 6x8 which
+  // doesn't intersect 280,280 15x16.
+  ClearDamageForAllSurfaces(root);
+  OwnedLayerImplList layers =
+      host_impl()->active_tree()->DetachLayersKeepingRootLayerForTesting();
+  ASSERT_EQ(7u, layers.size());
+  ASSERT_EQ(child1_, layers[1].get());
+  ASSERT_EQ(grand_child1_, layers[2].get());
+  ASSERT_EQ(grand_child2_, layers[3].get());
+  ASSERT_EQ(grand_child3_, layers[4].get());
+  ASSERT_EQ(grand_child4_, layers[5].get());
+  ASSERT_EQ(child2_, layers[6].get());
+  host_impl()->active_tree()->AddLayer(std::move(layers[1]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[3]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[4]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[5]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[6]));
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child4_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 5.2: Removing an intersecting sibling layer under the render surface
+  // with the backdrop filter invalidates cached backdrop-filtered result.
+  // Removing grand_child2_ at 290,290 6x8 which intersects 280,280 15x16.
+  ClearDamageForAllSurfaces(root);
+  layers = host_impl()->active_tree()->DetachLayersKeepingRootLayerForTesting();
+  ASSERT_EQ(6u, layers.size());
+  ASSERT_EQ(child1_, layers[1].get());
+  ASSERT_EQ(grand_child2_, layers[2].get());
+  ASSERT_EQ(grand_child3_, layers[3].get());
+  ASSERT_EQ(grand_child4_, layers[4].get());
+  ASSERT_EQ(child2_, layers[5].get());
+  host_impl()->active_tree()->AddLayer(std::move(layers[1]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[3]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[4]));
+  host_impl()->active_tree()->AddLayer(std::move(layers[5]));
+
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(GetRenderSurface(grand_child4_)
+                   ->can_use_cached_backdrop_filtered_result());
+
+  // Let run for one update and there should be no damage left.
+  ClearDamageForAllSurfaces(root);
+  EmulateDrawingOneFrame(root);
+  EXPECT_TRUE(GetRenderSurface(grand_child4_)
+                  ->can_use_cached_backdrop_filtered_result());
+
+  // CASE 6: Removing a intersecting sibling surface under the render
+  // surface with the backdrop filter invalidate cached backdrop-filtered
+  // result.
+  ClearDamageForAllSurfaces(root);
+  SetRenderSurfaceReason(grand_child3_, RenderSurfaceReason::kNone);
+  grand_child3_->SetDrawsContent(false);
+  EmulateDrawingOneFrame(root);
+  EXPECT_FALSE(GetRenderSurface(grand_child4_)
+                   ->can_use_cached_backdrop_filtered_result());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 8d53494..c878612 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1020,9 +1020,10 @@
   browser_controls_params_ = params;
   UpdateViewportContainerSizes();
 
-  if (IsActiveTree())
+  if (IsActiveTree()) {
     host_impl_->browser_controls_manager()->OnBrowserControlsParamsChanged(
         params.animate_browser_controls_height_changes);
+  }
 }
 
 void LayerTreeImpl::set_overscroll_behavior(
@@ -1032,14 +1033,28 @@
 
 bool LayerTreeImpl::ClampTopControlsShownRatio() {
   float ratio = top_controls_shown_ratio_->Current(true);
+  auto range = std::make_pair(0.f, 1.f);
+  if (IsActiveTree()) {
+    // BCOM might need to set ratios outside the [0, 1] range (e.g. animation
+    // running). So, use the values it provides instead of clamping to [0, 1].
+    range =
+        host_impl_->browser_controls_manager()->TopControlsShownRatioRange();
+  }
   return top_controls_shown_ratio_->SetCurrent(
-      base::ClampToRange(ratio, 0.f, 1.f));
+      base::ClampToRange(ratio, range.first, range.second));
 }
 
 bool LayerTreeImpl::ClampBottomControlsShownRatio() {
   float ratio = bottom_controls_shown_ratio_->Current(true);
+  auto range = std::make_pair(0.f, 1.f);
+  if (IsActiveTree()) {
+    // BCOM might need to set ratios outside the [0, 1] range (e.g. animation
+    // running). So, use the values it provides instead of clamping to [0, 1].
+    range =
+        host_impl_->browser_controls_manager()->BottomControlsShownRatioRange();
+  }
   return bottom_controls_shown_ratio_->SetCurrent(
-      base::ClampToRange(ratio, 0.f, 1.f));
+      base::ClampToRange(ratio, range.first, range.second));
 }
 
 bool LayerTreeImpl::SetCurrentBrowserControlsShownRatio(float top_ratio,
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 20231bef..c5cbee99 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -464,6 +464,7 @@
   if (enable_vr) {
     deps += [ ":chrome_vr_java_resources" ]
   }
+
   srcjar_deps += [ ":chrome_vr_android_java_enums_srcjar" ]
   if (enable_feed_in_chrome) {
     deps += [ ":chrome_feed_java_resources" ]
@@ -2157,10 +2158,9 @@
     ]
 
     # Include ArCore files directly instead of using bundles.
-    deps += [
-      "//chrome/browser/android/vr:ar_java",
-      "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
-    ]
+    deps +=
+        [ "//chrome/browser/android/vr:ar_java",
+          "//third_party/arcore-android-sdk-client:com_google_ar_core_java" ]
 
     _libarcore_dir = get_label_info(
                          "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 12c17b0..76ee757 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -318,6 +318,12 @@
 template("monochrome_public_common_apk_or_module_tmpl") {
   _is_bundle_module = defined(invoker.target_type) &&
                       invoker.target_type == "android_app_bundle_module"
+  if (_is_bundle_module) {
+    assert(
+        defined(invoker.is_base_module),
+        "_is_bundle_module is true but the invoker does not define is_base_module!")
+  }
+
   if (defined(invoker.enable_multidex)) {
     _enable_multidex = invoker.enable_multidex
   } else {
@@ -344,6 +350,32 @@
       "//components/crash/android:handler_java",
     ]
 
+    if (_is_bundle_module && invoker.is_base_module && enable_arcore) {
+      # AR DFM is disabled - bring in the ar_java target along with ARCore SDK
+      # and set the loadable_modules / secondary_abi_loadable_modules to what
+      # would be brought in by the module.
+      # This needs to happen for monochrome & trichrome builds of base module if ARCore is enabled.
+
+      _deps +=
+          [ "//chrome/browser/android/vr:ar_java",
+            "//third_party/arcore-android-sdk-client:com_google_ar_core_java" ]
+
+      _libarcore_dir = get_label_info(
+                           "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
+                           "target_out_dir") + "/com_google_ar_core_java/jni"
+
+      if (android_64bit_target_cpu) {
+        if (invoker.is_64_bit_browser) {
+          loadable_modules = [ "$_libarcore_dir/arm64-v8a/libarcore_sdk_c.so" ]
+        } else {
+          secondary_abi_loadable_modules =
+              [ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
+        }
+      } else {
+        loadable_modules = [ "$_libarcore_dir/armeabi-v7a/libarcore_sdk_c.so" ]
+      }
+    }
+
     if (is_monochrome) {
       product_config_java_packages = [
         "org.chromium.chrome.browser",
diff --git a/chrome/android/features/keyboard_accessory/DEPS b/chrome/android/features/keyboard_accessory/DEPS
index add6f73..2abf1df 100644
--- a/chrome/android/features/keyboard_accessory/DEPS
+++ b/chrome/android/features/keyboard_accessory/DEPS
@@ -2,6 +2,7 @@
   "+chrome/browser/ui/android/widget",
   "+chrome/browser/ui/messages/android/java",
   "+components/autofill/android/java/src/org/chromium/components/autofill",
+  "+components/embedder_support/android/java",
   "+components/feature_engagement/public",
   "-content/public/android",
   "+content/public/android/java/src/org/chromium/content_public",
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
index 8ac3c98..6247ccf 100644
--- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
+++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
@@ -40,7 +40,6 @@
 import android.graphics.drawable.Drawable;
 import android.view.Surface;
 import android.view.View;
-import android.view.ViewGroup;
 
 import androidx.annotation.Nullable;
 
@@ -78,6 +77,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.display.DisplayAndroid;
@@ -102,7 +102,7 @@
     private ChromeActivity mMockActivity;
     private WebContents mLastMockWebContents;
     @Mock
-    private ViewGroup mMockContentView;
+    private ContentView mMockContentView;
     @Mock
     private TabModelSelector mMockTabModelSelector;
     @Mock
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn
index ec196c5..ec02c9e 100644
--- a/chrome/android/features/vr/BUILD.gn
+++ b/chrome/android/features/vr/BUILD.gn
@@ -72,6 +72,7 @@
     "//chrome/browser/preferences:java",
     "//chrome/browser/util:java",
     "//components/browser_ui/modaldialog/android:java",
+    "//components/embedder_support/android:content_view_java",
     "//components/policy/android:policy_java",
     "//content/public/android:content_java",
     "//device/vr:java",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index bb3cf14..cf90b68 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -175,21 +175,6 @@
         <!-- ARCore APK integration -->
         <!-- This tag indicates that this application optionally uses ARCore. -->
         <meta-data android:name="com.google.ar.core" android:value="optional" />
-        <!-- This value must match value present in ARCore SDK's .aar -->
-        <!-- TODO(https://crbug.com/917406): modify build scripts to
-             automatically pull this value in - the problem exists because in
-             bundle mode, the ARCore SDK is packaged into AR module and
-             the module installation will not automatically bring in DFM's
-             manifest entries. -->
-        <meta-data android:name="com.google.ar.core.min_apk_version"
-            android:value="190531000"/>
-        <activity
-            android:name="com.google.ar.core.InstallActivity"
-            android:configChanges="keyboardHidden|orientation|screenSize"
-            android:excludeFromRecents="true"
-            android:exported="false"
-            android:launchMode="singleTop"
-            android:theme="@android:style/Theme.Material.Light.Dialog.Alert" />
         {% endif %}
 
         <!-- Cast support -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
index d8aaff1..9b85a28 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DeferredStartupHandler.java
@@ -7,14 +7,11 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.os.Looper;
-import android.os.SystemClock;
 
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.metrics.UmaUtils;
 
 import java.util.LinkedList;
 import java.util.Queue;
@@ -29,8 +26,6 @@
     }
 
     private boolean mDeferredStartupCompletedForApp;
-    private long mDeferredStartupDuration;
-    private long mMaxTaskDuration;
     private final Context mAppContext;
 
     private final Queue<Runnable> mDeferredTasks;
@@ -62,40 +57,19 @@
      * tasks.
      */
     public void queueDeferredTasksOnIdleHandler() {
-        mMaxTaskDuration = 0;
-        mDeferredStartupDuration = 0;
         Looper.myQueue().addIdleHandler(() -> {
             Runnable currentTask = mDeferredTasks.poll();
             if (currentTask == null) {
                 if (!mDeferredStartupCompletedForApp) {
                     mDeferredStartupCompletedForApp = true;
-                    recordDeferredStartupStats();
                 }
                 return false;
             }
-
-            long startTime = SystemClock.uptimeMillis();
             currentTask.run();
-            long timeTaken = SystemClock.uptimeMillis() - startTime;
-
-            mMaxTaskDuration = Math.max(mMaxTaskDuration, timeTaken);
-            mDeferredStartupDuration += timeTaken;
             return true;
         });
     }
 
-    private void recordDeferredStartupStats() {
-        RecordHistogram.recordLongTimesHistogram(
-                "UMA.Debug.EnableCrashUpload.DeferredStartUpDuration", mDeferredStartupDuration);
-        RecordHistogram.recordLongTimesHistogram(
-                "UMA.Debug.EnableCrashUpload.DeferredStartUpMaxTaskDuration", mMaxTaskDuration);
-        if (UmaUtils.hasComeToForeground()) {
-            RecordHistogram.recordLongTimesHistogram(
-                    "UMA.Debug.EnableCrashUpload.DeferredStartUpCompleteTime",
-                    SystemClock.uptimeMillis() - UmaUtils.getForegroundStartTicks());
-        }
-    }
-
     /**
      * Adds a single deferred task to the queue. The caller is responsible for calling
      * queueDeferredTasksOnIdleHandler after adding tasks.
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 0a2756f..f7208296 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
@@ -769,6 +769,7 @@
     public void onBottomControlsHeightChanged(
             int bottomControlsHeight, int bottomControlsMinHeight) {
         if (mTabVisible == null) return;
+        getWebContents().notifyBrowserControlsHeightChanged();
         Point viewportSize = getViewportSize();
         setSize(mTabVisible.getWebContents(), mTabVisible.getContentView(), viewportSize.x,
                 viewportSize.y);
@@ -776,9 +777,9 @@
     }
 
     @Override
-    public void onTopControlsHeightChanged(
-            int topControlsHeight, int topControlsMinHeight, boolean controlsResizeView) {
+    public void onTopControlsHeightChanged(int topControlsHeight, int topControlsMinHeight) {
         if (mTabVisible == null) return;
+        getWebContents().notifyBrowserControlsHeightChanged();
         Point viewportSize = getViewportSize();
         setSize(mTabVisible.getWebContents(), mTabVisible.getContentView(), viewportSize.x,
                 viewportSize.y);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
index 7e19c0a..e753eb6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -852,15 +852,6 @@
         // Nothing to do here yet.
     }
 
-    // TODO(crbug.com/1002519): This should be a temporary solution until the scene layer ownership
-    // is redone and the toolbar component owns its scene layer.
-    /**
-     * @return The {@link ToolbarSceneLayer}.
-     */
-    public ToolbarSceneLayer getToolbarSceneLayer() {
-        return mToolbarOverlay;
-    }
-
     /**
      * @return The {@link EdgeSwipeHandler} responsible for processing swipe events for the normal
      *         toolbar. By default this returns null.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
index 287e01f..a5df0de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
@@ -138,7 +138,7 @@
                     t.getBrightness(), t.showToolbar(), defaultThemeColor,
                     t.getToolbarBackgroundColor(), closeButtonColor, t.anonymizeToolbar(),
                     t.isTitleNeeded(), urlBarBackgroundId, t.getTextBoxBackgroundColor(),
-                    textBoxAlpha, t.getToolbarAlpha(), t.getToolbarYOffset() * dpToPx,
+                    textBoxAlpha, t.getToolbarAlpha(), fullscreenManager.getContentOffset(),
                     t.getSideBorderScale(), t.insetBorderVertical());
         }
         TabListSceneLayerJni.get().finishBuildingFrame(mNativePtr, TabListSceneLayer.this);
@@ -212,7 +212,7 @@
                 boolean showToolbar, int defaultThemeColor, int toolbarBackgroundColor,
                 int closeButtonColor, boolean anonymizeToolbar, boolean showTabTitle,
                 int toolbarTextBoxResource, int toolbarTextBoxBackgroundColor,
-                float toolbarTextBoxAlpha, float toolbarAlpha, float toolbarYOffset,
+                float toolbarTextBoxAlpha, float toolbarAlpha, float contentOffset,
                 float sideBorderScale, boolean insetVerticalBorder);
 
         void putBackgroundLayer(long nativeTabListSceneLayer, TabListSceneLayer caller,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java
index d5fa6a3e..de10a6f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ToolbarSceneLayer.java
@@ -47,9 +47,6 @@
     /** A LayoutRenderHost for accessing drawing information about the toolbar. */
     private LayoutRenderHost mRenderHost;
 
-    /** The static Y offset for the cases where there is a another cc layer above the toolbar. */
-    private int mStaticYOffset;
-
     /**
      * @param context An Android context to use.
      * @param provider A LayoutProvider for accessing the current layout.
@@ -63,14 +60,6 @@
     }
 
     /**
-     * Set a static Y offset for the toolbar.
-     * @param staticYOffset The Y offset in pixels.
-     */
-    public void setStaticYOffset(int staticYOffset) {
-        mStaticYOffset = staticYOffset;
-    }
-
-    /**
      * Update the toolbar and progress bar layers.
      *
      * @param browserControlsBackgroundColor The background color of the browser controls.
@@ -108,11 +97,15 @@
                         fullscreenManager.getTab(), browserControlsBackgroundColor);
 
         int textBoxResourceId = R.drawable.modern_location_bar;
+        // The content offset is passed to the toolbar layer so that it can position itself at the
+        // bottom of the space available for top controls. The main reason for using content offset
+        // instead of top controls offset is that top controls can have a greater height than that
+        // of the toolbar, e.g. when status indicator is visible, and the toolbar needs to be
+        // positioned at the bottom of the top controls regardless of the total height.
         ToolbarSceneLayerJni.get().updateToolbarLayer(mNativePtr, ToolbarSceneLayer.this,
                 resourceManager, R.id.control_container, browserControlsBackgroundColor,
                 textBoxResourceId, browserControlsUrlBarAlpha, textBoxColor,
-                fullscreenManager.getTopControlOffset() + mStaticYOffset, windowHeight, useTexture,
-                showShadow);
+                fullscreenManager.getContentOffset(), windowHeight, useTexture, showShadow);
 
         if (mProgressBarDrawingInfo == null) return;
         ToolbarSceneLayerJni.get().updateProgressBar(mNativePtr, ToolbarSceneLayer.this,
@@ -231,7 +224,7 @@
                 long nativeToolbarSceneLayer, ToolbarSceneLayer caller, SceneLayer contentTree);
         void updateToolbarLayer(long nativeToolbarSceneLayer, ToolbarSceneLayer caller,
                 ResourceManager resourceManager, int resourceId, int toolbarBackgroundColor,
-                int urlBarResourceId, float urlBarAlpha, int urlBarColor, float topOffset,
+                int urlBarResourceId, float urlBarAlpha, int urlBarColor, float contentOffset,
                 float viewHeight, boolean visible, boolean showShadow);
         void updateProgressBar(long nativeToolbarSceneLayer, ToolbarSceneLayer caller,
                 int progressBarX, int progressBarY, int progressBarWidth, int progressBarHeight,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindResultBar.java b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindResultBar.java
index 0048da6..a940a3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindResultBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindResultBar.java
@@ -22,9 +22,10 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.MathUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.base.LocalizationUtils;
+import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.interpolators.BakedBezierInterpolator;
 
 import java.util.ArrayList;
@@ -55,8 +56,8 @@
     private final int mMinGapBetweenStacks;
     private final int mStackedResultHeight;
 
-    private final Tab mTab;
     private FindInPageBridge mFindInPageBridge;
+    private final ContentView mContentView;
 
     int mRectsVersion = -1;
     private RectF[] mMatches = new RectF[0];
@@ -85,9 +86,12 @@
     /**
      * Creates an instance of a {@link FindResultBar}.
      * @param context The Context to create this {@link FindResultBar} under.
-     * @param tab The Tab containing the ContentView this {@link FindResultBar} will be drawn in.
+     * @param contentView The ContentView that holds the WebContents that is being searched. The
+     *         WebContents must have been attached to a view hierarchy and have a WindowAndroid.
+     * @param findInPageBridge Facilitator for user interactions.
      */
-    public FindResultBar(Context context, Tab tab, FindInPageBridge findInPageBridge) {
+    public FindResultBar(
+            Context context, ContentView contentView, FindInPageBridge findInPageBridge) {
         super(context);
 
         Resources res = context.getResources();
@@ -121,8 +125,9 @@
         mStrokePaint.setStrokeWidth(1.0f);
 
         mFindInPageBridge = findInPageBridge;
-        mTab = tab;
-        mTab.getContentView().addView(this,
+
+        mContentView = contentView;
+        mContentView.addView(this,
                 new FrameLayout.LayoutParams(
                         mBarTouchWidth, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.END));
         setTranslationX(MathUtils.flipSignIf(mBarTouchWidth, LocalizationUtils.isLayoutRtl()));
@@ -130,7 +135,11 @@
         mVisibilityAnimation = ObjectAnimator.ofFloat(this, TRANSLATION_X, 0);
         mVisibilityAnimation.setDuration(VISIBILITY_ANIMATION_DURATION_MS);
         mVisibilityAnimation.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
-        mTab.getWindowAndroid().startAnimationOverContent(mVisibilityAnimation);
+        WindowAndroid window = mContentView.getWebContents().getTopLevelNativeWindow();
+        if (window == null) {
+            throw new IllegalArgumentException("ContentView must be attached to a window.");
+        }
+        window.startAnimationOverContent(mVisibilityAnimation);
     }
 
     /** Dismisses this results bar by removing it from the view hierarchy. */
@@ -145,7 +154,8 @@
                 MathUtils.flipSignIf(mBarTouchWidth, LocalizationUtils.isLayoutRtl()));
         mVisibilityAnimation.setDuration(VISIBILITY_ANIMATION_DURATION_MS);
         mVisibilityAnimation.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
-        mTab.getWindowAndroid().startAnimationOverContent(mVisibilityAnimation);
+        mContentView.getWebContents().getTopLevelNativeWindow().startAnimationOverContent(
+                mVisibilityAnimation);
         mVisibilityAnimation.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
index e6a79da..03c3e09 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
@@ -744,7 +744,8 @@
                 && mCurrentTab.getWebContents() != null) {
             assert mFindInPageBridge != null;
 
-            mResultBar = new FindResultBar(getContext(), mCurrentTab, mFindInPageBridge);
+            mResultBar = new FindResultBar(
+                    getContext(), mCurrentTab.getContentView(), mFindInPageBridge);
         } else if (!visibility) {
             if (mResultBar != null) {
                 mResultBar.dismiss();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
index 0da9b6a..d0623c2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -159,8 +159,7 @@
         /**
          * Called when the height of the top controls are changed.
          */
-        default void onTopControlsHeightChanged(
-                int topControlsHeight, int topControlsMinHeight, boolean controlsResizeView) {}
+        default void onTopControlsHeightChanged(int topControlsHeight, int topControlsMinHeight) {}
 
         /**
          * Called when the viewport size of the active content is updated.
@@ -548,7 +547,7 @@
         mTopControlsMinHeight = topControlsMinHeight;
         for (int i = 0; i < mListeners.size(); i++) {
             mListeners.get(i).onTopControlsHeightChanged(
-                    mTopControlContainerHeight, mTopControlsMinHeight, mControlsResizeView);
+                    mTopControlContainerHeight, mTopControlsMinHeight);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/BrowserControlsMarginSupplier.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/BrowserControlsMarginSupplier.java
index ce317ee..0487c79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/BrowserControlsMarginSupplier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/BrowserControlsMarginSupplier.java
@@ -41,8 +41,7 @@
     public void onToggleOverlayVideoMode(boolean enabled) {}
 
     @Override
-    public void onTopControlsHeightChanged(
-            int topControlsHeight, int topControlsMinHeight, boolean controlsResizeView) {
+    public void onTopControlsHeightChanged(int topControlsHeight, int topControlsMinHeight) {
         updateMargins();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
index 723fdf2..cfcc24bf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
@@ -189,12 +189,6 @@
     void setDefaultTextEditActionModeCallback(ToolbarActionModeCallback callback);
 
     /**
-     * @return The margin to be applied to the URL bar based on the buttons currently visible next
-     *         to it, used to avoid text overlapping the buttons and vice versa.
-     */
-    int getUrlContainerMarginEnd();
-
-    /**
      * Called to set the width of the location bar when the url bar is not focused.
      *
      * Immediately after the animation to transition the URL bar from focused to unfocused finishes,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index afdc8b2..9b9c11ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -573,8 +573,7 @@
      * @return The margin to be applied to the URL bar based on the buttons currently visible next
      *         to it, used to avoid text overlapping the buttons and vice versa.
      */
-    @Override
-    public int getUrlContainerMarginEnd() {
+    private int getUrlContainerMarginEnd() {
         int urlContainerMarginEnd = 0;
         for (View childView : getUrlContainerViewsForMargin()) {
             ViewGroup.MarginLayoutParams childLayoutParams =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogContents.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogContents.java
index 1e783bb..ad6a369 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogContents.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogContents.java
@@ -13,6 +13,20 @@
  * Class containing all data that customizes the contents displayed in the dialog.
  */
 public class PasswordManagerDialogContents {
+    /**
+     * Helper class for range.
+     * TODO(crbug.com/1041591): Replace it with android.util.Range once the minimum API level is 21.
+     */
+    public static class BoldRange {
+        public final int start;
+        public final int end;
+        BoldRange(int start, int end) {
+            assert (start <= end);
+            this.start = start;
+            this.end = end;
+        }
+    }
+
     private final String mTitle;
     private final String mDetails;
     private final String mPrimaryButtonText;
@@ -23,6 +37,7 @@
     private boolean mPrimaryButtonFilled;
     private @Nullable Runnable mHelpButtonCallback;
     private @ModalDialogManager.ModalDialogType int mDialogType;
+    private BoldRange[] mBoldRanges;
 
     /**
      * Constructor for the dialog contents.
@@ -48,6 +63,7 @@
         mPrimaryButtonFilled = false;
         mHelpButtonCallback = null;
         mDialogType = ModalDialogManager.ModalDialogType.APP;
+        mBoldRanges = new BoldRange[] {};
     }
 
     /**
@@ -73,6 +89,19 @@
     }
 
     /**
+     * Sets the bold ranges in the dialog details.
+     * @param boldStartRanges The start positions of bold spans in dialog details, inclusive.
+     * @param boldEndRanges The end positions of bold spans in dialog details, exclusive.
+     */
+    public void setBoldRanges(int[] boldStartRanges, int[] boldEndRanges) {
+        assert (boldStartRanges.length == boldEndRanges.length);
+        mBoldRanges = new BoldRange[boldStartRanges.length];
+        for (int i = 0; i < boldStartRanges.length; i++) {
+            mBoldRanges[i] = new BoldRange(boldStartRanges[i], boldEndRanges[i]);
+        }
+    }
+
+    /**
      * Returns the title of the dialog. It is also used as content description.
      */
     public String getTitle() {
@@ -139,4 +168,11 @@
     public @ModalDialogManager.ModalDialogType int getDialogType() {
         return mDialogType;
     }
+
+    /**
+     * Returns the bold ranges in the details text.
+     */
+    public BoldRange[] getBoldRanges() {
+        return mBoldRanges;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogCoordinator.java
index 84c41c8..d013f353 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogCoordinator.java
@@ -10,6 +10,10 @@
 import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogProperties.TITLE;
 
 import android.content.Context;
+import android.graphics.Typeface;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.style.StyleSpan;
 import android.view.LayoutInflater;
 import android.view.View;
 
@@ -17,6 +21,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
+import org.chromium.chrome.browser.password_manager.PasswordManagerDialogContents.BoldRange;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modaldialog.ModalDialogProperties;
@@ -60,12 +65,23 @@
     private PropertyModel buildModel(PasswordManagerDialogContents contents) {
         return PasswordManagerDialogProperties.defaultModelBuilder()
                 .with(TITLE, contents.getTitle())
-                .with(DETAILS, contents.getDetails())
+                .with(DETAILS,
+                        addBoldSpanToDetails(contents.getDetails(), contents.getBoldRanges()))
                 .with(ILLUSTRATION, contents.getIllustrationId())
                 .with(HELP_BUTTON_CALLBACK, contents.getHelpButtonCallback())
                 .build();
     }
 
+    private SpannableString addBoldSpanToDetails(String details, BoldRange[] boldRanges) {
+        SpannableString spannableDetails = new SpannableString(details);
+        for (BoldRange boldRange : boldRanges) {
+            StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
+            spannableDetails.setSpan(
+                    boldSpan, boldRange.start, boldRange.end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        }
+        return spannableDetails;
+    }
+
     @VisibleForTesting
     public PasswordManagerDialogMediator getMediatorForTesting() {
         return mMediator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogProperties.java
index 7e240e22..5b3f2db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogProperties.java
@@ -27,7 +27,8 @@
     static final ReadableObjectPropertyKey<String> TITLE = new ReadableObjectPropertyKey<>();
 
     // Multiline explanation text displayed under the illustration.
-    static final ReadableObjectPropertyKey<String> DETAILS = new ReadableObjectPropertyKey<>();
+    static final ReadableObjectPropertyKey<CharSequence> DETAILS =
+            new ReadableObjectPropertyKey<>();
 
     private PasswordManagerDialogProperties() {}
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogView.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogView.java
index df5281ce..554242c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogView.java
@@ -81,7 +81,7 @@
         mTitleView.setText(title);
     }
 
-    void setDetails(String details) {
+    void setDetails(CharSequence details) {
         mDetailsView.setText(details);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index de1016c3..a9d9060 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -6,13 +6,13 @@
 
 import android.content.Context;
 import android.view.View;
-import android.view.ViewGroup;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import org.chromium.base.UserDataHost;
 import org.chromium.chrome.browser.native_page.NativePage;
+import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
@@ -78,7 +78,7 @@
      * @return Content view used for rendered web contents. Can be null
      *    if web contents is null.
      */
-    ViewGroup getContentView();
+    ContentView getContentView();
 
     /**
      * @return The {@link View} displaying the current page in the tab. This can be {@code null}, if
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 3d744c49..aba2a33 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -13,7 +13,6 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
-import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 
 import androidx.annotation.Nullable;
@@ -95,7 +94,7 @@
     private WebContents mWebContents;
 
     /** The parent view of the ContentView and the InfoBarContainer. */
-    private ViewGroup mContentView;
+    private ContentView mContentView;
 
     /** A list of Tab observers.  These are used to broadcast Tab events to listeners. */
     private final ObserverList<TabObserver> mObservers = new ObserverList<>();
@@ -334,7 +333,7 @@
     }
 
     @Override
-    public ViewGroup getContentView() {
+    public ContentView getContentView() {
         return mContentView;
     }
 
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 14831ab..5c4035b0 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
@@ -152,7 +152,10 @@
     }
 
     private void initStatusIndicatorCoordinator(LayoutManager layoutManager) {
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.OFFLINE_INDICATOR_V2)) {
+        // TODO(crbug.com/1035584): Disable on tablets for now as we need to do one or two extra
+        // things for tablets.
+        if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity)
+                || !ChromeFeatureList.isEnabled(ChromeFeatureList.OFFLINE_INDICATOR_V2)) {
             return;
         }
 
@@ -160,8 +163,6 @@
                 mActivity, mActivity.getCompositorViewHolder().getResourceManager());
         layoutManager.setStatusIndicatorSceneOverlay(mStatusIndicatorCoordinator.getSceneLayer());
         mStatusIndicatorObserver = (indicatorHeight -> {
-            getToolbarManager().setControlContainerTopMargin(indicatorHeight);
-            layoutManager.getToolbarSceneLayer().setStaticYOffset(indicatorHeight);
             final int resourceId = mActivity.getControlContainerHeightResource();
             final int topControlsNewHeight =
                     mActivity.getResources().getDimensionPixelSize(resourceId) + indicatorHeight;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index fd7a7f5..0b50fe7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -634,6 +634,20 @@
                 }
             }
 
+            @Override
+            public void onBrowserControlsOffsetChanged(Tab tab, int topControlsOffsetY,
+                    int bottomControlsOffsetY, int contentOffsetY) {
+                // For now, this is only useful for the offline indicator v2 feature.
+                if (ChromeFeatureList.isInitialized()
+                        && !ChromeFeatureList.isEnabled(ChromeFeatureList.OFFLINE_INDICATOR_V2)) {
+                    return;
+                }
+
+                // Controls need to be offset to match the composited layer, which is
+                // anchored at the bottom of the controls container.
+                setControlContainerTopMargin(getToolbarExtraYOffset());
+            }
+
             private void handleIPHForSuccessfulPageLoad(final Tab tab) {
                 if (mTextBubble != null) {
                     mTextBubble.dismiss();
@@ -1687,17 +1701,6 @@
     }
 
     /**
-     * Sets the top margin for the control container.
-     * @param margin The margin in pixels.
-     */
-    public void setControlContainerTopMargin(int margin) {
-        final ViewGroup.MarginLayoutParams layoutParams =
-                ((ViewGroup.MarginLayoutParams) mControlContainer.getLayoutParams());
-        layoutParams.topMargin = margin;
-        mControlContainer.setLayoutParams(layoutParams);
-    }
-
-    /**
      * Gets the Toolbar view.
      */
     @Nullable
@@ -1706,6 +1709,18 @@
     }
 
     /**
+     * We use getTopControlOffset to position the top controls. However, the toolbar's height may
+     * be less than the total top controls height. If that's the case, this method will return the
+     * extra offset needed to align the toolbar at the bottom of the top controls.
+     * @return The extra Y offset for the toolbar in pixels.
+     */
+    private int getToolbarExtraYOffset() {
+        final int stripAndToolbarHeight = mActivity.getResources().getDimensionPixelSize(
+                R.dimen.tab_strip_and_toolbar_height);
+        return mActivity.getFullscreenManager().getTopControlsHeight() - stripAndToolbarHeight;
+    }
+
+    /**
      * Sets the drawable that the close button shows, or hides it if {@code drawable} is
      * {@code null}.
      */
@@ -2045,6 +2060,21 @@
                 == Configuration.KEYBOARD_QWERTY;
     }
 
+    /**
+     * Sets the top margin for the control container.
+     * @param margin The margin in pixels.
+     */
+    private void setControlContainerTopMargin(int margin) {
+        final ViewGroup.MarginLayoutParams layoutParams =
+                ((ViewGroup.MarginLayoutParams) mControlContainer.getLayoutParams());
+        if (layoutParams.topMargin == margin) {
+            return;
+        }
+
+        layoutParams.topMargin = margin;
+        mControlContainer.setLayoutParams(layoutParams);
+    }
+
     private static class LoadProgressSimulator {
         private static final int MSG_ID_UPDATE_PROGRESS = 1;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
index dfa7697..ad07b87 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java
@@ -839,11 +839,6 @@
         public void setShowIconsWhenUrlFocused(boolean showIcon) {}
 
         @Override
-        public int getUrlContainerMarginEnd() {
-            return 0;
-        }
-
-        @Override
         public void setUnfocusedWidth(int unfocusedWidth) {}
 
         @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreInstallUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreInstallUtils.java
index 4548a393..a08ab3c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreInstallUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreInstallUtils.java
@@ -6,7 +6,6 @@
 
 import android.app.Activity;
 
-import org.chromium.base.BundleUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
@@ -82,7 +81,8 @@
     @CalledByNative
     private boolean canRequestInstallArModule() {
         // We can only try to install the AR module if we are in a bundle mode.
-        return BundleUtils.isBundle();
+        // Currently, AR DFM is disabled so we should never have to install it.
+        return false;
     }
 
     @CalledByNative
diff --git a/chrome/android/modules/chrome_feature_modules.gni b/chrome/android/modules/chrome_feature_modules.gni
index 8b8202a..016da28e 100644
--- a/chrome/android/modules/chrome_feature_modules.gni
+++ b/chrome/android/modules/chrome_feature_modules.gni
@@ -60,7 +60,7 @@
 
 # Modules shipped in Monochrome (Android N+).
 monochrome_module_descs = chrome_modern_module_descs
-if (enable_arcore) {
+if (false) {  # AR DFM is currently disabled
   monochrome_module_descs += [ ar_module_desc ]
 }
 if (!disable_autofill_assistant_dfm) {
diff --git a/chrome/android/modules/test_dummy/provider/BUILD.gn b/chrome/android/modules/test_dummy/provider/BUILD.gn
index 5802333d..5932e88 100644
--- a/chrome/android/modules/test_dummy/provider/BUILD.gn
+++ b/chrome/android/modules/test_dummy/provider/BUILD.gn
@@ -11,7 +11,5 @@
     "//chrome/android/features/test_dummy/public:java",
     "//chrome/android/modules/test_dummy/public:java",
   ]
-  sources = [
-    "java/src/org/chromium/chrome/modules/test_dummy/TestDummyModuleProvider.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyModuleProvider.java" ]
 }
diff --git a/chrome/app/version_assembly/BUILD.gn b/chrome/app/version_assembly/BUILD.gn
index 5efaff9..56cfbad 100644
--- a/chrome/app/version_assembly/BUILD.gn
+++ b/chrome/app/version_assembly/BUILD.gn
@@ -13,9 +13,7 @@
   process_only = true
   visibility = [ ":*" ]
   template_file = "chrome_exe_manifest.template"
-  sources = [
-    "//chrome/VERSION",
-  ]
+  sources = [ "//chrome/VERSION" ]
   output = version_assembly_output_file
 }
 
@@ -29,18 +27,14 @@
     version_assembly_output_file,
   ]
 
-  deps = [
-    ":chrome_exe_version_manifest",
-  ]
+  deps = [ ":chrome_exe_version_manifest" ]
 }
 
 # Generates the manifest for the version assembly, which is the versioned
 # directory where Chrome finds chrome.dll.
 process_version("version_assembly_manifest") {
   template_file = "version_assembly_manifest.template"
-  sources = [
-    "//chrome/VERSION",
-  ]
+  sources = [ "//chrome/VERSION" ]
   output = "$root_build_dir/$chrome_version_full.manifest"
   process_only = true
 }
diff --git a/chrome/browser/android/compositor/layer/tab_layer.cc b/chrome/browser/android/compositor/layer/tab_layer.cc
index 7f7da6c..809b1ca1 100644
--- a/chrome/browser/android/compositor/layer/tab_layer.cc
+++ b/chrome/browser/android/compositor/layer/tab_layer.cc
@@ -144,7 +144,7 @@
                              int toolbar_textbox_background_color,
                              float toolbar_textbox_alpha,
                              float toolbar_alpha,
-                             float toolbar_y_offset,
+                             float content_offset,
                              float side_border_scale,
                              bool inset_border) {
   if (alpha <= 0) {
@@ -231,15 +231,12 @@
   toolbar_layer_->PushResource(
       toolbar_resource_id, toolbar_background_color, anonymize_toolbar,
       toolbar_textbox_background_color, toolbar_textbox_resource_id,
-      toolbar_textbox_alpha, view_height,
-      // TODO(mdjones): Feels odd to pass 0 here when
-      // we have access to toolbar_y_offset.
-      0, false, false);
+      toolbar_textbox_alpha, view_height, content_offset, false, false);
   toolbar_layer_->UpdateProgressBar(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
   float toolbar_impact_height = 0;
   if (show_toolbar && !back_visible)
-    toolbar_impact_height = toolbar_layer_->layer()->bounds().height();
+    toolbar_impact_height = content_offset;
 
   //----------------------------------------------------------------------------
   // Compute Alpha and Visibility
@@ -292,9 +289,8 @@
       descaled_local_content_area.height() - toolbar_impact_height);
 
   // Shrink the toolbar layer so we properly clip if it's offset.
-  gfx::Size toolbar_size(
-      toolbar_layer_->layer()->bounds().width(),
-      toolbar_layer_->layer()->bounds().height() - toolbar_y_offset);
+  gfx::Size toolbar_size(toolbar_layer_->layer()->bounds().width(),
+                         toolbar_layer_->layer()->bounds().height());
 
   //----------------------------------------------------------------------------
   // Compute Layer Positions
diff --git a/chrome/browser/android/compositor/layer/toolbar_layer.cc b/chrome/browser/android/compositor/layer/toolbar_layer.cc
index ada6e07..c2712db 100644
--- a/chrome/browser/android/compositor/layer/toolbar_layer.cc
+++ b/chrome/browser/android/compositor/layer/toolbar_layer.cc
@@ -32,7 +32,7 @@
                                 int url_bar_background_resource_id,
                                 float url_bar_alpha,
                                 float window_height,
-                                float y_offset,
+                                float content_offset,
                                 bool show_debug,
                                 bool clip_shadow) {
   ToolbarResource* resource =
@@ -110,7 +110,9 @@
   else if (!show_debug && debug_layer_->parent())
     debug_layer_->RemoveFromParent();
 
-  layer_->SetPosition(gfx::PointF(0, y_offset));
+  // Position the toolbar at the bottom of the space available for top controls.
+  layer_->SetPosition(
+      gfx::PointF(0, content_offset - layer_->bounds().height()));
 }
 
 int ToolbarLayer::GetIndexOfLayer(scoped_refptr<cc::Layer> layer) {
diff --git a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
index 71f69ee5..dd86466 100644
--- a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
@@ -145,7 +145,7 @@
     jint toolbar_textbox_background_color,
     jfloat toolbar_textbox_alpha,
     jfloat toolbar_alpha,
-    jfloat toolbar_y_offset,
+    jfloat content_offset,
     jfloat side_border_scale,
     jboolean inset_border) {
   scoped_refptr<TabLayer> layer;
@@ -189,8 +189,8 @@
         show_toolbar, default_theme_color, toolbar_background_color,
         close_button_color, anonymize_toolbar, show_tab_title,
         toolbar_textbox_resource_id, toolbar_textbox_background_color,
-        toolbar_textbox_alpha, toolbar_alpha, toolbar_y_offset,
-        side_border_scale, inset_border);
+        toolbar_textbox_alpha, toolbar_alpha, content_offset, side_border_scale,
+        inset_border);
   }
 
   gfx::RectF self(own_tree_->position(), gfx::SizeF(own_tree_->bounds()));
diff --git a/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc
index 837a6df..39685a3 100644
--- a/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/toolbar_scene_layer.cc
@@ -38,7 +38,7 @@
     jint url_bar_resource_id,
     jfloat url_bar_alpha,
     jint url_bar_color,
-    jfloat y_offset,
+    jfloat content_offset,
     jfloat view_height,
     bool visible,
     bool show_shadow) {
@@ -55,8 +55,8 @@
   if (visible) {
     toolbar_layer_->PushResource(toolbar_resource_id, toolbar_background_color,
                                  false, url_bar_color, url_bar_resource_id,
-                                 url_bar_alpha, view_height, y_offset, false,
-                                 !show_shadow);
+                                 url_bar_alpha, view_height, content_offset,
+                                 false, !show_shadow);
   }
 }
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_consent_prompt.cc b/chrome/browser/android/vr/arcore_device/arcore_consent_prompt.cc
index aa511b1..21a7edef 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_consent_prompt.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_consent_prompt.cc
@@ -66,9 +66,8 @@
 
 ArCoreConsentPrompt::~ArCoreConsentPrompt() = default;
 
-void ArCoreConsentPrompt::OnUserConsentResult(
-    JNIEnv* env,
-    jboolean is_granted) {
+void ArCoreConsentPrompt::OnUserConsentResult(JNIEnv* env,
+                                              jboolean is_granted) {
   jdelegate_.Reset();
 
   if (!on_user_consent_callback_)
@@ -139,9 +138,8 @@
       GetTabFromRenderer(render_process_id_, render_frame_id_));
 }
 
-void ArCoreConsentPrompt::OnRequestInstallArModuleResult(
-    JNIEnv* env,
-    bool success) {
+void ArCoreConsentPrompt::OnRequestInstallArModuleResult(JNIEnv* env,
+                                                         bool success) {
   DVLOG(1) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
@@ -150,9 +148,8 @@
   }
 }
 
-void ArCoreConsentPrompt::OnRequestInstallSupportedArCoreResult(
-    JNIEnv* env,
-    bool success) {
+void ArCoreConsentPrompt::OnRequestInstallSupportedArCoreResult(JNIEnv* env,
+                                                                bool success) {
   DVLOG(1) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(on_request_arcore_install_or_update_result_callback_);
@@ -162,15 +159,14 @@
 
 void ArCoreConsentPrompt::RequestArModule() {
   DVLOG(1) << __func__;
-  if (ShouldRequestInstallArModule()) {
-    if (!CanRequestInstallArModule()) {
-      OnRequestArModuleResult(false);
-      return;
-    }
 
-    on_request_ar_module_result_callback_ = base::BindOnce(
-        &ArCoreConsentPrompt::OnRequestArModuleResult, GetWeakPtr());
-    RequestInstallArModule();
+  if (ShouldRequestInstallArModule()) {
+    // AR DFM is disabled - if we think we should install AR module, then it
+    // means that we are using a build that does not support AR capabilities.
+    // Treat this as if the AR module installation failed.
+    LOG(WARNING) << "AR is not supported on this build";
+
+    OnRequestArModuleResult(false);
     return;
   }
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
index dce5c25..72992c1 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_java_utils.cc
@@ -19,10 +19,6 @@
 
 namespace vr {
 
-namespace {
-
-}  // namespace
-
 ArCoreJavaUtils::ArCoreJavaUtils() {
   JNIEnv* env = AttachCurrentThread();
   if (!env)
@@ -109,6 +105,21 @@
   // absolute path.
   ScopedJavaLocalRef<jstring> java_path =
       Java_ArCoreJavaUtils_getArCoreShimLibraryPath(env);
+
+  // Crash in debug builds if `java_path` is a null pointer but handle this
+  // situation in release builds. This is done by design - the `java_path` will
+  // be null only if there was a regression introduced to our gn/gni files w/o
+  // causing a build break. In release builds, this approach will result in the
+  // site not being able to request an AR session.
+  DCHECK(java_path)
+      << "Unable to find path to ARCore SDK library - please ensure that "
+         "loadable_modules and secondary_abi_loadable_modules are set "
+         "correctly when building";
+  if (!java_path) {
+    LOG(ERROR) << "Unable to find path to ARCore SDK library";
+    return false;
+  }
+
   return LoadArCoreSdk(base::android::ConvertJavaStringToUTF8(env, java_path));
 }
 
diff --git a/chrome/browser/apps/app_service/app_service_metrics.cc b/chrome/browser/apps/app_service/app_service_metrics.cc
index 68d7382..2590fee 100644
--- a/chrome/browser/apps/app_service/app_service_metrics.cc
+++ b/chrome/browser/apps/app_service/app_service_metrics.cc
@@ -70,10 +70,18 @@
       UMA_HISTOGRAM_ENUMERATION("Apps.DefaultAppLaunch.FromFileManager",
                                 default_app_name);
       break;
-    // TODO(crbug.com/853604): Add metrics.
     case apps::mojom::LaunchSource::kFromLink:
+      UMA_HISTOGRAM_ENUMERATION("Apps.DefaultAppLaunch.FromLink",
+                                default_app_name);
+      break;
     case apps::mojom::LaunchSource::kFromOmnibox:
-      return;
+      UMA_HISTOGRAM_ENUMERATION("Apps.DefaultAppLaunch.FromOmnibox",
+                                default_app_name);
+      break;
+    case apps::mojom::LaunchSource::kFromChromeInternal:
+      UMA_HISTOGRAM_ENUMERATION("Apps.DefaultAppLaunch.FromChromeInternal",
+                                default_app_name);
+      break;
   }
 }
 
@@ -98,6 +106,7 @@
     case apps::mojom::LaunchSource::kFromFileManager:
     case apps::mojom::LaunchSource::kFromLink:
     case apps::mojom::LaunchSource::kFromOmnibox:
+    case apps::mojom::LaunchSource::kFromChromeInternal:
       break;
   }
 }
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc
index 7d59ab6..ecbf8ba 100644
--- a/chrome/browser/apps/app_service/extension_apps.cc
+++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -117,6 +117,7 @@
     case apps::mojom::LaunchSource::kFromFileManager:
     case apps::mojom::LaunchSource::kFromLink:
     case apps::mojom::LaunchSource::kFromOmnibox:
+    case apps::mojom::LaunchSource::kFromChromeInternal:
       return ash::LAUNCH_FROM_UNKNOWN;
   }
 }
@@ -407,6 +408,7 @@
     case apps::mojom::LaunchSource::kFromFileManager:
     case apps::mojom::LaunchSource::kFromLink:
     case apps::mojom::LaunchSource::kFromOmnibox:
+    case apps::mojom::LaunchSource::kFromChromeInternal:
       break;
   }
 
diff --git a/chrome/browser/chromeos/power/ml/BUILD.gn b/chrome/browser/chromeos/power/ml/BUILD.gn
index 0bcddd4..a4f29c7 100644
--- a/chrome/browser/chromeos/power/ml/BUILD.gn
+++ b/chrome/browser/chromeos/power/ml/BUILD.gn
@@ -3,13 +3,9 @@
 # found in the LICENSE file.
 
 source_set("user_activity_ukm_logger_helpers") {
-  public = [
-    "user_activity_ukm_logger_helpers.h",
-  ]
+  public = [ "user_activity_ukm_logger_helpers.h" ]
 
-  sources = [
-    "user_activity_ukm_logger_helpers.cc",
-  ]
+  sources = [ "user_activity_ukm_logger_helpers.cc" ]
 
   deps = [
     "//base",
diff --git a/chrome/browser/image_editor/internal/BUILD.gn b/chrome/browser/image_editor/internal/BUILD.gn
index 116179d..12c1e6d 100644
--- a/chrome/browser/image_editor/internal/BUILD.gn
+++ b/chrome/browser/image_editor/internal/BUILD.gn
@@ -7,11 +7,7 @@
 # Upstream ImageEditor implementation which does nothing. Actual implementation
 # lives downstream.
 android_library("java") {
-  sources = [
-    "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinatorImpl.java",
-  ]
+  sources = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinatorImpl.java" ]
 
-  deps = [
-    "//chrome/browser/image_editor/public:java",
-  ]
+  deps = [ "//chrome/browser/image_editor/public:java" ]
 }
diff --git a/chrome/browser/image_editor/public/BUILD.gn b/chrome/browser/image_editor/public/BUILD.gn
index 87f6881..1e4d315 100644
--- a/chrome/browser/image_editor/public/BUILD.gn
+++ b/chrome/browser/image_editor/public/BUILD.gn
@@ -5,11 +5,7 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [
-    "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinator.java",
-  ]
+  sources = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinator.java" ]
 
-  deps = [
-    "//third_party/android_deps:android_support_v7_appcompat_java",
-  ]
+  deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
 }
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
index 7b93b5d..d9ac1cb 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -24,7 +24,6 @@
 #include "components/performance_manager/embedder/performance_manager_registry.h"
 #include "components/performance_manager/performance_manager_lock_observer.h"
 #include "components/performance_manager/public/graph/graph.h"
-#include "components/performance_manager/worker_watcher.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_features.h"
 
@@ -130,11 +129,6 @@
   g_browser_process->profile_manager()->RemoveObserver(this);
   observed_profiles_.RemoveAll();
 
-  // Clear up the worker nodes.
-  for (auto& worker_watcher : worker_watchers_)
-    worker_watcher.second->TearDown();
-  worker_watchers_.clear();
-
   page_live_state_data_helper_.reset();
 
   // There may still be WebContents and RenderProcessHosts with attached user
@@ -152,15 +146,7 @@
 void ChromeBrowserMainExtraPartsPerformanceManager::OnProfileAdded(
     Profile* profile) {
   observed_profiles_.Add(profile);
-  auto worker_watcher = std::make_unique<performance_manager::WorkerWatcher>(
-      profile->UniqueId(),
-      content::BrowserContext::GetDefaultStoragePartition(profile)
-          ->GetSharedWorkerService(),
-      &process_node_source_, &frame_node_source_);
-
-  bool inserted =
-      worker_watchers_.insert({profile, std::move(worker_watcher)}).second;
-  DCHECK(inserted);
+  registry_->NotifyBrowserContextAdded(profile);
 }
 
 void ChromeBrowserMainExtraPartsPerformanceManager::
@@ -171,8 +157,5 @@
 void ChromeBrowserMainExtraPartsPerformanceManager::OnProfileWillBeDestroyed(
     Profile* profile) {
   observed_profiles_.Remove(profile);
-  auto it = worker_watchers_.find(profile);
-  DCHECK(it != worker_watchers_.end());
-  it->second->TearDown();
-  worker_watchers_.erase(it);
+  registry_->NotifyBrowserContextRemoved(profile);
 }
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
index 5831d0b..92d4d50 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
@@ -15,8 +15,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager_observer.h"
 #include "chrome/browser/profiles/profile_observer.h"
-#include "components/performance_manager/process_node_source.h"
-#include "components/performance_manager/tab_helper_frame_node_source.h"
 
 class Profile;
 
@@ -30,7 +28,6 @@
 class PageLiveStateDecoratorHelper;
 class PerformanceManager;
 class PerformanceManagerRegistry;
-class WorkerWatcher;
 }  // namespace performance_manager
 
 // Handles the initialization of the performance manager and a few dependent
@@ -79,15 +76,6 @@
 
   ScopedObserver<Profile, ProfileObserver> observed_profiles_{this};
 
-  // Needed by the worker watchers to access existing process nodes and frame
-  // nodes.
-  performance_manager::ProcessNodeSource process_node_source_;
-  performance_manager::TabHelperFrameNodeSource frame_node_source_;
-
-  // Observes the lifetime of all types of workers.
-  base::flat_map<Profile*, std::unique_ptr<performance_manager::WorkerWatcher>>
-      worker_watchers_;
-
   // Needed to properly maintain some of the PageLiveStateDecorator' properties.
   std::unique_ptr<performance_manager::PageLiveStateDecoratorHelper>
       page_live_state_data_helper_;
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 1e8fa49b..f339f69 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -298,6 +298,7 @@
     extensions::kExtensionScheme,
 #endif
     content::kChromeUIScheme,
+    content::kChromeUIUntrustedScheme,
     url::kDataScheme,
 #if defined(OS_CHROMEOS)
     content::kExternalFileScheme,
diff --git a/chrome/browser/resource_coordinator/BUILD.gn b/chrome/browser/resource_coordinator/BUILD.gn
index c308b79..c5e180f 100644
--- a/chrome/browser/resource_coordinator/BUILD.gn
+++ b/chrome/browser/resource_coordinator/BUILD.gn
@@ -7,25 +7,17 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("tab_metrics_event_proto") {
-  sources = [
-    "tab_metrics_event.proto",
-  ]
+  sources = [ "tab_metrics_event.proto" ]
 }
 
 mojom("mojo_bindings") {
-  sources = [
-    "lifecycle_unit_state.mojom",
-  ]
+  sources = [ "lifecycle_unit_state.mojom" ]
 }
 
 source_set("tab_manager_features") {
-  public = [
-    "tab_manager_features.h",
-  ]
+  public = [ "tab_manager_features.h" ]
 
-  sources = [
-    "tab_manager_features.cc",
-  ]
+  sources = [ "tab_manager_features.cc" ]
 
   deps = [
     "//base",
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 1c31c6b..11b3775 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -586,8 +586,9 @@
       while (node && !node.details) {
         node = node.parent;
       }
-      if (node) {
-        current = cursors.Range.fromNode(node.details);
+      if (node && node.details.length) {
+        // TODO currently can only jump to first detail.
+        current = cursors.Range.fromNode(node.details[0]);
       }
       break;
     case 'readFromHere':
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn b/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
index 980be60..a4dd8090 100644
--- a/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
+++ b/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
@@ -18,9 +18,7 @@
 }
 
 js_type_check("closure_compile") {
-  deps = [
-    ":internet_detail_dialog",
-  ]
+  deps = [ ":internet_detail_dialog" ]
 }
 
 js_library("internet_detail_dialog") {
diff --git a/chrome/browser/resources/downloads/BUILD.gn b/chrome/browser/resources/downloads/BUILD.gn
index d1bcb37f..af70a9b 100644
--- a/chrome/browser/resources/downloads/BUILD.gn
+++ b/chrome/browser/resources/downloads/BUILD.gn
@@ -33,9 +33,7 @@
     pak_file = downloads_pak_file
     out_folder = unpak_folder
 
-    deps = [
-      ":flattened_resources",
-    ]
+    deps = [ ":flattened_resources" ]
   }
 
   grit("flattened_resources") {
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index f30d514c..fd049191 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -29,9 +29,7 @@
     pak_file = extensions_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/extensions_resources.h",
@@ -352,16 +348,12 @@
 }
 
 js_library("host_permissions_toggle_list") {
-  deps = [
-    ":item",
-  ]
+  deps = [ ":item" ]
   externs_list = [ "$externs_path/developer_private.js" ]
 }
 
 js_library("install_warnings_dialog") {
-  deps = [
-    "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
-  ]
+  deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m" ]
   externs_list = [ "$externs_path/developer_private.js" ]
 }
 
@@ -380,9 +372,7 @@
 }
 
 js_library("item_behavior") {
-  deps = [
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
+  deps = [ "//ui/webui/resources/js:load_time_data.m" ]
   externs_list = [ "$externs_path/developer_private.js" ]
 }
 
@@ -428,9 +418,7 @@
 }
 
 js_library("kiosk_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
 if (is_chromeos) {
diff --git a/chrome/browser/resources/usb_internals/BUILD.gn b/chrome/browser/resources/usb_internals/BUILD.gn
index a91a629..30f5807 100644
--- a/chrome/browser/resources/usb_internals/BUILD.gn
+++ b/chrome/browser/resources/usb_internals/BUILD.gn
@@ -50,7 +50,5 @@
     "-E",
     "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
   ]
-  deps = [
-    "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js",
-  ]
+  deps = [ "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js" ]
 }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
index b70386c..ec22470 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
@@ -164,26 +164,19 @@
 
 // File types supported for DLP scanning.
 // Keep sorted for efficient access.
-constexpr const std::array<const base::FilePath::CharType*, 36>
+constexpr const std::array<const base::FilePath::CharType*, 21>
     kSupportedDLPFileTypes = {
-        FILE_PATH_LITERAL(".7z"),          FILE_PATH_LITERAL(".bzip"),
-        FILE_PATH_LITERAL(".cab"),         FILE_PATH_LITERAL(".doc"),
-        FILE_PATH_LITERAL(".docx"),        FILE_PATH_LITERAL(".eps"),
-        FILE_PATH_LITERAL(".gzip"),        FILE_PATH_LITERAL(".hwp"),
-        FILE_PATH_LITERAL(".img_for_ocr"), FILE_PATH_LITERAL(".kml"),
-        FILE_PATH_LITERAL(".kmz"),         FILE_PATH_LITERAL(".odp"),
-        FILE_PATH_LITERAL(".ods"),         FILE_PATH_LITERAL(".odt"),
-        FILE_PATH_LITERAL(".pdf"),         FILE_PATH_LITERAL(".ppt"),
-        FILE_PATH_LITERAL(".pptx"),        FILE_PATH_LITERAL(".ps"),
-        FILE_PATH_LITERAL(".rar"),         FILE_PATH_LITERAL(".rtf"),
-        FILE_PATH_LITERAL(".sdc"),         FILE_PATH_LITERAL(".sdd"),
-        FILE_PATH_LITERAL(".sdw"),         FILE_PATH_LITERAL(".sxc"),
-        FILE_PATH_LITERAL(".sxi"),         FILE_PATH_LITERAL(".sxw"),
-        FILE_PATH_LITERAL(".tar"),         FILE_PATH_LITERAL(".ttf"),
-        FILE_PATH_LITERAL(".txt"),         FILE_PATH_LITERAL(".wml"),
-        FILE_PATH_LITERAL(".wpd"),         FILE_PATH_LITERAL(".xls"),
-        FILE_PATH_LITERAL(".xlsx"),        FILE_PATH_LITERAL(".xml"),
-        FILE_PATH_LITERAL(".xps"),         FILE_PATH_LITERAL(".zip")};
+        FILE_PATH_LITERAL(".7z"),   FILE_PATH_LITERAL(".bzip"),
+        FILE_PATH_LITERAL(".cab"),  FILE_PATH_LITERAL(".doc"),
+        FILE_PATH_LITERAL(".docx"), FILE_PATH_LITERAL(".eps"),
+        FILE_PATH_LITERAL(".gzip"), FILE_PATH_LITERAL(".odt"),
+        FILE_PATH_LITERAL(".pdf"),  FILE_PATH_LITERAL(".ppt"),
+        FILE_PATH_LITERAL(".pptx"), FILE_PATH_LITERAL(".ps"),
+        FILE_PATH_LITERAL(".rar"),  FILE_PATH_LITERAL(".rtf"),
+        FILE_PATH_LITERAL(".tar"),  FILE_PATH_LITERAL(".txt"),
+        FILE_PATH_LITERAL(".wpd"),  FILE_PATH_LITERAL(".xls"),
+        FILE_PATH_LITERAL(".xlsx"), FILE_PATH_LITERAL(".xps"),
+        FILE_PATH_LITERAL(".zip")};
 
 }  // namespace
 
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc
index 9091458..40e4841 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc
@@ -1127,18 +1127,13 @@
   DeepScanningDialogDelegate::Data data;
   ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(profile(), url, &data));
 
+  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.7z"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.bzip"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.cab"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.doc"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.docx"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.eps"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.gzip"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.hwp"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.img_for_ocr"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.kml"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.kmz"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.odp"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.ods"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.odt"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.pdf"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.ppt"));
@@ -1146,21 +1141,11 @@
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.ps"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.rar"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.rtf"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sdc"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sdd"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sdw"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.7z"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sxc"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sxi"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.sxw"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.tar"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.ttf"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.txt"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.wml"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.wpd"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.xls"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.xlsx"));
-  data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.xml"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.xps"));
   data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.zip"));
 
@@ -1175,8 +1160,8 @@
       base::BindOnce(
           [](bool* called, const DeepScanningDialogDelegate::Data& data,
              const DeepScanningDialogDelegate::Result& result) {
-            EXPECT_EQ(36u, data.paths.size());
-            ASSERT_EQ(36u, result.paths_results.size());
+            EXPECT_EQ(21u, data.paths.size());
+            EXPECT_EQ(21u, result.paths_results.size());
 
             // The supported types should be marked as false.
             for (const auto& result : result.paths_results)
diff --git a/chrome/browser/sync_file_system/drive_backend/BUILD.gn b/chrome/browser/sync_file_system/drive_backend/BUILD.gn
index 99f079b0..18f1984a 100644
--- a/chrome/browser/sync_file_system/drive_backend/BUILD.gn
+++ b/chrome/browser/sync_file_system/drive_backend/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("sync_file_system_drive_proto") {
-  sources = [
-    "metadata_database.proto",
-  ]
+  sources = [ "metadata_database.proto" ]
 }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index a621122..1fbd4887 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -9,6 +9,7 @@
 import("//build/config/jumbo.gni")
 import("//build/config/linux/gtk/gtk.gni")
 import("//build/config/ui.gni")
+import("//chrome/browser/buildflags.gni")
 import("//chrome/common/features.gni")
 import("//chromeos/assistant/assistant.gni")
 import("//components/feature_engagement/features.gni")
@@ -390,6 +391,7 @@
     "//chrome/app/theme:chrome_unscaled_resources",
     "//chrome/app/theme:theme_resources",
     "//chrome/app/vector_icons",
+    "//chrome/browser:buildflags",
     "//chrome/browser:dev_ui_browser_resources",
     "//chrome/browser:resource_prefetch_predictor_proto",
     "//chrome/browser/devtools",
@@ -1454,6 +1456,10 @@
     }
   }
 
+  if (enable_kaleidoscope) {
+    deps += [ "//chrome/browser/media/kaleidoscope/internal" ]
+  }
+
   if (enable_supervised_users) {
     sources += [
       "webui/supervised_user_internals_message_handler.cc",
diff --git a/chrome/browser/ui/app_list/OWNERS b/chrome/browser/ui/app_list/OWNERS
index 301ef10..90b6293 100644
--- a/chrome/browser/ui/app_list/OWNERS
+++ b/chrome/browser/ui/app_list/OWNERS
@@ -1,7 +1,6 @@
 calamity@chromium.org
 jennyz@chromium.org
 khmel@chromium.org
-stevenjb@chromium.org
 xiyuan@chromium.org
 
 per-file app_launch_event_logger*=charleszhao@chromium.org
diff --git a/chrome/browser/ui/ash/OWNERS b/chrome/browser/ui/ash/OWNERS
index 54238d96..aee95f3 100644
--- a/chrome/browser/ui/ash/OWNERS
+++ b/chrome/browser/ui/ash/OWNERS
@@ -1,7 +1,6 @@
 jamescook@chromium.org
 oshima@chromium.org
 sky@chromium.org
-stevenjb@chromium.org
 xiyuan@chromium.org
 
 per-file chrome_keyboard_ui*=yhanada@chromium.org
diff --git a/chrome/browser/ui/ash/launcher/OWNERS b/chrome/browser/ui/ash/launcher/OWNERS
index 23593dd..5345cbf 100644
--- a/chrome/browser/ui/ash/launcher/OWNERS
+++ b/chrome/browser/ui/ash/launcher/OWNERS
@@ -1,5 +1,4 @@
 skuhne@chromium.org
-stevenjb@chromium.org
 khmel@chromium.org
 
-# COMPONENT: UI>Shell>Shelf
\ No newline at end of file
+# COMPONENT: UI>Shell>Shelf
diff --git a/chrome/browser/ui/ash/network/OWNERS b/chrome/browser/ui/ash/network/OWNERS
new file mode 100644
index 0000000..a83b4d9
--- /dev/null
+++ b/chrome/browser/ui/ash/network/OWNERS
@@ -0,0 +1,5 @@
+azeemarshad@chromium.org
+jonmann@chromium.org
+khorimoto@chromium.org
+
+# COMPONENT: UI>Shell>Networking
diff --git a/chrome/browser/ui/cocoa/notifications/BUILD.gn b/chrome/browser/ui/cocoa/notifications/BUILD.gn
index 8e06dc2..dac35c0 100644
--- a/chrome/browser/ui/cocoa/notifications/BUILD.gn
+++ b/chrome/browser/ui/cocoa/notifications/BUILD.gn
@@ -59,7 +59,5 @@
     "xpc_mach_port.mm",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm b/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
index 8dc4ea5..aed09ff 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/ssl/ssl_client_auth_metrics.h"
 #include "chrome/browser/ssl/ssl_client_certificate_selector.h"
@@ -36,7 +37,8 @@
 
 namespace {
 
-struct TestClientCertificateDelegateResults {
+struct TestClientCertificateDelegateResults
+    : public base::SupportsWeakPtr<TestClientCertificateDelegateResults> {
   bool destroyed = false;
   bool continue_with_certificate_called = false;
   scoped_refptr<net::X509Certificate> cert;
@@ -46,17 +48,26 @@
 class TestClientCertificateDelegate
     : public content::ClientCertificateDelegate {
  public:
-  // Creates a ClientCertificateDelegate that sets |*destroyed| to true on
-  // destruction.
+  // Creates a ClientCertificateDelegate that sets |results->destroyed| to true
+  // on destruction. The |results| parameter is a WeakPtr so we avoid retaining
+  // a dangling pointer to a stack object that has since been deallocated.
   explicit TestClientCertificateDelegate(
-      TestClientCertificateDelegateResults* results)
+      base::WeakPtr<TestClientCertificateDelegateResults> results)
       : results_(results) {}
 
-  ~TestClientCertificateDelegate() override { results_->destroyed = true; }
+  ~TestClientCertificateDelegate() override {
+    if (!results_) {
+      return;
+    }
+    results_->destroyed = true;
+  }
 
   // content::ClientCertificateDelegate.
   void ContinueWithCertificate(scoped_refptr<net::X509Certificate> cert,
                                scoped_refptr<net::SSLPrivateKey> key) override {
+    if (!results_) {
+      return;
+    }
     EXPECT_FALSE(results_->continue_with_certificate_called);
     results_->cert = cert;
     results_->key = key;
@@ -65,7 +76,7 @@
   }
 
  private:
-  TestClientCertificateDelegateResults* results_;
+  base::WeakPtr<TestClientCertificateDelegateResults> results_;
 
   DISALLOW_COPY_AND_ASSIGN(TestClientCertificateDelegate);
 };
@@ -143,7 +154,7 @@
       chrome::ShowSSLClientCertificateSelector(
           web_contents, auth_requestor_->cert_request_info_.get(),
           GetTestCertificateList(),
-          std::make_unique<TestClientCertificateDelegate>(&results));
+          std::make_unique<TestClientCertificateDelegate>(results.AsWeakPtr()));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
 
@@ -174,10 +185,11 @@
       chrome::ShowSSLClientCertificateSelector(
           web_contents, auth_requestor_->cert_request_info_.get(),
           GetTestCertificateList(),
-          std::make_unique<TestClientCertificateDelegate>(&results));
+          std::make_unique<TestClientCertificateDelegate>(results.AsWeakPtr()));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
 
+  // Cancel the dialog without selecting a certificate.
   std::move(cancellation_callback).Run();
 
   base::RunLoop().RunUntilIdle();
@@ -186,10 +198,20 @@
   // The user did not close the tab, so there should be zero samples reported
   // for ClientCertSelectionResult::kUserCloseTab.
 
-  // The TestClientCertificateDelegate will not be freed (yet) because no
-  // SSLClientAuthObserver methods have been invoked. The SSLClientAuthObserver
-  // owns the ClientCertificateDelegate in a unique_ptr, so it will be freed the
-  // SSLClientAuthObserver is destroyed.
+  // A note on object lifetimes:
+  //
+  // The earlier call to ShowSSLClientCertificateSelector() created a
+  // self-owning (and self-deleting) SSLClientAuthObserver, which also owns the
+  // TestClientCertificateDelegate in this test.
+  //
+  // At this point, the TestClientCertificateDelegate's destructor has not
+  // executed because no SSLClientAuthObserver methods that trigger
+  // self-deletion have been called, e.g.  ContinueWithCertificate().
+  //
+  // Since ~TestClientCertificateDelegate() must write to |results| to indicate
+  // destruction occurred, it must have some way to know whether |results|
+  // still exists. This is why we are using a WeakPtr to |results|.
+
   EXPECT_FALSE(results.destroyed);
   EXPECT_FALSE(results.continue_with_certificate_called);
 }
@@ -207,7 +229,7 @@
       chrome::ShowSSLClientCertificateSelectorMacForTesting(
           web_contents, auth_requestor_->cert_request_info_.get(),
           GetTestCertificateList(),
-          std::make_unique<TestClientCertificateDelegate>(&results),
+          std::make_unique<TestClientCertificateDelegate>(results.AsWeakPtr()),
           base::DoNothing());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
@@ -239,7 +261,7 @@
       chrome::ShowSSLClientCertificateSelectorMacForTesting(
           web_contents, auth_requestor_->cert_request_info_.get(),
           GetTestCertificateList(),
-          std::make_unique<TestClientCertificateDelegate>(&results),
+          std::make_unique<TestClientCertificateDelegate>(results.AsWeakPtr()),
           base::DoNothing());
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
@@ -282,7 +304,7 @@
       chrome::ShowSSLClientCertificateSelector(
           web_contents, auth_requestor_->cert_request_info_.get(),
           GetTestCertificateList(),
-          std::make_unique<TestClientCertificateDelegate>(&results));
+          std::make_unique<TestClientCertificateDelegate>(results.AsWeakPtr()));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
 
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index fa641896..a7f064a 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -15,6 +15,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/accessibility/accessibility_ui.h"
+#include "chrome/browser/buildflags.h"
 #include "chrome/browser/devtools/devtools_ui_bindings.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/media/media_engagement_service.h"
@@ -96,6 +97,10 @@
 #include "ui/web_dialogs/web_dialog_ui.h"
 #include "url/gurl.h"
 
+#if BUILDFLAG(ENABLE_KALEIDOSCOPE)
+#include "chrome/browser/media/kaleidoscope/internal/constants.h"
+#endif
+
 #if BUILDFLAG(ENABLE_NACL)
 #include "chrome/browser/ui/webui/nacl_ui.h"
 #endif
@@ -872,6 +877,11 @@
       // https://crbug.com/829414
       origin.host() == chrome::kChromeUIPrintHost ||
 #endif
+#if BUILDFLAG(ENABLE_KALEIDOSCOPE)
+      // TODO(https://crbug.com/1039904): This is only for prototyping purposes.
+      // Must be removed before launch.
+      origin.host() == kKaleidoscopeContentUIHost ||
+#endif
       // https://crbug.com/831812
       origin.host() == chrome::kChromeUISyncConfirmationHost ||
       // https://crbug.com/831813
diff --git a/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc b/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc
new file mode 100644
index 0000000..06d13523
--- /dev/null
+++ b/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc
@@ -0,0 +1,110 @@
+// 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/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/web_ui_browsertest_util.h"
+#include "ipc/ipc_security_test_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/url_constants.h"
+
+// Tests embedder specific behavior of WebUIs.
+class ChromeWebUINavigationBrowserTest : public InProcessBrowserTest {
+ public:
+  ChromeWebUINavigationBrowserTest() {
+    content::WebUIControllerFactory::RegisterFactory(&factory_);
+  }
+
+  ~ChromeWebUINavigationBrowserTest() override {
+    content::WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
+  }
+
+ protected:
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+    ASSERT_TRUE(embedded_test_server()->Start());
+  }
+
+ private:
+  content::TestWebUIControllerFactory factory_;
+};
+
+// Verify that a browser check stops websites from embeding chrome:// iframes.
+// This is a copy of the DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck
+// test in content/browser/webui/web_ui_navigation_browsertest.cc. We need a
+// copy here because the browser side check is done by embedders.
+IN_PROC_BROWSER_TEST_F(ChromeWebUINavigationBrowserTest,
+                       DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  auto* main_frame = web_contents->GetMainFrame();
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  // Add iframe but don't navigate it to a chrome:// URL yet.
+  EXPECT_TRUE(content::ExecJs(main_frame,
+                              "var frame = document.createElement('iframe');\n"
+                              "document.body.appendChild(frame);\n",
+                              content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+                              1 /* world_id */));
+
+  content::RenderFrameHost* child = content::ChildFrameAt(main_frame, 0);
+  EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+  content::TestNavigationObserver observer(web_contents);
+  GURL webui_url(content::GetWebUIURL("web-ui/title1.html?noxfo=true"));
+  content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+                                     webui_url);
+  observer.Wait();
+
+  // Retrieve the RenderFrameHost again since it might have been swapped.
+  child = content::ChildFrameAt(main_frame, 0);
+  EXPECT_EQ(content::kBlockedURL, child->GetLastCommittedURL());
+}
+
+// Verify that a browser check stops websites from embeding chrome-untrusted://
+// iframes. This is a copy of the
+// DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck test in
+// content/browser/webui/web_ui_navigation_browsertest.cc. We need a copy here
+// because the browser side check is done by embedders.
+IN_PROC_BROWSER_TEST_F(
+    ChromeWebUINavigationBrowserTest,
+    DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+  auto* main_frame = web_contents->GetMainFrame();
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+  // Add iframe but don't navigate it to a chrome-untrusted:// URL yet.
+  EXPECT_TRUE(content::ExecJs(main_frame,
+                              "var frame = document.createElement('iframe');\n"
+                              "document.body.appendChild(frame);\n",
+                              content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+                              1 /* world_id */));
+
+  content::RenderFrameHost* child = content::ChildFrameAt(main_frame, 0);
+  EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+  content::TestNavigationObserver observer(web_contents);
+  content::AddUntrustedDataSource(browser()->profile(), "test-iframe-host",
+                                  /*child_src=*/base::nullopt,
+                                  /*disable_xfo=*/true);
+
+  GURL untrusted_url(
+      content::GetChromeUntrustedUIURL("test-iframe-host/title1.html"));
+  content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+                                     untrusted_url);
+  observer.Wait();
+
+  // Retrieve the RenderFrameHost again since it might have been swapped.
+  child = content::ChildFrameAt(main_frame, 0);
+  EXPECT_EQ(content::kBlockedURL, child->GetLastCommittedURL());
+}
diff --git a/chrome/browser/ui/webui/downloads/BUILD.gn b/chrome/browser/ui/webui/downloads/BUILD.gn
index fae31c3..5e66ed8 100644
--- a/chrome/browser/ui/webui/downloads/BUILD.gn
+++ b/chrome/browser/ui/webui/downloads/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojo_bindings") {
-  sources = [
-    "downloads.mojom",
-  ]
+  sources = [ "downloads.mojom" ]
 }
diff --git a/chrome/browser/win/conflicts/BUILD.gn b/chrome/browser/win/conflicts/BUILD.gn
index f453df0..4091e99 100644
--- a/chrome/browser/win/conflicts/BUILD.gn
+++ b/chrome/browser/win/conflicts/BUILD.gn
@@ -11,9 +11,7 @@
 #       to the //chrome/browser target (chrome/browser/BUILD.gn).
 
 proto_library("module_list_proto") {
-  sources = [
-    "proto/module_list.proto",
-  ]
+  sources = [ "proto/module_list.proto" ]
 }
 
 source_set("module_info") {
@@ -39,9 +37,7 @@
 
 loadable_module("conflicts_dll") {
   testonly = true
-  sources = [
-    "test/conflicts_dll.cc",
-  ]
+  sources = [ "test/conflicts_dll.cc" ]
 }
 
 source_set("unit_tests") {
diff --git a/chrome/chrome_cleaner/test/secure_dll_loading_test.cc b/chrome/chrome_cleaner/test/secure_dll_loading_test.cc
index 5b8d17c..c772f66 100644
--- a/chrome/chrome_cleaner/test/secure_dll_loading_test.cc
+++ b/chrome/chrome_cleaner/test/secure_dll_loading_test.cc
@@ -13,6 +13,7 @@
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/process/launch.h"
@@ -41,6 +42,8 @@
     ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &out_dir));
     exe_path_ = out_dir.Append(GetParam() + L".exe");
     empty_dll_path_ = out_dir.Append(chrome_cleaner::kEmptyDll);
+
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
   }
 
   base::Process LaunchProcess(bool disable_secure_dll_loading) {
@@ -68,6 +71,8 @@
         base::NumberToString(
             static_cast<int>(chrome_cleaner::ExecutionMode::kCleanup)));
 
+    chrome_cleaner::AppendTestSwitches(temp_dir_, &command_line);
+
     base::LaunchOptions options;
     options.handles_to_inherit.push_back(init_done_notifier->handle());
     child_process_logger_.UpdateLaunchOptions(&options);
@@ -114,6 +119,9 @@
   chrome_cleaner::ChildProcessLogger child_process_logger_;
   base::FilePath exe_path_;
   base::FilePath empty_dll_path_;
+
+  // Temp directory for child process log files.
+  base::ScopedTempDir temp_dir_;
 };
 
 INSTANTIATE_TEST_SUITE_P(SecureDLLLoading,
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_chromepermission_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_chromepermission_unittest.cc
index 60568eb..34f485d 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_chromepermission_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_chromepermission_unittest.cc
@@ -15,6 +15,10 @@
 
 namespace extensions {
 
+namespace {
+const char kChromeUntrustedTestURL[] = "chrome-untrusted://test/";
+}  // namespace
+
 namespace errors = manifest_errors;
 
 typedef ChromeManifestTest ChromePermissionManifestTest;
@@ -26,6 +30,13 @@
                            chrome::kChromeUINewTabURL));
 }
 
+TEST_F(ChromePermissionManifestTest, ChromeUntrustedURLPermissionInvalid) {
+  LoadAndExpectWarning(
+      "permission_chrome_untrusted_url_invalid.json",
+      ErrorUtils::FormatErrorMessage(errors::kPermissionUnknownOrMalformed,
+                                     kChromeUntrustedTestURL));
+}
+
 TEST_F(ChromePermissionManifestTest, ChromeURLPermissionAllowedWithFlag) {
   // Ignore the policy delegate for this test.
   PermissionsData::SetPolicyDelegate(NULL);
@@ -41,6 +52,20 @@
       << error;
 }
 
+// Tests that extensions can't access chrome-untrusted:// even with the
+// kExtensionsOnChromeURLs flag enabled.
+TEST_F(ChromePermissionManifestTest,
+       ChromeUntrustedURLPermissionDisallowedWithFlag) {
+  // Ignore the policy delegate for this test.
+  PermissionsData::SetPolicyDelegate(nullptr);
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kExtensionsOnChromeURLs);
+  LoadAndExpectWarning(
+      "permission_chrome_untrusted_url_invalid.json",
+      ErrorUtils::FormatErrorMessage(errors::kPermissionUnknownOrMalformed,
+                                     kChromeUntrustedTestURL));
+}
+
 TEST_F(ChromePermissionManifestTest,
        ChromeResourcesPermissionValidOnlyForComponents) {
   LoadAndExpectWarning("permission_chrome_resources_url.json",
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index 55f9005..8a80e8af 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -47,6 +47,8 @@
 
 const char kAllHostsPermission[] = "*://*/*";
 
+const char kChromeUntrustedURL[] = "chrome-untrusted://test/index.html";
+
 GURL GetFaviconURL(const char* path) {
   GURL::Replacements replace_path;
   replace_path.SetPathStr(path);
@@ -87,7 +89,8 @@
 
 // Checks that urls are properly restricted for the given extension.
 void CheckRestrictedUrls(const Extension* extension,
-                         bool block_chrome_urls) {
+                         bool block_chrome_urls,
+                         bool block_chrome_untrusted_urls) {
   // We log the name so we know _which_ extension failed here.
   const std::string& name = extension->name();
   const GURL chrome_settings_url(chrome::kChromeUISettingsURL);
@@ -95,6 +98,7 @@
   const GURL google_url("https://www.google.com/");
   const GURL self_url("chrome-extension://" + extension->id() + "/foo.html");
   const GURL invalid_url("chrome-debugger://foo/bar.html");
+  const GURL chrome_untrusted_url(kChromeUntrustedURL);
 
   std::string error;
   EXPECT_EQ(block_chrome_urls, extension->permissions_data()->IsRestrictedUrl(
@@ -114,6 +118,14 @@
   else
     EXPECT_TRUE(error.empty()) << name;
 
+  EXPECT_EQ(block_chrome_untrusted_urls,
+            extension->permissions_data()->IsRestrictedUrl(chrome_untrusted_url,
+                                                           &error));
+  if (block_chrome_untrusted_urls)
+    EXPECT_EQ(manifest_errors::kCannotAccessPage, error) << name;
+  else
+    EXPECT_TRUE(error.empty()) << name;
+
   // Google should never be a restricted url.
   error.clear();
   EXPECT_FALSE(
@@ -304,20 +316,26 @@
       GetExtensionWithHostPermission("normal_extension",
                                      kAllHostsPermission,
                                      Manifest::INTERNAL);
-  // Chrome urls should be blocked for normal extensions.
-  CheckRestrictedUrls(extension.get(), true);
+  // Chrome and chrome-untrusted:// urls should be blocked for normal
+  // extensions.
+  CheckRestrictedUrls(extension.get(), /*block_chrome_urls=*/true,
+                      /*block_chrome_untrusted_urls=*/true);
 
   scoped_refptr<const Extension> component =
       GetExtensionWithHostPermission("component",
                                      kAllHostsPermission,
                                      Manifest::COMPONENT);
-  // Chrome urls should be accessible by component extensions.
-  CheckRestrictedUrls(component.get(), false);
+  // Chrome and chrome-untrusted:// urls should be accessible by component
+  // extensions.
+  CheckRestrictedUrls(component.get(), /*block_chrome_urls=*/false,
+                      /*block_chrome_untrusted_urls=*/false);
 
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kExtensionsOnChromeURLs);
-  // Enabling the switch should allow all extensions to access chrome urls.
-  CheckRestrictedUrls(extension.get(), false);
+  // Enabling the switch should allow all extensions to access chrome urls but
+  // not chrome-untrusted:// urls.
+  CheckRestrictedUrls(extension.get(), /*block_chrome_urls=*/false,
+                      /*block_chrome_untrusted_urls=*/true);
 }
 
 TEST(PermissionsDataTest, GetPermissionMessages_ManyAPIPermissions) {
@@ -391,6 +409,7 @@
                       crx_file::id_util::GenerateIdForPath(
                           base::FilePath(FILE_PATH_LITERAL("foo")))),
         settings_url(chrome::kChromeUISettingsURL),
+        chrome_untrusted_url(kChromeUntrustedURL),
         about_flags_url("about:flags") {
     urls_.insert(http_url);
     urls_.insert(http_url_with_path);
@@ -402,6 +421,7 @@
     urls_.insert(favicon_url);
     urls_.insert(extension_url);
     urls_.insert(settings_url);
+    urls_.insert(chrome_untrusted_url);
     urls_.insert(about_flags_url);
     // Ignore the policy delegate for this test.
     PermissionsData::SetPolicyDelegate(NULL);
@@ -477,6 +497,7 @@
   // URLs that regular extensions should never get access to.
   const GURL extension_url;
   const GURL settings_url;
+  const GURL chrome_untrusted_url;
   const GURL about_flags_url;
 
  private:
@@ -501,6 +522,8 @@
             GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), extension_url));
@@ -519,6 +542,8 @@
 
   EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url));
   EXPECT_FALSE(
+      extension->permissions_data()->HasHostPermission(chrome_untrusted_url));
+  EXPECT_FALSE(
       extension->permissions_data()->HasHostPermission(about_flags_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
 
@@ -529,6 +554,8 @@
   EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
             GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
@@ -550,6 +577,8 @@
                 "chrome://*/"),
             warnings[0].message);
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
 
@@ -557,6 +586,8 @@
   extension = LoadManifestStrict("script_and_capture",
       "extension_chrome_favicon_wildcard.json");
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
 
@@ -580,6 +611,8 @@
             GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
 
   // Component extensions should only get access to what they ask for.
   extension = LoadManifest("script_and_capture",
@@ -589,6 +622,8 @@
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), extension_url));
@@ -610,6 +645,8 @@
             GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(
       ALLOWED_SCRIPT_AND_CAPTURE,
       GetExtensionAccess(extension.get(), favicon_url));  // chrome:// requested
@@ -623,9 +660,11 @@
   EXPECT_TRUE(IsAllowedScript(extension.get(), https_url));
   EXPECT_FALSE(IsAllowedScript(extension.get(), within_extension_url));
   EXPECT_FALSE(IsAllowedScript(extension.get(), extension_url));
+  EXPECT_FALSE(IsAllowedScript(extension.get(), chrome_untrusted_url));
 
   const PermissionsData* permissions_data = extension->permissions_data();
   EXPECT_FALSE(permissions_data->HasHostPermission(settings_url));
+  EXPECT_FALSE(permissions_data->HasHostPermission(chrome_untrusted_url));
   EXPECT_FALSE(permissions_data->HasHostPermission(about_flags_url));
   EXPECT_TRUE(permissions_data->HasHostPermission(favicon_url));
 
@@ -636,6 +675,8 @@
   EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
             GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
@@ -655,6 +696,8 @@
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
             GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
@@ -664,6 +707,8 @@
   extension = LoadManifestStrict("script_and_capture",
                                  "extension_chrome_favicon_wildcard.json");
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(ALLOWED_SCRIPT_ONLY,
             GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
@@ -673,6 +718,8 @@
   extension =
       LoadManifestStrict("script_and_capture", "extension_http_favicon.json");
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
 
   // Component extensions with <all_urls> should get everything except for
@@ -687,6 +734,8 @@
             GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
 
   // Component extensions should only get access to what they ask for.
   extension =
@@ -696,6 +745,8 @@
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), https_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), file_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), settings_url));
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(extension.get(), chrome_untrusted_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), favicon_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), about_flags_url));
   EXPECT_EQ(DISALLOWED, GetExtensionAccess(extension.get(), extension_url));
@@ -822,6 +873,38 @@
             GetExtensionAccess(active_tab.get(), settings_url, kTabId));
 }
 
+// chrome-untrusted:// can never be captured.
+TEST_F(ExtensionScriptAndCaptureVisibleTest, CaptureChromeUntrustedURLs) {
+  const int kTabId = 42;
+  scoped_refptr<const Extension> all_urls =
+      ExtensionBuilder("all urls").AddPermission("<all_urls>").Build();
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(all_urls.get(), chrome_untrusted_url, kTabId));
+
+  scoped_refptr<const Extension> active_tab =
+      ExtensionBuilder("active tab").AddPermission("activeTab").Build();
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(active_tab.get(), chrome_untrusted_url, kTabId));
+
+  {
+    APIPermissionSet tab_api_permissions;
+    tab_api_permissions.insert(APIPermission::kTab);
+    URLPatternSet tab_hosts;
+    // Even extensions that can execute scripts everywhere, e.g. component
+    // extensions, are not able to capture chrome-untrusted://.
+    tab_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(
+                            /*can_execute_script_everywhere=*/true),
+                        chrome_untrusted_url.GetOrigin());
+    PermissionSet tab_permissions(std::move(tab_api_permissions),
+                                  ManifestPermissionSet(), tab_hosts.Clone(),
+                                  tab_hosts.Clone());
+    active_tab->permissions_data()->UpdateTabSpecificPermissions(
+        kTabId, tab_permissions);
+  }
+  EXPECT_EQ(DISALLOWED,
+            GetExtensionAccess(active_tab.get(), chrome_untrusted_url, kTabId));
+}
+
 TEST_F(ExtensionScriptAndCaptureVisibleTest, CaptureFileURLs) {
   const int kTabId = 42;
   scoped_refptr<const Extension> all_urls =
@@ -1272,6 +1355,33 @@
   }
 }
 
+// TODO(crbug.com/1041309): Add support for capturing chrome-untrusted://.
+TEST_F(CaptureVisiblePageTest, ChromeUntrustedSchemeNotCaptured) {
+  const GURL chrome_untrusted_url(kChromeUntrustedURL);
+
+  SCOPED_TRACE(chrome_untrusted_url.spec());
+  EXPECT_FALSE(CanCapture(all_urls(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kActiveTabOrAllUrls));
+
+  EXPECT_FALSE(CanCapture(active_tab(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kActiveTabOrAllUrls));
+  GrantActiveTab(active_tab(), chrome_untrusted_url);
+  EXPECT_FALSE(CanCapture(active_tab(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kActiveTabOrAllUrls));
+  ClearActiveTab(active_tab());
+  EXPECT_FALSE(CanCapture(active_tab(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kActiveTabOrAllUrls));
+
+  EXPECT_FALSE(CanCapture(page_capture(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kPageCapture));
+  GrantActiveTab(page_capture(), chrome_untrusted_url);
+  EXPECT_FALSE(CanCapture(page_capture(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kPageCapture));
+  ClearActiveTab(page_capture());
+  EXPECT_FALSE(CanCapture(page_capture(), chrome_untrusted_url,
+                          extensions::CaptureRequirement::kPageCapture));
+}
+
 TEST_F(CaptureVisiblePageTest, SelfExtensionURLs) {
   auto get_filesystem_url_for_extension = [](const Extension& extension) {
     return GURL(base::StringPrintf("filesystem:chrome-extension://%s/foo",
diff --git a/chrome/common/win/BUILD.gn b/chrome/common/win/BUILD.gn
index 434c1d74..e0a3530 100644
--- a/chrome/common/win/BUILD.gn
+++ b/chrome/common/win/BUILD.gn
@@ -13,18 +13,14 @@
     ":eventlog_provider",
   ]
 
-  sources = [
-    "eventlog_messages.mc",
-  ]
+  sources = [ "eventlog_messages.mc" ]
 
   user_mode_logging = false
   compile_generated_code = false
 }
 
 process_version_rc_template("eventlog_provider_dll_version") {
-  sources = [
-    "eventlog_provider.ver",
-  ]
+  sources = [ "eventlog_provider.ver" ]
   output = "$target_gen_dir/eventlog_provider_dll_version.rc"
 }
 
diff --git a/chrome/service/BUILD.gn b/chrome/service/BUILD.gn
index 6775dd4a..e6d3a1d 100644
--- a/chrome/service/BUILD.gn
+++ b/chrome/service/BUILD.gn
@@ -75,9 +75,7 @@
     "//third_party/webrtc_overrides:webrtc_component",
   ]
 
-  public_deps = [
-    "//chrome/common:service_process_mojom",
-  ]
+  public_deps = [ "//chrome/common:service_process_mojom" ]
 
   if (use_cups) {
     sources += [ "cloud_print/print_system_cups.cc" ]
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom
index 6eb0f3f6..ea1e1b2 100644
--- a/chrome/services/app_service/public/mojom/types.mojom
+++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -165,18 +165,23 @@
   bool is_placeholder_icon;
 };
 
+// Enumeration of possible app launch sources.
+// Note the enumeration is used in UMA histogram so entries
+// should not be re-ordered or removed.
 enum LaunchSource {
-  kUnknown,
-  kFromAppListGrid,              // Grid of apps, not the search box.
-  kFromAppListGridContextMenu,   // Grid of apps; context menu.
-  kFromAppListQuery,             // Query-dependent results (larger icons).
-  kFromAppListQueryContextMenu,  // Query-dependent results; context menu.
-  kFromAppListRecommendation,    // Query-less recommendations (smaller icons).
-  kFromParentalControls,         // Parental Controls Settings Section.
-  kFromShelf,                    // Shelf.
-  kFromFileManager,              // FileManager.
-  kFromLink,                     // Left-licking on links in the browser.
-  kFromOmnibox,                  // Enter URL in the Omnibox in the browser.
+  kUnknown = 0,
+  kFromAppListGrid = 1,             // Grid of apps, not the search box.
+  kFromAppListGridContextMenu = 2,  // Grid of apps; context menu.
+  kFromAppListQuery = 3,            // Query-dependent results (larger icons).
+  kFromAppListQueryContextMenu = 4, // Query-dependent results; context menu.
+  kFromAppListRecommendation = 5,   // Query-less recommendations (smaller
+                                    // icons).
+  kFromParentalControls = 6,        // Parental Controls Settings Section.
+  kFromShelf = 7,                   // Shelf.
+  kFromFileManager = 8,             // FileManager.
+  kFromLink = 9,                    // Left-licking on links in the browser.
+  kFromOmnibox = 10,                // Enter URL in the Omnibox in the browser.
+  kFromChromeInternal = 11,         // Chrome internal call.
 };
 
 enum TriState {
diff --git a/chrome/services/util_win/BUILD.gn b/chrome/services/util_win/BUILD.gn
index 0a6e6ce..5e29596c 100644
--- a/chrome/services/util_win/BUILD.gn
+++ b/chrome/services/util_win/BUILD.gn
@@ -29,9 +29,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "av_products_unittest.cc",
-  ]
+  sources = [ "av_products_unittest.cc" ]
 
   deps = [
     ":lib",
diff --git a/chrome/services/util_win/public/mojom/BUILD.gn b/chrome/services/util_win/public/mojom/BUILD.gn
index 3165c02..9a6444c 100644
--- a/chrome/services/util_win/public/mojom/BUILD.gn
+++ b/chrome/services/util_win/public/mojom/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "util_win.mojom",
-  ]
+  sources = [ "util_win.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 e049098..31d58e8 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -78,19 +78,13 @@
 if (is_android) {
   android_library("test_support_java") {
     testonly = true
-    deps = [
-      "//chrome/android:chrome_all_java",
-    ]
-    sources = [
-      "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java",
-    ]
+    deps = [ "//chrome/android:chrome_all_java" ]
+    sources = [ "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java" ]
   }
 
   generate_jni("test_support_jni_headers") {
     testonly = true
-    sources = [
-      "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java",
-    ]
+    sources = [ "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java" ]
   }
 }
 
@@ -412,9 +406,7 @@
 
 group("telemetry_gpu_integration_test") {
   testonly = true
-  deps = [
-    "//tools/perf/chrome_telemetry_build:telemetry_chrome_test",
-  ]
+  deps = [ "//tools/perf/chrome_telemetry_build:telemetry_chrome_test" ]
 
   data = [
     # For isolate contract.
@@ -476,9 +468,7 @@
     "//tools/perf/chrome_telemetry_build:telemetry_chrome_test_without_chrome",
   ]
 
-  data = [
-    "//content/test/gpu/",
-  ]
+  data = [ "//content/test/gpu/" ]
 }
 
 if (is_win) {
@@ -488,9 +478,7 @@
       "../browser/ui/startup/credential_provider_signin_dialog_win_test_data.cc",
       "../browser/ui/startup/credential_provider_signin_dialog_win_test_data.h",
     ]
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
   }
 }
 
@@ -528,9 +516,7 @@
       "//testing/android/native_test:native_test_support",
     ]
 
-    data_deps = [
-      "//testing/buildbot/filters:android_browsertests_filters",
-    ]
+    data_deps = [ "//testing/buildbot/filters:android_browsertests_filters" ]
 
     sources = [
       "../browser/engagement/important_sites_util_browsertest.cc",
@@ -574,9 +560,7 @@
       "base/android/android_browser_test.cc",
       "base/android/android_browser_test.h",
     ]
-    public_deps = [
-      "//content/test:test_support",
-    ]
+    public_deps = [ "//content/test:test_support" ]
     deps = [
       "//chrome/browser",
       "//content/public/browser",
@@ -647,9 +631,7 @@
   testonly = true
   sources = []
 
-  deps = [
-    ":test_support",
-  ]
+  deps = [ ":test_support" ]
 
   if (is_chromeos) {
     sources += [ "base/browser_tests_main_chromeos.cc" ]
@@ -1353,6 +1335,7 @@
       "../browser/ui/webui/bookmarks/bookmarks_browsertest.cc",
       "../browser/ui/webui/bookmarks/bookmarks_browsertest.h",
       "../browser/ui/webui/chrome_url_data_manager_browsertest.cc",
+      "../browser/ui/webui/chrome_webui_navigation_browsertest.cc",
       "../browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc",
       "../browser/ui/webui/chromeos/account_migration_welcome_ui_test.h",
       "../browser/ui/webui/chromeos/bluetooth_pairing_dialog_browsertest-inl.h",
@@ -2804,9 +2787,7 @@
 
   group("browser_tests_apprtc") {
     testonly = true
-    data_deps = [
-      ":browser_tests",
-    ]
+    data_deps = [ ":browser_tests" ]
     data = [
       "//third_party/webrtc/rtc_tools/testing/browsertest/apprtc/out/app_engine/",
       "//third_party/webrtc/rtc_tools/testing/browsertest/apprtc/temp/google-cloud-sdk/",
@@ -2820,9 +2801,7 @@
   }
 
   sizes_test("chrome_sizes") {
-    data_deps = [
-      "//chrome",
-    ]
+    data_deps = [ "//chrome" ]
     if (is_win) {
       data_deps += [ "//chrome/installer/mini_installer" ]
     }
@@ -2831,9 +2810,7 @@
 
 group("telemetry_perf_unittests") {
   testonly = true
-  deps = [
-    "//tools/perf:perf",
-  ]
+  deps = [ "//tools/perf:perf" ]
 
   data = [
     # For isolate contract.
@@ -2852,9 +2829,7 @@
 
 group("telemetry_perf_tests") {
   testonly = true
-  deps = [
-    "//tools/perf/:perf",
-  ]
+  deps = [ "//tools/perf/:perf" ]
 
   data = [
     # Needed for isolate script to execute.
@@ -2865,13 +2840,9 @@
 
 group("ct_telemetry_perf_tests_without_chrome") {
   testonly = true
-  deps = [
-    "//tools/perf/:perf_without_chrome",
-  ]
+  deps = [ "//tools/perf/:perf_without_chrome" ]
 
-  data = [
-    "//tools/perf/contrib/cluster_telemetry/",
-  ]
+  data = [ "//tools/perf/contrib/cluster_telemetry/" ]
 
   data_deps = [
     "//components/subresource_filter/tools:index_ruleset",
@@ -2883,9 +2854,7 @@
 # is done.
 group("performance_test_suite") {
   testonly = true
-  deps = [
-    "//chrome/test:telemetry_perf_tests",
-  ]
+  deps = [ "//chrome/test:telemetry_perf_tests" ]
 
   data_deps = [
     "//base:base_perftests",
@@ -2920,16 +2889,12 @@
 # //testing/buildbot/gn_isolate_map.pyl
 group("performance_webview_test_suite") {
   testonly = true
-  deps = [
-    "//chrome/test:performance_test_suite",
-  ]
+  deps = [ "//chrome/test:performance_test_suite" ]
 }
 
 group("performance_weblayer_test_suite") {
   testonly = true
-  deps = [
-    "//chrome/test:performance_test_suite",
-  ]
+  deps = [ "//chrome/test:performance_test_suite" ]
 }
 
 # Difference between this and telemetry_perf_tests is that this runs a devil
@@ -2937,16 +2902,12 @@
 # //testing/buildbot/gn_isolate_map.pyl
 group("telemetry_perf_webview_tests") {
   testonly = true
-  deps = [
-    "//chrome/test:telemetry_perf_tests",
-  ]
+  deps = [ "//chrome/test:telemetry_perf_tests" ]
 }
 
 group("angle_perftests") {
   testonly = true
-  data_deps = [
-    "//testing:run_perf_test",
-  ]
+  data_deps = [ "//testing:run_perf_test" ]
   if (is_win || is_linux || is_android) {
     data_deps += [ "//third_party/angle/src/tests:angle_perftests" ]
   }
@@ -2954,9 +2915,7 @@
 
 group("dawn_perf_tests") {
   testonly = true
-  data_deps = [
-    "//testing:run_perf_test",
-  ]
+  data_deps = [ "//testing:run_perf_test" ]
   if (use_dawn) {
     data_deps += [ "//third_party/dawn:dawn_perf_tests_temp_group" ]
   }
@@ -2964,9 +2923,8 @@
 
 if (is_mac) {
   mojom("firefox_importer_interface") {
-    sources = [
-      "../utility/importer/firefox_importer_unittest_utils_mac.mojom",
-    ]
+    sources =
+        [ "../utility/importer/firefox_importer_unittest_utils_mac.mojom" ]
     public_deps = [
       "//components/autofill/core/common/mojom:mojo_types",
       "//mojo/public/mojom/base",
@@ -5381,9 +5339,7 @@
 
 static_library("test_support_unit") {
   testonly = true
-  sources = [
-    "base/run_all_unittests.cc",
-  ]
+  sources = [ "base/run_all_unittests.cc" ]
 
   public_deps = [
     ":test_support",
@@ -5397,9 +5353,7 @@
   deps = []
 
   if (is_win) {
-    deps = [
-      "//chrome/install_static/test:test_support",
-    ]
+    deps = [ "//chrome/install_static/test:test_support" ]
   }
 
   if (is_chromeos) {
@@ -5494,9 +5448,7 @@
   import("//third_party/protobuf/proto_library.gni")
 
   proto_library("test_proto") {
-    sources = [
-      "../common/safe_browsing/ipc_protobuf_message_test.proto",
-    ]
+    sources = [ "../common/safe_browsing/ipc_protobuf_message_test.proto" ]
   }
 
   if (is_chromeos) {
@@ -6132,9 +6084,7 @@
       "../browser/sync/test/integration/wallet_helper.cc",
       "../browser/sync/test/integration/wallet_helper.h",
     ]
-    public_deps = [
-      "//chrome/browser",
-    ]
+    public_deps = [ "//chrome/browser" ]
     deps = [
       ":test_support",
       "//base",
@@ -6375,9 +6325,7 @@
 
   # Executable to measure time to load libraries.
   test("load_library_perf_tests") {
-    sources = [
-      "../browser/load_library_perf_test.cc",
-    ]
+    sources = [ "../browser/load_library_perf_test.cc" ]
 
     # This test deliberately does not depend in chrome's test support targets.
     # This is a small test and Chrome's test support targets bring in the
@@ -6392,9 +6340,7 @@
       "//third_party/widevine/cdm:buildflags",
     ]
 
-    data_deps = [
-      "//testing:run_perf_test",
-    ]
+    data_deps = [ "//testing:run_perf_test" ]
 
     if (enable_library_cdms) {
       deps += [ "//media/cdm:cdm_paths" ]
@@ -6409,9 +6355,7 @@
   }
 
   test("ntp_render_browsertests") {
-    sources = [
-      "../browser/ui/search/local_ntp_render_browsertest.cc",
-    ]
+    sources = [ "../browser/ui/search/local_ntp_render_browsertest.cc" ]
 
     configs += [ "//build/config:precompiled_headers" ]
 
@@ -6474,9 +6418,7 @@
     ]
 
     if (is_linux || is_win) {
-      data_deps = [
-        "//chrome:packed_resources",
-      ]
+      data_deps = [ "//chrome:packed_resources" ]
     }
 
     defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
@@ -6540,9 +6482,7 @@
 
   group("telemetry_unittests") {
     testonly = true
-    deps = [
-      "//tools/perf/chrome_telemetry_build:telemetry_chrome_test",
-    ]
+    deps = [ "//tools/perf/chrome_telemetry_build:telemetry_chrome_test" ]
 
     data = [
       "//third_party/catapult/telemetry/telemetry/internal/bin/",
@@ -6557,9 +6497,7 @@
 
   group("telemetry_gpu_unittests_run") {
     testonly = true
-    deps = [
-      ":telemetry_gpu_unittests",
-    ]
+    deps = [ ":telemetry_gpu_unittests" ]
   }
 
   group("telemetry_gpu_unittests") {
@@ -6616,9 +6554,7 @@
 
 if (is_chromeos) {
   fuzzer_test("tokenized_string_fuzzer") {
-    sources = [
-      "../common/string_matching/tokenized_string_fuzzer.cc",
-    ]
+    sources = [ "../common/string_matching/tokenized_string_fuzzer.cc" ]
     deps = [
       "//base",
       "//chrome/common/string_matching",
@@ -6628,9 +6564,7 @@
 
 if (is_win) {
   test("pixel_browser_tests") {
-    sources = [
-      "pixel/demo/skia_gold_demo_pixeltest.cc",
-    ]
+    sources = [ "pixel/demo/skia_gold_demo_pixeltest.cc" ]
     configs += [ "//build/config:precompiled_headers" ]
     defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
     deps = [
@@ -6638,18 +6572,12 @@
       ":test_support",
     ]
     if (is_win) {
-      data = [
-        "//tools/skia_goldctl/goldctl.exe",
-      ]
+      data = [ "//tools/skia_goldctl/goldctl.exe" ]
     } else {
-      data = [
-        "//tools/skia_goldctl/goldctl",
-      ]
+      data = [ "//tools/skia_goldctl/goldctl" ]
     }
     if (!is_mac) {
-      data_deps = [
-        "//chrome:packed_resources",
-      ]
+      data_deps = [ "//chrome:packed_resources" ]
     }
   }
 }
@@ -6695,9 +6623,7 @@
 
   proto_library("consistency_golden_proto") {
     visibility = [ ":usage_time_limit_unittests" ]
-    sources = [
-      "../browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto",
-    ]
+    sources = [ "../browser/chromeos/child_accounts/time_limit_consistency_test/goldens/consistency_golden.proto" ]
     generate_python = false
   }
 }
@@ -6705,9 +6631,7 @@
 if (is_mac || is_win || is_android) {
   group("rendering_representative_perf_tests") {
     testonly = true
-    deps = [
-      "//tools/perf/chrome_telemetry_build:telemetry_chrome_test",
-    ]
+    deps = [ "//tools/perf/chrome_telemetry_build:telemetry_chrome_test" ]
     data = [
       "//build/android/pylib",
       "//chrome/test/data/perf",
@@ -6724,9 +6648,7 @@
 if (is_win) {
   test("delayloads_unittests") {
     output_name = "delayloads_unittests"
-    sources = [
-      "delayload/delayloads_unittest.cc",
-    ]
+    sources = [ "delayload/delayloads_unittest.cc" ]
 
     defines = []
     if (is_multi_dll_chrome) {
@@ -6747,9 +6669,7 @@
     # the //chrome target to bundle up both initial/chrome.exe and chrome.exe.
     # As a workaround, explicitly include a data dep on just chrome.exe, and
     # add //chrome to deps above to make sure it's been built.
-    data = [
-      "$root_out_dir/chrome.exe",
-    ]
+    data = [ "$root_out_dir/chrome.exe" ]
 
     # Don't want the test-specific dependencies to affect load tests.
     # In particular, a few system DLLs cause user32 to be loaded, which is bad.
@@ -6794,9 +6714,7 @@
 
   test("xr_browser_tests_binary") {
     testonly = true
-    deps = [
-      ":xr_browser_tests_common",
-    ]
+    deps = [ ":xr_browser_tests_common" ]
 
     # Most tests require VR to be enabled.
     if (enable_vr) {
@@ -6847,9 +6765,7 @@
     ]
 
     if (!is_mac) {
-      data_deps = [
-        "//chrome:packed_resources",
-      ]
+      data_deps = [ "//chrome:packed_resources" ]
     }
   }
 
@@ -6857,11 +6773,7 @@
   # once the functionality is available on all platforms.
   copy("xr_browser_tests_runner") {
     testonly = true
-    sources = [
-      "//chrome/browser/vr/test/run_xr_browser_tests.py",
-    ]
-    outputs = [
-      "$root_out_dir/run_xr_browser_tests.py",
-    ]
+    sources = [ "//chrome/browser/vr/test/run_xr_browser_tests.py" ]
+    outputs = [ "$root_out_dir/run_xr_browser_tests.py" ]
   }
 }
diff --git a/chrome/test/base/in_process_browser_test_browsertest.cc b/chrome/test/base/in_process_browser_test_browsertest.cc
index c8f712a..cb2ed68 100644
--- a/chrome/test/base/in_process_browser_test_browsertest.cc
+++ b/chrome/test/base/in_process_browser_test_browsertest.cc
@@ -21,6 +21,7 @@
 #include "content/public/common/content_switches.h"
 #include "net/base/filename_util.h"
 #include "net/base/net_errors.h"
+#include "net/dns/public/resolve_error_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -44,7 +45,8 @@
   explicit LoadFailObserver(content::WebContents* contents)
       : content::WebContentsObserver(contents),
         failed_load_(false),
-        error_code_(net::OK) { }
+        error_code_(net::OK),
+        resolve_error_info_(net::ResolveErrorInfo(net::OK)) {}
 
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override {
@@ -53,16 +55,21 @@
 
     failed_load_ = true;
     error_code_ = navigation_handle->GetNetErrorCode();
+    resolve_error_info_ = navigation_handle->GetResolveErrorInfo();
     validated_url_ = navigation_handle->GetURL();
   }
 
   bool failed_load() const { return failed_load_; }
   net::Error error_code() const { return error_code_; }
+  net::ResolveErrorInfo resolve_error_info() const {
+    return resolve_error_info_;
+  }
   const GURL& validated_url() const { return validated_url_; }
 
  private:
   bool failed_load_;
   net::Error error_code_;
+  net::ResolveErrorInfo resolve_error_info_;
   GURL validated_url_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadFailObserver);
@@ -85,6 +92,7 @@
     ui_test_utils::NavigateToURL(browser(), url);
     EXPECT_TRUE(observer.failed_load());
     EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, observer.error_code());
+    EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, observer.resolve_error_info().error);
     EXPECT_EQ(url, observer.validated_url());
   }
 }
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/reverse_relations.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/reverse_relations.js
index e9f4755..afe7bf5 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/reverse_relations.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/reverse_relations.js
@@ -6,7 +6,7 @@
   function testDetailsReverseRelations() {
     var detailsFrom = rootNode.find({attributes: {name: 'DetailsFrom'}});
     var detailsTo = rootNode.find({attributes: {name: 'DetailsTo'}});
-    assertEq(detailsFrom.details, detailsTo);
+    assertEq(detailsFrom.details[0], detailsTo);
     assertEq(detailsTo.detailsFor.length, 1);
     assertEq(detailsTo.detailsFor[0], detailsFrom);
     chrome.test.succeed();
diff --git a/chrome/test/data/extensions/manifest_tests/permission_chrome_untrusted_url_invalid.json b/chrome/test/data/extensions/manifest_tests/permission_chrome_untrusted_url_invalid.json
new file mode 100644
index 0000000..70783d2
--- /dev/null
+++ b/chrome/test/data/extensions/manifest_tests/permission_chrome_untrusted_url_invalid.json
@@ -0,0 +1,8 @@
+{
+  "name": "test",
+  "manifest_version": 2,
+  "version": "1",
+  "permissions": [
+    "chrome-untrusted://test/"
+  ]
+}
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn
index c894251..f0fc33e 100644
--- a/chrome/test/media_router/BUILD.gn
+++ b/chrome/test/media_router/BUILD.gn
@@ -148,11 +148,7 @@
       "internal/",
       "telemetry/",
     ]
-    deps = [
-      "//tools/perf:perf",
-    ]
-    data_deps = [
-      "//tools/perf/contrib/media_router_benchmarks:telemetry_extension_resources",
-    ]
+    deps = [ "//tools/perf:perf" ]
+    data_deps = [ "//tools/perf/contrib/media_router_benchmarks:telemetry_extension_resources" ]
   }
 }
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 7bc18b97..66ac32f 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1313,7 +1313,7 @@
   network::DnsLookupResult result2 =
       network::BlockingDnsLookup(network_context, kHostPortPair,
                                  std::move(params), net::NetworkIsolationKey());
-  EXPECT_EQ(net::ERR_DNS_CACHE_MISS, result2.error);
+  EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, result2.error);
 }
 
 // HostResolver and HostResolverPrivate tests. The PPAPI code used by these
diff --git a/chrome/tools/convert_dict/BUILD.gn b/chrome/tools/convert_dict/BUILD.gn
index 089b379..ee89913f 100644
--- a/chrome/tools/convert_dict/BUILD.gn
+++ b/chrome/tools/convert_dict/BUILD.gn
@@ -25,9 +25,7 @@
   # Production code shouldn't be depending on this.
   testonly = true
 
-  sources = [
-    "convert_dict.cc",
-  ]
+  sources = [ "convert_dict.cc" ]
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
   deps = [
     ":lib",
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index a3da19b..810d4e7 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -592,18 +592,12 @@
   }
 
   java_cpp_enum("java_enums") {
-    sources = [
-      "cast_content_window.h",
-    ]
+    sources = [ "cast_content_window.h" ]
   }
 }
 
 cast_source_set("web_contents_provider") {
-  sources = [
-    "webview/web_contents_provider.h",
-  ]
+  sources = [ "webview/web_contents_provider.h" ]
 
-  deps = [
-    "//content/public/browser",
-  ]
+  deps = [ "//content/public/browser" ]
 }
diff --git a/chromecast/browser/bluetooth/public/mojom/BUILD.gn b/chromecast/browser/bluetooth/public/mojom/BUILD.gn
index 5340c0d..e0763737 100644
--- a/chromecast/browser/bluetooth/public/mojom/BUILD.gn
+++ b/chromecast/browser/bluetooth/public/mojom/BUILD.gn
@@ -7,7 +7,5 @@
 # TODO(slan): This likely falls in the class of interfaces that are provided by
 # the browser. We should consider putting these in a common location.
 mojom("mojom") {
-  sources = [
-    "web_bluetooth.mojom",
-  ]
+  sources = [ "web_bluetooth.mojom" ]
 }
diff --git a/chromecast/browser/general_audience_browsing/mojom/BUILD.gn b/chromecast/browser/general_audience_browsing/mojom/BUILD.gn
index 740525b3..6d6e19e 100644
--- a/chromecast/browser/general_audience_browsing/mojom/BUILD.gn
+++ b/chromecast/browser/general_audience_browsing/mojom/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "general_audience_browsing.mojom",
-  ]
+  sources = [ "general_audience_browsing.mojom" ]
 }
diff --git a/chromecast/browser/webview/proto/BUILD.gn b/chromecast/browser/webview/proto/BUILD.gn
index 78f5860..3a1fdd1 100644
--- a/chromecast/browser/webview/proto/BUILD.gn
+++ b/chromecast/browser/webview/proto/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/grpc/grpc_library.gni")
 
 cc_grpc_library("proto") {
-  sources = [
-    "webview.proto",
-  ]
+  sources = [ "webview.proto" ]
 }
diff --git a/chromeos/components/proximity_auth/BUILD.gn b/chromeos/components/proximity_auth/BUILD.gn
index b60ec24..219086d 100644
--- a/chromeos/components/proximity_auth/BUILD.gn
+++ b/chromeos/components/proximity_auth/BUILD.gn
@@ -78,9 +78,7 @@
     "mock_proximity_auth_client.h",
   ]
 
-  public_deps = [
-    ":proximity_auth",
-  ]
+  public_deps = [ ":proximity_auth" ]
 
   deps = [
     "//base",
@@ -135,9 +133,7 @@
 # Note: This is a convenience target for ease of rapid iteration during
 # development. It is not executed on any try or build bots.
 test("proximity_auth_unittests") {
-  sources = [
-    "run_all_unittests.cc",
-  ]
+  sources = [ "run_all_unittests.cc" ]
   deps = [
     ":unit_tests",
     "//base",
diff --git a/chromeos/components/proximity_auth/public/mojom/BUILD.gn b/chromeos/components/proximity_auth/public/mojom/BUILD.gn
index 31af832..c3d4a0b 100644
--- a/chromeos/components/proximity_auth/public/mojom/BUILD.gn
+++ b/chromeos/components/proximity_auth/public/mojom/BUILD.gn
@@ -5,7 +5,5 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "auth_type.mojom",
-  ]
+  sources = [ "auth_type.mojom" ]
 }
diff --git a/chromeos/components/tether/BUILD.gn b/chromeos/components/tether/BUILD.gn
index 4bbcb3c..5f5f40e 100644
--- a/chromeos/components/tether/BUILD.gn
+++ b/chromeos/components/tether/BUILD.gn
@@ -195,9 +195,7 @@
     "test_timer_factory.h",
   ]
 
-  public_deps = [
-    ":tether",
-  ]
+  public_deps = [ ":tether" ]
 
   deps = [
     "//base",
diff --git a/chromeos/components/tether/proto/BUILD.gn b/chromeos/components/tether/proto/BUILD.gn
index dc40a95..1b7c394 100644
--- a/chromeos/components/tether/proto/BUILD.gn
+++ b/chromeos/components/tether/proto/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "tether.proto",
-  ]
+  sources = [ "tether.proto" ]
 }
diff --git a/chromeos/dbus/cros_healthd/cros_healthd_client.cc b/chromeos/dbus/cros_healthd/cros_healthd_client.cc
index 887a49b..3d1566f 100644
--- a/chromeos/dbus/cros_healthd/cros_healthd_client.cc
+++ b/chromeos/dbus/cros_healthd/cros_healthd_client.cc
@@ -29,7 +29,8 @@
   ~CrosHealthdClientImpl() override = default;
 
   // CrosHealthdClient overrides:
-  mojo::Remote<cros_healthd::mojom::CrosHealthdService> BootstrapMojoConnection(
+  mojo::Remote<cros_healthd::mojom::CrosHealthdServiceFactory>
+  BootstrapMojoConnection(
       base::OnceCallback<void(bool success)> result_callback) override {
     mojo::PlatformChannel platform_channel;
 
@@ -44,9 +45,10 @@
 
     // Bind our end of |pipe| to our CrosHealthdService remote. The daemon
     // should bind its end to a CrosHealthdService implementation.
-    mojo::Remote<cros_healthd::mojom::CrosHealthdService> cros_healthd_service;
-    cros_healthd_service.Bind(
-        mojo::PendingRemote<cros_healthd::mojom::CrosHealthdService>(
+    mojo::Remote<cros_healthd::mojom::CrosHealthdServiceFactory>
+        cros_healthd_service_factory;
+    cros_healthd_service_factory.Bind(
+        mojo::PendingRemote<cros_healthd::mojom::CrosHealthdServiceFactory>(
             std::move(pipe), 0u /* version */));
 
     dbus::MethodCall method_call(
@@ -63,7 +65,7 @@
             &CrosHealthdClientImpl::OnBootstrapMojoConnectionResponse,
             weak_ptr_factory_.GetWeakPtr(), std::move(result_callback)));
 
-    return cros_healthd_service;
+    return cros_healthd_service_factory;
   }
 
   void Init(dbus::Bus* const bus) {
diff --git a/chromeos/dbus/cros_healthd/cros_healthd_client.h b/chromeos/dbus/cros_healthd/cros_healthd_client.h
index 29f50ad..d8288fa 100644
--- a/chromeos/dbus/cros_healthd/cros_healthd_client.h
+++ b/chromeos/dbus/cros_healthd/cros_healthd_client.h
@@ -40,7 +40,7 @@
 
   // Uses D-Bus to bootstrap the Mojo connection between the cros_healthd daemon
   // and the browser. Returns a bound remote
-  virtual mojo::Remote<cros_healthd::mojom::CrosHealthdService>
+  virtual mojo::Remote<cros_healthd::mojom::CrosHealthdServiceFactory>
   BootstrapMojoConnection(
       base::OnceCallback<void(bool success)> result_callback) = 0;
 
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_client.cc b/chromeos/dbus/cros_healthd/fake_cros_healthd_client.cc
index 0a9eb55..0643f68 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_client.cc
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_client.cc
@@ -32,10 +32,10 @@
   return g_instance;
 }
 
-mojo::Remote<mojom::CrosHealthdService>
+mojo::Remote<mojom::CrosHealthdServiceFactory>
 FakeCrosHealthdClient::BootstrapMojoConnection(
     base::OnceCallback<void(bool success)> result_callback) {
-  mojo::Remote<mojom::CrosHealthdService> remote(
+  mojo::Remote<mojom::CrosHealthdServiceFactory> remote(
       receiver_.BindNewPipeAndPassRemote());
 
   std::move(result_callback).Run(/*success=*/true);
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_client.h b/chromeos/dbus/cros_healthd/fake_cros_healthd_client.h
index 2a47ff1..e27f8c2 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_client.h
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_client.h
@@ -34,7 +34,7 @@
   static FakeCrosHealthdClient* Get();
 
   // CrosHealthdClient overrides:
-  mojo::Remote<mojom::CrosHealthdService> BootstrapMojoConnection(
+  mojo::Remote<mojom::CrosHealthdServiceFactory> BootstrapMojoConnection(
       base::OnceCallback<void(bool success)> result_callback) override;
 
   // Set the list of routines that will be used in the response to any
@@ -56,7 +56,7 @@
 
  private:
   FakeCrosHealthdService fake_service_;
-  mojo::Receiver<mojom::CrosHealthdService> receiver_{&fake_service_};
+  mojo::Receiver<mojom::CrosHealthdServiceFactory> receiver_{&fake_service_};
 
   DISALLOW_COPY_AND_ASSIGN(FakeCrosHealthdClient);
 };
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
index 086f331..2eddcab 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.cc
@@ -12,6 +12,16 @@
 FakeCrosHealthdService::FakeCrosHealthdService() = default;
 FakeCrosHealthdService::~FakeCrosHealthdService() = default;
 
+void FakeCrosHealthdService::GetProbeService(
+    mojom::CrosHealthdProbeServiceRequest service) {
+  probe_receiver_set_.Add(this, std::move(service));
+}
+
+void FakeCrosHealthdService::GetDiagnosticsService(
+    mojom::CrosHealthdDiagnosticsServiceRequest service) {
+  diagnostics_receiver_set_.Add(this, std::move(service));
+}
+
 void FakeCrosHealthdService::GetAvailableRoutines(
     GetAvailableRoutinesCallback callback) {
   std::move(callback).Run(available_routines_);
diff --git a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
index 2d4ebb9..4f75d143 100644
--- a/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
+++ b/chromeos/dbus/cros_healthd/fake_cros_healthd_service.h
@@ -11,16 +11,29 @@
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 
 namespace chromeos {
 namespace cros_healthd {
 
-class FakeCrosHealthdService final : public mojom::CrosHealthdService {
+// This class serves as a fake for all three of cros_healthd's mojo interfaces.
+// The factory methods bind to receivers held within FakeCrosHealtdService, and
+// all requests on each of the interfaces are fulfilled by
+// FakeCrosHealthdService.
+class FakeCrosHealthdService final
+    : public mojom::CrosHealthdServiceFactory,
+      public mojom::CrosHealthdDiagnosticsService,
+      public mojom::CrosHealthdProbeService {
  public:
   FakeCrosHealthdService();
   ~FakeCrosHealthdService() override;
 
-  // CrosHealthdService overrides:
+  // CrosHealthdServiceFactory overrides:
+  void GetProbeService(mojom::CrosHealthdProbeServiceRequest service) override;
+  void GetDiagnosticsService(
+      mojom::CrosHealthdDiagnosticsServiceRequest service) override;
+
+  // CrosHealthdDiagnosticsService overrides:
   void GetAvailableRoutines(GetAvailableRoutinesCallback callback) override;
   void GetRoutineUpdate(int32_t id,
                         mojom::DiagnosticRoutineCommandEnum command,
@@ -38,6 +51,8 @@
       RunBatteryHealthRoutineCallback callback) override;
   void RunSmartctlCheckRoutine(
       RunSmartctlCheckRoutineCallback callback) override;
+
+  // CrosHealthdProbeService overrides:
   void ProbeTelemetryInfo(
       const std::vector<mojom::ProbeCategoryEnum>& categories,
       ProbeTelemetryInfoCallback callback) override;
@@ -71,6 +86,11 @@
   // Used as the response to any ProbeTelemetryInfo IPCs received.
   mojom::TelemetryInfoPtr telemetry_response_info_{mojom::TelemetryInfo::New()};
 
+  // Allows the remote end to call the probe and diagnostics service methods.
+  mojo::ReceiverSet<mojom::CrosHealthdProbeService> probe_receiver_set_;
+  mojo::ReceiverSet<mojom::CrosHealthdDiagnosticsService>
+      diagnostics_receiver_set_;
+
   DISALLOW_COPY_AND_ASSIGN(FakeCrosHealthdService);
 };
 
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.cc b/chromeos/services/cros_healthd/public/cpp/service_connection.cc
index 4dd925ed..b2e11e50 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.cc
+++ b/chromeos/services/cros_healthd/public/cpp/service_connection.cc
@@ -28,37 +28,49 @@
  private:
   // ServiceConnection overrides:
   void GetAvailableRoutines(
-      mojom::CrosHealthdService::GetAvailableRoutinesCallback callback)
-      override;
+      mojom::CrosHealthdDiagnosticsService::GetAvailableRoutinesCallback
+          callback) override;
   void GetRoutineUpdate(
       int32_t id,
       mojom::DiagnosticRoutineCommandEnum command,
       bool include_output,
-      mojom::CrosHealthdService::GetRoutineUpdateCallback callback) override;
+      mojom::CrosHealthdDiagnosticsService::GetRoutineUpdateCallback callback)
+      override;
   void RunUrandomRoutine(
       uint32_t length_seconds,
-      mojom::CrosHealthdService::RunUrandomRoutineCallback callback) override;
+      mojom::CrosHealthdDiagnosticsService::RunUrandomRoutineCallback callback)
+      override;
   void RunBatteryCapacityRoutine(
       uint32_t low_mah,
       uint32_t high_mah,
-      mojom::CrosHealthdService::RunBatteryCapacityRoutineCallback callback)
-      override;
+      mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
+          callback) override;
   void RunBatteryHealthRoutine(
       uint32_t maximum_cycle_count,
       uint32_t percent_battery_wear_allowed,
-      mojom::CrosHealthdService::RunBatteryHealthRoutineCallback callback)
-      override;
+      mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
+          callback) override;
   void RunSmartctlCheckRoutine(
-      mojom::CrosHealthdService::RunSmartctlCheckRoutineCallback callback)
-      override;
+      mojom::CrosHealthdDiagnosticsService::RunSmartctlCheckRoutineCallback
+          callback) override;
   void ProbeTelemetryInfo(
       const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
-      mojom::CrosHealthdService::ProbeTelemetryInfoCallback callback) override;
+      mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback)
+      override;
 
-  // Binds the top level interface |cros_healthd_service_| to an
+  // Binds the factory interface |cros_healthd_service_factory_| to an
   // implementation in the cros_healthd daemon, if it is not already bound. The
   // binding is accomplished via D-Bus bootstrap.
-  void BindCrosHealthdServiceIfNeeded();
+  void BindCrosHealthdServiceFactoryIfNeeded();
+
+  // Uses |cros_healthd_service_factory_| to bind the diagnostics service remote
+  // to an implementation in the cros_healethd daemon, if it is not already
+  // bound.
+  void BindCrosHealthdDiagnosticsServiceIfNeeded();
+
+  // Uses |cros_healthd_service_factory_| to bind the probe service remote to an
+  // implementation in the cros_healethd daemon, if it is not already bound.
+  void BindCrosHealthdProbeServiceIfNeeded();
 
   // Mojo disconnect handler. Resets |cros_healthd_service_|, which will be
   // reconnected upon next use.
@@ -67,7 +79,10 @@
   // Response callback for BootstrapMojoConnection.
   void OnBootstrapMojoConnectionResponse(bool success);
 
-  mojo::Remote<mojom::CrosHealthdService> cros_healthd_service_;
+  mojo::Remote<mojom::CrosHealthdServiceFactory> cros_healthd_service_factory_;
+  mojo::Remote<mojom::CrosHealthdProbeService> cros_healthd_probe_service_;
+  mojo::Remote<mojom::CrosHealthdDiagnosticsService>
+      cros_healthd_diagnostics_service_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
@@ -75,76 +90,107 @@
 };
 
 void ServiceConnectionImpl::GetAvailableRoutines(
-    mojom::CrosHealthdService::GetAvailableRoutinesCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::GetAvailableRoutinesCallback
+        callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->GetAvailableRoutines(std::move(callback));
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->GetAvailableRoutines(std::move(callback));
 }
 
 void ServiceConnectionImpl::GetRoutineUpdate(
     int32_t id,
     mojom::DiagnosticRoutineCommandEnum command,
     bool include_output,
-    mojom::CrosHealthdService::GetRoutineUpdateCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::GetRoutineUpdateCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->GetRoutineUpdate(id, command, include_output,
-                                          std::move(callback));
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->GetRoutineUpdate(
+      id, command, include_output, std::move(callback));
 }
 
 void ServiceConnectionImpl::RunUrandomRoutine(
     uint32_t length_seconds,
-    mojom::CrosHealthdService::RunUrandomRoutineCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::RunUrandomRoutineCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->RunUrandomRoutine(length_seconds, std::move(callback));
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunUrandomRoutine(length_seconds,
+                                                       std::move(callback));
 }
 
 void ServiceConnectionImpl::RunBatteryCapacityRoutine(
     uint32_t low_mah,
     uint32_t high_mah,
-    mojom::CrosHealthdService::RunBatteryCapacityRoutineCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
+        callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->RunBatteryCapacityRoutine(low_mah, high_mah,
-                                                   std::move(callback));
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunBatteryCapacityRoutine(
+      low_mah, high_mah, std::move(callback));
 }
 
 void ServiceConnectionImpl::RunBatteryHealthRoutine(
     uint32_t maximum_cycle_count,
     uint32_t percent_battery_wear_allowed,
-    mojom::CrosHealthdService::RunBatteryHealthRoutineCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
+        callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->RunBatteryHealthRoutine(
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunBatteryHealthRoutine(
       maximum_cycle_count, percent_battery_wear_allowed, std::move(callback));
 }
 
 void ServiceConnectionImpl::RunSmartctlCheckRoutine(
-    mojom::CrosHealthdService::RunSmartctlCheckRoutineCallback callback) {
+    mojom::CrosHealthdDiagnosticsService::RunSmartctlCheckRoutineCallback
+        callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->RunSmartctlCheckRoutine(std::move(callback));
+  BindCrosHealthdDiagnosticsServiceIfNeeded();
+  cros_healthd_diagnostics_service_->RunSmartctlCheckRoutine(
+      std::move(callback));
 }
 
 void ServiceConnectionImpl::ProbeTelemetryInfo(
     const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
-    mojom::CrosHealthdService::ProbeTelemetryInfoCallback callback) {
+    mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  BindCrosHealthdServiceIfNeeded();
-  cros_healthd_service_->ProbeTelemetryInfo(categories_to_test,
-                                            std::move(callback));
+  BindCrosHealthdProbeServiceIfNeeded();
+  cros_healthd_probe_service_->ProbeTelemetryInfo(categories_to_test,
+                                                  std::move(callback));
 }
 
-void ServiceConnectionImpl::BindCrosHealthdServiceIfNeeded() {
+void ServiceConnectionImpl::BindCrosHealthdServiceFactoryIfNeeded() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (cros_healthd_service_.is_bound())
+  if (cros_healthd_service_factory_.is_bound())
     return;
 
-  cros_healthd_service_ = CrosHealthdClient::Get()->BootstrapMojoConnection(
-      base::BindOnce(&ServiceConnectionImpl::OnBootstrapMojoConnectionResponse,
-                     base::Unretained(this)));
-  cros_healthd_service_.set_disconnect_handler(base::BindOnce(
+  cros_healthd_service_factory_ =
+      CrosHealthdClient::Get()->BootstrapMojoConnection(base::BindOnce(
+          &ServiceConnectionImpl::OnBootstrapMojoConnectionResponse,
+          base::Unretained(this)));
+  cros_healthd_service_factory_.set_disconnect_handler(base::BindOnce(
+      &ServiceConnectionImpl::OnDisconnect, base::Unretained(this)));
+}
+
+void ServiceConnectionImpl::BindCrosHealthdDiagnosticsServiceIfNeeded() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (cros_healthd_diagnostics_service_.is_bound())
+    return;
+
+  BindCrosHealthdServiceFactoryIfNeeded();
+  cros_healthd_service_factory_->GetDiagnosticsService(
+      cros_healthd_diagnostics_service_.BindNewPipeAndPassReceiver());
+  cros_healthd_diagnostics_service_.set_disconnect_handler(base::BindOnce(
+      &ServiceConnectionImpl::OnDisconnect, base::Unretained(this)));
+}
+
+void ServiceConnectionImpl::BindCrosHealthdProbeServiceIfNeeded() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (cros_healthd_probe_service_.is_bound())
+    return;
+
+  BindCrosHealthdServiceFactoryIfNeeded();
+  cros_healthd_service_factory_->GetProbeService(
+      cros_healthd_probe_service_.BindNewPipeAndPassReceiver());
+  cros_healthd_probe_service_.set_disconnect_handler(base::BindOnce(
       &ServiceConnectionImpl::OnDisconnect, base::Unretained(this)));
 }
 
@@ -156,7 +202,9 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Connection errors are not expected, so log a warning.
   DLOG(WARNING) << "cros_healthd Mojo connection closed.";
-  cros_healthd_service_.reset();
+  cros_healthd_service_factory_.reset();
+  cros_healthd_probe_service_.reset();
+  cros_healthd_diagnostics_service_.reset();
 }
 
 void ServiceConnectionImpl::OnBootstrapMojoConnectionResponse(
@@ -164,7 +212,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!success) {
     DLOG(WARNING) << "BootstrapMojoConnection D-Bus call failed.";
-    cros_healthd_service_.reset();
+    cros_healthd_service_factory_.reset();
   }
 }
 
diff --git a/chromeos/services/cros_healthd/public/cpp/service_connection.h b/chromeos/services/cros_healthd/public/cpp/service_connection.h
index b07595e..5c81450 100644
--- a/chromeos/services/cros_healthd/public/cpp/service_connection.h
+++ b/chromeos/services/cros_healthd/public/cpp/service_connection.h
@@ -23,7 +23,8 @@
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void GetAvailableRoutines(
-      mojom::CrosHealthdService::GetAvailableRoutinesCallback callback) = 0;
+      mojom::CrosHealthdDiagnosticsService::GetAvailableRoutinesCallback
+          callback) = 0;
 
   // Send a command to an existing routine. Also returns status information
   // for the routine. See
@@ -33,14 +34,16 @@
       int32_t id,
       mojom::DiagnosticRoutineCommandEnum command,
       bool include_output,
-      mojom::CrosHealthdService::GetRoutineUpdateCallback callback) = 0;
+      mojom::CrosHealthdDiagnosticsService::GetRoutineUpdateCallback
+          callback) = 0;
 
   // Requests that cros_healthd runs the urandom routine. See
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunUrandomRoutine(
       uint32_t length_seconds,
-      mojom::CrosHealthdService::RunUrandomRoutineCallback callback) = 0;
+      mojom::CrosHealthdDiagnosticsService::RunUrandomRoutineCallback
+          callback) = 0;
 
   // Requests that cros_healthd runs the battery capacity routine. See
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
@@ -48,7 +51,7 @@
   virtual void RunBatteryCapacityRoutine(
       uint32_t low_mah,
       uint32_t high_mah,
-      mojom::CrosHealthdService::RunBatteryCapacityRoutineCallback
+      mojom::CrosHealthdDiagnosticsService::RunBatteryCapacityRoutineCallback
           callback) = 0;
 
   // Requests that cros_healthd runs the battery health routine. See
@@ -57,20 +60,22 @@
   virtual void RunBatteryHealthRoutine(
       uint32_t maximum_cycle_count,
       uint32_t percent_battery_wear_allowed,
-      mojom::CrosHealthdService::RunBatteryHealthRoutineCallback callback) = 0;
+      mojom::CrosHealthdDiagnosticsService::RunBatteryHealthRoutineCallback
+          callback) = 0;
 
   // Requests that cros_healthd runs the smartcl check routine. See
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void RunSmartctlCheckRoutine(
-      mojom::CrosHealthdService::RunSmartctlCheckRoutineCallback callback) = 0;
+      mojom::CrosHealthdDiagnosticsService::RunSmartctlCheckRoutineCallback
+          callback) = 0;
 
   // Gather pieces of information about the platform. See
   // src/chromeos/service/cros_healthd/public/mojom/cros_healthd.mojom for
   // details.
   virtual void ProbeTelemetryInfo(
       const std::vector<mojom::ProbeCategoryEnum>& categories_to_test,
-      mojom::CrosHealthdService::ProbeTelemetryInfoCallback callback) = 0;
+      mojom::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) = 0;
 
  protected:
   ServiceConnection() = default;
diff --git a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom b/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
index a6f9dfb..5886072 100644
--- a/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
+++ b/chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom
@@ -13,9 +13,17 @@
 import "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom";
 import "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom";
 
-// Interface exposed by the cros_healthd daemon.
-interface CrosHealthdService {
-  // ------------------- Start of diagnostics definitions ---------------------
+// Factory interface which allows remote ends to request implementations of the
+// probe or diagnostics services.
+interface CrosHealthdServiceFactory {
+  // Returns a bound interface to the diagnostics service.
+  GetDiagnosticsService(CrosHealthdDiagnosticsService& service);
+  // Returns a bound interface to the probe service.
+  GetProbeService(CrosHealthdProbeService& service);
+};
+
+// Diagnostics interface exposed by the cros_healthd daemon.
+interface CrosHealthdDiagnosticsService {
   // Returns an array of all diagnostic routines that the platform supports.
   GetAvailableRoutines()
       => (array<DiagnosticRoutineEnum> available_routines);
@@ -98,20 +106,11 @@
   // * |response| - contains a unique identifier and status for the created
   //                routine.
   RunSmartctlCheckRoutine() => (RunRoutineResponse response);
+};
 
-  // ------------------- End of diagnostics definitions -----------------------
-
-  // ------------------- Start of probe definitions ---------------------
-
-  // Returns telemetry information for the desired categories. This IPC is
-  // exposed so that the browser can pull data from cros_healthd. The browser
-  // will periodically call ProbeTelemetryInfo and upload the results to the EMM
-  // API in the cloud, where the data collected from cros_healthd will be made
-  // available to OEMs. Since the browser is making requests and cros_healthd is
-  // replying, we can consider cros_healthd the privileged side of this
-  // communication. ProbeTelemetryInfo only returns parsed data, so the browser
-  // will not do any parsing. cros_healthd does not process input that could be
-  // controlled by a malicious attacker.
+// Probe interface exposed by the cros_healthd daemon.
+interface CrosHealthdProbeService {
+  // Returns telemetry information for the desired categories.
   //
   // The request:
   // * |categories| - list of each of the categories that ProbeTelemetryInfo
@@ -123,6 +122,4 @@
   //                      will be non-null.
   ProbeTelemetryInfo(array<ProbeCategoryEnum> categories)
       => (TelemetryInfo telemetry_info);
-
-  // ------------------- End of probe definitions -----------------------
 };
diff --git a/chromeos/services/network_config/BUILD.gn b/chromeos/services/network_config/BUILD.gn
index 11a6124f..cb8be1428 100644
--- a/chromeos/services/network_config/BUILD.gn
+++ b/chromeos/services/network_config/BUILD.gn
@@ -48,9 +48,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "cros_network_config_unittest.cc",
-  ]
+  sources = [ "cros_network_config_unittest.cc" ]
 
   deps = [
     ":network_config",
diff --git a/chromeos/services/network_config/public/cpp/BUILD.gn b/chromeos/services/network_config/public/cpp/BUILD.gn
index 965cf420..aa50efe 100644
--- a/chromeos/services/network_config/public/cpp/BUILD.gn
+++ b/chromeos/services/network_config/public/cpp/BUILD.gn
@@ -10,9 +10,7 @@
     "cros_network_config_util.h",
   ]
 
-  deps = [
-    "//chromeos/services/network_config/public/mojom",
-  ]
+  deps = [ "//chromeos/services/network_config/public/mojom" ]
 }
 
 source_set("test_support") {
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 0058999..02bb187c 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -209,6 +209,7 @@
       "//components/image_fetcher/ios:unit_tests",
       "//components/language/ios/browser:unit_tests",
       "//components/password_manager/ios:unit_tests",
+      "//components/safe_browsing/ios:unit_tests",
       "//components/security_state/ios:unit_tests",
       "//components/signin/ios/browser:unit_tests",
       "//components/translate/ios/browser:unit_tests",
diff --git a/components/bubble/BUILD.gn b/components/bubble/BUILD.gn
index b9e66327..ca014493 100644
--- a/components/bubble/BUILD.gn
+++ b/components/bubble/BUILD.gn
@@ -15,9 +15,7 @@
     "bubble_ui.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 static_library("test_support") {
@@ -39,9 +37,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "bubble_manager_unittest.cc",
-  ]
+  sources = [ "bubble_manager_unittest.cc" ]
 
   deps = [
     ":bubble",
diff --git a/components/constrained_window/BUILD.gn b/components/constrained_window/BUILD.gn
index 67d450d..2779bda 100644
--- a/components/constrained_window/BUILD.gn
+++ b/components/constrained_window/BUILD.gn
@@ -39,9 +39,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "constrained_window_views_unittest.cc",
-  ]
+  sources = [ "constrained_window_views_unittest.cc" ]
 
   deps = [
     ":constrained_window",
diff --git a/components/cronet/BUILD.gn b/components/cronet/BUILD.gn
index 6d0b2cc..82867a5c0 100644
--- a/components/cronet/BUILD.gn
+++ b/components/cronet/BUILD.gn
@@ -26,9 +26,7 @@
 
 process_version("cronet_version_header") {
   template_file = "//components/cronet/version.h.in"
-  sources = [
-    "//chrome/VERSION",
-  ]
+  sources = [ "//chrome/VERSION" ]
   output = "$target_gen_dir/version.h"
   extra_args = [
     "-e",
@@ -84,9 +82,7 @@
     "metrics_util.cc",
     "metrics_util.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 # Unit tests for Cronet common implementation.
@@ -117,15 +113,11 @@
 if (is_android) {
   group("cronet_package") {
     testonly = true
-    deps = [
-      "//components/cronet/android:cronet_package_android",
-    ]
+    deps = [ "//components/cronet/android:cronet_package_android" ]
   }
 } else if (is_ios) {
   group("cronet_package") {
-    deps = [
-      "//components/cronet/ios:cronet_package_ios",
-    ]
+    deps = [ "//components/cronet/ios:cronet_package_ios" ]
   }
 } else {
   config("shared_library_public_config") {
@@ -153,9 +145,7 @@
       "//net",
     ]
 
-    sources = [
-      "cronet_global_state_stubs.cc",
-    ]
+    sources = [ "cronet_global_state_stubs.cc" ]
 
     if (is_mac && !is_component_build) {
       ldflags = [
@@ -211,12 +201,8 @@
     _license_path = "$_package_dir/LICENSE"
 
     script = "//tools/licenses.py"
-    inputs = [
-      lastchange_file,
-    ]
-    outputs = [
-      _license_path,
-    ]
+    inputs = [ lastchange_file ]
+    outputs = [ _license_path ]
     args = [
       "license_file",
       rebase_path(_license_path, root_build_dir),
@@ -234,21 +220,15 @@
       "//AUTHORS",
       "//chrome/VERSION",
     ]
-    deps = [
-      ":cronet",
-    ]
-    outputs = [
-      "$_package_dir/{{source_file_part}}",
-    ]
+    deps = [ ":cronet" ]
+    outputs = [ "$_package_dir/{{source_file_part}}" ]
   }
 
   # Copy headers.
   copy("cronet_package_headers") {
     sources = cronet_native_public_headers + grpc_public_headers
 
-    outputs = [
-      "$_package_dir/include/{{source_file_part}}",
-    ]
+    outputs = [ "$_package_dir/include/{{source_file_part}}" ]
   }
 
   group("cronet_package") {
@@ -294,9 +274,7 @@
   }
 
   test("cronet_sample_test") {
-    sources = [
-      "native/sample/test/sample_test.cc",
-    ]
+    sources = [ "native/sample/test/sample_test.cc" ]
     deps = [
       ":cronet_sample",
       "//testing/gtest:gtest",
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn
index 1bd7dd2..2885e68 100644
--- a/components/cronet/android/BUILD.gn
+++ b/components/cronet/android/BUILD.gn
@@ -63,49 +63,33 @@
 }
 
 java_cpp_enum("rtt_throughput_values_java") {
-  sources = [
-    "//net/nqe/network_quality.h",
-  ]
+  sources = [ "//net/nqe/network_quality.h" ]
 }
 
 java_cpp_enum("net_request_priority_java") {
-  sources = [
-    "//net/base/request_priority.h",
-  ]
+  sources = [ "//net/base/request_priority.h" ]
 }
 
 java_cpp_enum("network_quality_observation_source_java") {
-  sources = [
-    "//net/nqe/network_quality_observation_source.h",
-  ]
+  sources = [ "//net/nqe/network_quality_observation_source.h" ]
 }
 
 java_cpp_enum("url_request_error_java") {
-  sources = [
-    "url_request_error.h",
-  ]
+  sources = [ "url_request_error.h" ]
 }
 
 java_cpp_enum("http_cache_type_java") {
-  sources = [
-    "//components/cronet/url_request_context_config.h",
-  ]
+  sources = [ "//components/cronet/url_request_context_config.h" ]
 }
 
 java_cpp_template("load_states_list") {
-  sources = [
-    "java/src/org/chromium/net/impl/LoadState.template",
-  ]
-  inputs = [
-    "//net/base/load_states_list.h",
-  ]
+  sources = [ "java/src/org/chromium/net/impl/LoadState.template" ]
+  inputs = [ "//net/base/load_states_list.h" ]
   package_path = "org/chromium/net/impl"
 }
 
 java_cpp_template("integrated_mode_state") {
-  sources = [
-    "java/src/org/chromium/net/impl/IntegratedModeState.template",
-  ]
+  sources = [ "java/src/org/chromium/net/impl/IntegratedModeState.template" ]
   package_path = "org/chromium/net/impl"
   if (integrated_mode) {
     defines = [ "INTEGRATED_MODE" ]
@@ -218,9 +202,7 @@
 
 shared_library("cronet") {
   output_name = _cronet_shared_lib_name
-  sources = [
-    "cronet_jni.cc",
-  ]
+  sources = [ "cronet_jni.cc" ]
   deps = [
     ":cronet_static",
     "//base",
@@ -231,12 +213,8 @@
 }
 
 sizes_test("cronet_sizes") {
-  data_deps = [
-    ":cronet",
-  ]
-  data = [
-    "${root_out_dir}/lib${_cronet_shared_lib_name}.so",
-  ]
+  data_deps = [ ":cronet" ]
+  data = [ "${root_out_dir}/lib${_cronet_shared_lib_name}.so" ]
   executable_args = [
     "--platform",
     "android-cronet",
@@ -396,9 +374,7 @@
     "java/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactory.java",
     "java/src/org/chromium/net/urlconnection/MessageLoop.java",
   ]
-  deps = [
-    ":cronet_api_java",
-  ]
+  deps = [ ":cronet_api_java" ]
 }
 
 # cronet_impl_native_base_java.jar - native implementation of the Cronet engine.
@@ -444,9 +420,7 @@
 android_resources("cronet_sample_apk_resources") {
   resource_dirs = [ "sample/res" ]
   android_manifest = "sample/AndroidManifest.xml"
-  deps = [
-    "//third_party/android_deps:android_support_v7_appcompat_java",
-  ]
+  deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
 }
 
 android_library("cronet_sample_apk_java") {
@@ -491,9 +465,7 @@
 
 android_resource_sizes_test("resource_sizes_cronet_sample_apk") {
   apk_name = "CronetSample"
-  data_deps = [
-    ":cronet_sample_apk",
-  ]
+  data_deps = [ ":cronet_sample_apk" ]
 }
 
 action("cronet_combine_proguard_flags") {
@@ -505,9 +477,7 @@
     "//components/cronet/android/cronet_appreduce_workaround.patch",
     "//components/cronet/android/cronet_impl_native_proguard.cfg",
   ]
-  outputs = [
-    "$target_gen_dir/cronet_impl_native_proguard.cfg",
-  ]
+  outputs = [ "$target_gen_dir/cronet_impl_native_proguard.cfg" ]
   args = [ "--output-file" ] + rebase_path(outputs, root_build_dir) +
          rebase_path(sources, root_build_dir)
 }
@@ -520,9 +490,7 @@
 # usage.
 android_java_prebuilt("package_api_java") {
   jar_path = "$_package_dir/cronet_api.jar"
-  deps = [
-    ":repackage_api",
-  ]
+  deps = [ ":repackage_api" ]
 }
 
 android_java_prebuilt("package_impl_common_java") {
@@ -582,9 +550,7 @@
 
     script = "//components/cronet/tools/jar_src.py"
     depfile = "$target_gen_dir/$target_name.d"
-    outputs = [
-      invoker.jar_path,
-    ]
+    outputs = [ invoker.jar_path ]
     args = [
       "--src-search-dirs=${_rebased_src_search_dirs}",
       "--jar-path",
@@ -708,30 +674,22 @@
 
 repackage_jars("repackage_api") {
   output = "$_package_dir/cronet_api.jar"
-  deps = [
-    ":cronet_api_java",
-  ]
+  deps = [ ":cronet_api_java" ]
 }
 
 repackage_jars("repackage_platform") {
   output = "$_package_dir/cronet_impl_platform_java.jar"
-  deps = [
-    ":cronet_impl_platform_base_java",
-  ]
+  deps = [ ":cronet_impl_platform_base_java" ]
 }
 
 repackage_jars("repackage_fake") {
   output = "$_package_dir/cronet_impl_fake_java.jar"
-  deps = [
-    ":cronet_impl_fake_base_java",
-  ]
+  deps = [ ":cronet_impl_fake_base_java" ]
 }
 
 repackage_jars("repackage_util") {
   output = "$_package_dir/cronet_impl_util_java.jar"
-  deps = [
-    ":cronet_impl_java_util_java",
-  ]
+  deps = [ ":cronet_impl_java_util_java" ]
 }
 
 # See crbug.com/1005836 for more info on why repackage_native requires 2 extra
@@ -765,9 +723,7 @@
   # Since only the unprocessed jar is used, no need to complete the bytecode
   # processing steps.
   enable_bytecode_rewriter = false
-  deps = [
-    ":repackage_native_impl",
-  ]
+  deps = [ ":repackage_native_impl" ]
 }
 
 repackage_jars("repackage_common") {
@@ -795,9 +751,7 @@
     apk_under_test = ":cronet_sample_apk"
     android_manifest = "sample/javatests/AndroidManifest.xml"
     min_sdk_version = _cronet_min_sdk_version
-    sources = [
-      "sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java",
-    ]
+    sources = [ "sample/javatests/src/org/chromium/cronet_sample_apk/CronetSampleTest.java" ]
     deps = [
       "//third_party/android_support_test_runner:rules_java",
       "//third_party/android_support_test_runner:runner_java",
@@ -1034,9 +988,7 @@
       "//third_party/hamcrest:hamcrest_core_java",
     ]
     deps += cronet_javatests_deps_to_package
-    data = [
-      "//components/cronet/test/data/",
-    ]
+    data = [ "//components/cronet/test/data/" ]
   }
 
   instrumentation_test_apk("cronet_test_instrumentation_apk") {
@@ -1076,9 +1028,7 @@
     ]
     additional_apks = [ "//net/android:net_test_support_apk" ]
 
-    data_deps = [
-      "//net:test_support",
-    ]
+    data_deps = [ "//net:test_support" ]
 
     enable_multidex = true
     if (!is_java_debug) {
@@ -1223,13 +1173,9 @@
       "//testing/gtest",
     ]
 
-    sources = [
-      "../run_all_unittests.cc",
-    ]
+    sources = [ "../run_all_unittests.cc" ]
 
-    data = [
-      "//components/cronet/test/data/",
-    ]
+    data = [ "//components/cronet/test/data/" ]
 
     if (is_android) {
       shard_timeout = 180
@@ -1251,15 +1197,11 @@
       "//testing/gtest",
     ]
 
-    sources = [
-      "../run_all_unittests.cc",
-    ]
+    sources = [ "../run_all_unittests.cc" ]
 
     defines = [ "CRONET_TESTS_IMPLEMENTATION" ]
 
-    data = [
-      "//components/cronet/test/data/",
-    ]
+    data = [ "//components/cronet/test/data/" ]
 
     if (is_android) {
       shard_timeout = 180
@@ -1322,9 +1264,7 @@
     _license_path = "$_package_dir/LICENSE"
 
     script = "//tools/licenses.py"
-    outputs = [
-      _license_path,
-    ]
+    outputs = [ _license_path ]
     args = [
       "license_file",
       rebase_path(_license_path, root_build_dir),
@@ -1339,9 +1279,7 @@
     script = "//components/cronet/tools/generate_javadoc.py"
     depfile = "$target_gen_dir/$target_name.d"
     _zip_file = "$target_gen_dir/$target_name.zip"
-    outputs = [
-      _zip_file,
-    ]
+    outputs = [ _zip_file ]
     _annotations_jar = "$root_out_dir/lib.java/third_party/android_deps/androidx_annotation_annotation.jar"
     _src_jar = "$_package_dir/cronet_api-src.jar"
     inputs = [
@@ -1388,9 +1326,7 @@
       "cronet_impl_fake_proguard.cfg",
       "cronet_impl_platform_proguard.cfg",
     ]
-    outputs = [
-      "$_package_dir/{{source_file_part}}",
-    ]
+    outputs = [ "$_package_dir/{{source_file_part}}" ]
 
     deps = [
       ":cronet_api_java",
@@ -1404,34 +1340,21 @@
   copy("cronet_package_copy_native_headers") {
     sources = cronet_native_public_headers + grpc_public_headers
 
-    outputs = [
-      "$_package_dir/include/{{source_file_part}}",
-    ]
+    outputs = [ "$_package_dir/include/{{source_file_part}}" ]
   }
 
   copy("cronet_package_copy_native_lib") {
-    sources = [
-      "$root_out_dir/" + _cronet_shared_lib_file_name,
-    ]
-    outputs = [
-      "$_package_dir/libs/${android_app_abi}/" + _cronet_shared_lib_file_name,
-    ]
-    deps = [
-      ":cronet",
-    ]
+    sources = [ "$root_out_dir/" + _cronet_shared_lib_file_name ]
+    outputs = [ "$_package_dir/libs/${android_app_abi}/" +
+                _cronet_shared_lib_file_name ]
+    deps = [ ":cronet" ]
   }
 
   copy("cronet_package_copy_native_lib_unstripped") {
-    sources = [
-      "$root_out_dir/lib.unstripped/" + _cronet_shared_lib_file_name,
-    ]
-    outputs = [
-      "$_package_dir/symbols/${android_app_abi}/" +
-          _cronet_shared_lib_file_name,
-    ]
-    deps = [
-      ":cronet",
-    ]
+    sources = [ "$root_out_dir/lib.unstripped/" + _cronet_shared_lib_file_name ]
+    outputs = [ "$_package_dir/symbols/${android_app_abi}/" +
+                _cronet_shared_lib_file_name ]
+    deps = [ ":cronet" ]
   }
 
   copy("cronet_package_copy_native_test_lib") {
@@ -1440,9 +1363,8 @@
       "$root_out_dir/libcronet_tests.so",
       "$root_out_dir/libnetty-tcnative.so",
     ]
-    outputs = [
-      "$_test_package_dir/libs/${android_app_abi}/{{source_file_part}}",
-    ]
+    outputs =
+        [ "$_test_package_dir/libs/${android_app_abi}/{{source_file_part}}" ]
     deps = [
       ":cronet_tests",
       "//third_party/netty-tcnative:netty-tcnative-so",
@@ -1455,9 +1377,8 @@
       "$root_out_dir/lib.unstripped/libcronet_tests.so",
       "$root_out_dir/lib.unstripped/libnetty-tcnative.so",
     ]
-    outputs = [
-      "$_test_package_dir/symbols/${android_app_abi}/{{source_file_part}}",
-    ]
+    outputs =
+        [ "$_test_package_dir/symbols/${android_app_abi}/{{source_file_part}}" ]
     deps = [
       ":cronet_tests",
       "//third_party/netty-tcnative:netty-tcnative-so",
@@ -1466,12 +1387,8 @@
 
   copy("cronet_package_copy_test_assets") {
     testonly = true
-    sources = [
-      "//components/cronet/test/data",
-    ]
-    outputs = [
-      "$_test_package_dir/assets/test",
-    ]
+    sources = [ "//components/cronet/test/data" ]
+    outputs = [ "$_test_package_dir/assets/test" ]
   }
 
   copy("cronet_package_copy_test_support_apks") {
@@ -1480,12 +1397,9 @@
       # Provides EmbeddedTestServer.
       "$root_out_dir/apks/ChromiumNetTestSupport.apk",
     ]
-    outputs = [
-      "$_test_package_dir/apks/${android_app_abi}/{{source_file_part}}",
-    ]
-    deps = [
-      "//net/android:net_test_support_apk",
-    ]
+    outputs =
+        [ "$_test_package_dir/apks/${android_app_abi}/{{source_file_part}}" ]
+    deps = [ "//net/android:net_test_support_apk" ]
   }
 
   copy("cronet_package_copy_test_files") {
@@ -1497,9 +1411,7 @@
       "//net/data/ssl/certificates/quic-leaf-cert.key.pkcs8.pem",
       "//net/data/ssl/certificates/root_ca_cert.pem",
     ]
-    outputs = [
-      "$_test_package_dir/assets/test_files/net/data/ssl/certificates/{{source_file_part}}",
-    ]
+    outputs = [ "$_test_package_dir/assets/test_files/net/data/ssl/certificates/{{source_file_part}}" ]
     deps = [
       # Not really dependent, but builds can fail if these two targets attempt
       # to create the "assets" subdirectory simultaneously.
@@ -1508,21 +1420,15 @@
   }
 
   copy("cronet_package_copy_resources") {
-    sources = [
-      "api/res/raw/keep_cronet_api.xml",
-    ]
-    outputs = [
-      "$_package_dir/res/raw/{{source_file_part}}",
-    ]
+    sources = [ "api/res/raw/keep_cronet_api.xml" ]
+    outputs = [ "$_package_dir/res/raw/{{source_file_part}}" ]
   }
 
   # Enforce that ARM Neon is not used when building for ARMv7
   if (target_cpu == "arm" && arm_version == 7 && !arm_use_neon) {
     action("enforce_no_neon") {
       script = "//components/cronet/tools/check_no_neon.py"
-      outputs = [
-        "$target_gen_dir/$target_name.stamp",
-      ]
+      outputs = [ "$target_gen_dir/$target_name.stamp" ]
       args = [
         rebase_path("${android_tool_prefix}objdump", root_build_dir),
 
@@ -1534,18 +1440,14 @@
         "--stamp",
         rebase_path(outputs[0], root_build_dir),
       ]
-      deps = [
-        "//base:base",
-      ]
+      deps = [ "//base:base" ]
     }
   }
 
   # Enforce restrictions for API<->impl boundary.
   action("api_static_checks") {
     script = "//components/cronet/tools/api_static_checks.py"
-    outputs = [
-      "$target_gen_dir/$target_name.stamp",
-    ]
+    outputs = [ "$target_gen_dir/$target_name.stamp" ]
     args = [
       "--api_jar",
       rebase_path(
@@ -1572,9 +1474,7 @@
       ":cronet_impl_native_base_java",
       ":cronet_impl_platform_base_java",
     ]
-    inputs = [
-      "//components/cronet/tools/update_api.py",
-    ]
+    inputs = [ "//components/cronet/tools/update_api.py" ]
     sources = [
       "//components/cronet/android/api.txt",
       "//components/cronet/android/api_version.txt",
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index 2eef75e..3f50a8d3 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -15,9 +15,7 @@
 assert(!is_component_build, "Cronet requires static library build.")
 
 group("cronet_consumer_group") {
-  deps = [
-    "//components/cronet/ios/cronet_consumer",
-  ]
+  deps = [ "//components/cronet/ios/cronet_consumer" ]
 }
 
 config("cronet_include_config") {
@@ -90,13 +88,9 @@
     "//ios/web/public/init:global_state",
   ]
 
-  public_deps = [
-    ":cronet_sources",
-  ]
+  public_deps = [ ":cronet_sources" ]
 
-  sources = [
-    "ios_global_state_configuration.cc",
-  ]
+  sources = [ "ios_global_state_configuration.cc" ]
 }
 
 # Tweak |info_plist| with current version and revision.
@@ -116,15 +110,11 @@
 
   libs = [ "UIKit.Framework" ]
 
-  public_deps = [
-    "//components/grpc_support:headers",
-  ]
+  public_deps = [ "//components/grpc_support:headers" ]
 
   public_headers = _cronet_public_headers
 
-  sources = [
-    "Cronet.h",
-  ]
+  sources = [ "Cronet.h" ]
 
   configs -= [ "//build/config/compiler:default_symbols" ]
   configs += [ "//build/config/compiler:symbols" ]
@@ -135,9 +125,7 @@
 test("cronet_unittests_ios") {
   testonly = true
 
-  sources = [
-    "../run_all_unittests.cc",
-  ]
+  sources = [ "../run_all_unittests.cc" ]
 
   deps = [
     ":cronet_sources_with_global_state",
@@ -158,9 +146,7 @@
     rebase_path("$target_gen_dir"),
     rebase_path("//"),
   ]
-  outputs = [
-    "$target_gen_dir/accept_languages_table.h",
-  ]
+  outputs = [ "$target_gen_dir/accept_languages_table.h" ]
 }
 
 # A static library which contains just _cronet_sources.
@@ -169,9 +155,7 @@
   deps = _cronet_deps
   sources = _cronet_sources + [ "ios_global_state_configuration.cc" ]
   public_configs = [ ":cronet_include_config" ]
-  public_deps = [
-    "//components/grpc_support",
-  ]
+  public_deps = [ "//components/grpc_support" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
@@ -181,9 +165,7 @@
   visibility = [ ":*" ]
   complete_static_lib = true
   configs -= [ "//build/config/compiler:thin_archive" ]
-  deps = [
-    ":cronet_static",
-  ]
+  deps = [ ":cronet_static" ]
 
   if (use_custom_libcxx) {
     deps += [
@@ -204,9 +186,7 @@
     ":cronet_deps_complete",
     ":cronet_static",
   ]
-  outputs = [
-    "$target_out_dir/$current_cpu/cronet_static_complete.a",
-  ]
+  outputs = [ "$target_out_dir/$current_cpu/cronet_static_complete.a" ]
   args = [
     "--input_libs",
     rebase_path("$target_out_dir/libcronet_static.a", root_build_dir),
@@ -252,9 +232,7 @@
   bundle_data(_framework_headers_target) {
     visibility = [ ":$_target_name" ]
     sources = invoker.public_headers
-    outputs = [
-      "{{bundle_contents_dir}}/Headers/{{source_file_part}}",
-    ]
+    outputs = [ "{{bundle_contents_dir}}/Headers/{{source_file_part}}" ]
   }
 
   _framework_binary_target = _target_name + "_framework_binary"
@@ -263,12 +241,8 @@
   bundle_data(_framework_binary_target) {
     visibility = [ ":$_target_name" ]
     sources = get_target_outputs(_static_library_target)
-    outputs = [
-      "{{bundle_executable_dir}}/$_framework_name",
-    ]
-    public_deps = [
-      _static_library_target,
-    ]
+    outputs = [ "{{bundle_executable_dir}}/$_framework_name" ]
+    public_deps = [ _static_library_target ]
   }
 
   create_bundle(_target_name) {
@@ -300,12 +274,8 @@
     _license_path = "$_package_dir/LICENSE"
 
     script = "//tools/licenses.py"
-    inputs = [
-      lastchange_file,
-    ]
-    outputs = [
-      _license_path,
-    ]
+    inputs = [ lastchange_file ]
+    outputs = [ _license_path ]
     args = [
       "license_file",
       rebase_path(_license_path, root_build_dir),
@@ -319,16 +289,10 @@
   }
 
   copy("cronet_static_copy") {
-    sources = [
-      "$root_out_dir/Static/Cronet.framework",
-    ]
-    outputs = [
-      "$_package_dir/Static/Cronet.framework",
-    ]
+    sources = [ "$root_out_dir/Static/Cronet.framework" ]
+    outputs = [ "$_package_dir/Static/Cronet.framework" ]
 
-    deps = [
-      ":cronet_static_framework",
-    ]
+    deps = [ ":cronet_static_framework" ]
   }
 
   copy("cronet_package_copy") {
@@ -337,9 +301,7 @@
       "//AUTHORS",
       "//chrome/VERSION",
     ]
-    outputs = [
-      "$_package_dir/{{source_file_part}}",
-    ]
+    outputs = [ "$_package_dir/{{source_file_part}}" ]
 
     deps = [
       ":cronet_framework",
@@ -357,22 +319,16 @@
       # generate both the dSYM and binary image are listed in deps.
       _dsyms = [ "$root_out_dir/Cronet.dSYM" ]
 
-      sources = [
-        "$root_out_dir/Cronet.framework",
-      ]
+      sources = [ "$root_out_dir/Cronet.framework" ]
 
       _output = "$_package_dir/Cronet.dSYM.tar.bz2"
 
-      outputs = [
-        _output,
-      ]
+      outputs = [ _output ]
 
       args = [ rebase_path(_output, root_out_dir) ] +
              rebase_path(_dsyms, root_out_dir)
 
-      deps = [
-        ":cronet_framework",
-      ]
+      deps = [ ":cronet_framework" ]
     }
   } else {
     group("cronet_dsym_archive") {
diff --git a/components/cronet/ios/cronet_consumer/BUILD.gn b/components/cronet/ios/cronet_consumer/BUILD.gn
index a0454400..b4bba9a 100644
--- a/components/cronet/ios/cronet_consumer/BUILD.gn
+++ b/components/cronet/ios/cronet_consumer/BUILD.gn
@@ -11,9 +11,7 @@
   ios_app_bundle(_target_name) {
     info_plist = "cronet-consumer-Info.plist"
 
-    deps = [
-      "//base:base",
-    ]
+    deps = [ "//base:base" ]
 
     deps += invoker.deps
 
@@ -37,9 +35,7 @@
 }
 
 cronet_consumer_template("cronet_consumer") {
-  deps = [
-    "//components/cronet/ios:cronet_framework+link",
-  ]
+  deps = [ "//components/cronet/ios:cronet_framework+link" ]
   bundle_deps = [ "//components/cronet/ios:cronet_framework+bundle" ]
 }
 
@@ -48,9 +44,7 @@
 # duplicate architecture (e.g. arm64+arm64) and breaks the build.
 if (!defined(additional_target_cpus) || additional_target_cpus == []) {
   cronet_consumer_template("cronet_consumer_static") {
-    deps = [
-      "//components/cronet/ios:cronet_static_framework",
-    ]
+    deps = [ "//components/cronet/ios:cronet_static_framework" ]
 
     cflags = [
       "-F",
diff --git a/components/cronet/native/BUILD.gn b/components/cronet/native/BUILD.gn
index 2b82f47..6ee1271c 100644
--- a/components/cronet/native/BUILD.gn
+++ b/components/cronet/native/BUILD.gn
@@ -48,9 +48,7 @@
 
   configs += [ ":cronet_native_include_config" ]
   public_configs = [ ":cronet_native_include_config" ]
-  public_deps = [
-    ":cronet_native_headers",
-  ]
+  public_deps = [ ":cronet_native_headers" ]
 
   sources = [
     "buffer.cc",
diff --git a/components/cronet/stale_host_resolver.cc b/components/cronet/stale_host_resolver.cc
index 5097042..58fb0c8 100644
--- a/components/cronet/stale_host_resolver.cc
+++ b/components/cronet/stale_host_resolver.cc
@@ -216,8 +216,10 @@
   cache_parameters.source = net::HostResolverSource::LOCAL_ONLY;
   cache_request_ = resolver_->inner_resolver_->CreateRequest(
       host_, network_isolation_key_, net_log_, cache_parameters);
-  cache_error_ =
+  int error =
       cache_request_->Start(base::BindOnce([](int error) { NOTREACHED(); }));
+  DCHECK_NE(net::ERR_IO_PENDING, error);
+  cache_error_ = cache_request_->GetResolveErrorInfo().error;
   DCHECK_NE(net::ERR_IO_PENDING, cache_error_);
   // If it's a fresh cache hit (or literal), return it synchronously.
   if (cache_error_ != net::ERR_DNS_CACHE_MISS &&
diff --git a/components/cronet/test/BUILD.gn b/components/cronet/test/BUILD.gn
index f83f078..9ed0fc2 100644
--- a/components/cronet/test/BUILD.gn
+++ b/components/cronet/test/BUILD.gn
@@ -32,23 +32,17 @@
     "data/success.txt",
     "data/success.txt.mock-http-headers",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 # Test support for Cronet common implementation.
 source_set("test_support") {
   testonly = true
 
-  deps = [
-    "//net:test_support",
-  ]
+  deps = [ "//net:test_support" ]
 
-  data = [
-    "data/",
-  ]
+  data = [ "data/" ]
 
   sources = [
     "test_server.cc",
diff --git a/components/dbus/menu/BUILD.gn b/components/dbus/menu/BUILD.gn
index 7db84121b..9c0d113 100644
--- a/components/dbus/menu/BUILD.gn
+++ b/components/dbus/menu/BUILD.gn
@@ -30,9 +30,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "menu_property_list_unittest.cc",
-  ]
+  sources = [ "menu_property_list_unittest.cc" ]
   deps = [
     ":menu",
     "//base",
diff --git a/components/download/quarantine/BUILD.gn b/components/download/quarantine/BUILD.gn
index 395de65..4fb32a8 100644
--- a/components/download/quarantine/BUILD.gn
+++ b/components/download/quarantine/BUILD.gn
@@ -8,7 +8,5 @@
     "quarantine.h",
   ]
 
-  deps = [
-    "//components/services/quarantine",
-  ]
+  deps = [ "//components/services/quarantine" ]
 }
diff --git a/components/embedder_support/android/BUILD.gn b/components/embedder_support/android/BUILD.gn
index ad90ef04..cd8862b 100644
--- a/components/embedder_support/android/BUILD.gn
+++ b/components/embedder_support/android/BUILD.gn
@@ -6,9 +6,7 @@
 import("//build/config/locales.gni")
 
 android_library("application_java") {
-  deps = [
-    "//base:base_java",
-  ]
+  deps = [ "//base:base_java" ]
   sources = [
     "java/src/org/chromium/components/embedder_support/application/ClassLoaderContextWrapperFactory.java",
     "java/src/org/chromium/components/embedder_support/application/FontPreloadingWorkaround.java",
@@ -51,15 +49,11 @@
     "//ui/android:ui_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
-  sources = [
-    "java/src/org/chromium/components/embedder_support/view/ContentViewRenderView.java",
-  ]
+  sources = [ "java/src/org/chromium/components/embedder_support/view/ContentViewRenderView.java" ]
 }
 
 generate_jni("view_jni_headers") {
-  sources = [
-    "java/src/org/chromium/components/embedder_support/view/ContentViewRenderView.java",
-  ]
+  sources = [ "java/src/org/chromium/components/embedder_support/view/ContentViewRenderView.java" ]
 }
 
 java_strings_grd("web_contents_delegate_strings_grd") {
@@ -94,9 +88,7 @@
 android_resources("web_contents_delegate_java_resources") {
   custom_package = "org.chromium.components.embedder_support.delegate"
   resource_dirs = [ "java/res" ]
-  deps = [
-    ":web_contents_delegate_strings_grd",
-  ]
+  deps = [ ":web_contents_delegate_strings_grd" ]
 }
 
 android_library("web_contents_delegate_java") {
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
index d70d47e..baaca32f 100644
--- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
+++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
@@ -102,6 +102,10 @@
         setOnSystemUiVisibilityChangeListener(this);
     }
 
+    public WebContents getWebContents() {
+        return mWebContents;
+    }
+
     protected WebContentsAccessibility getWebContentsAccessibility() {
         return !mWebContents.isDestroyed() ? WebContentsAccessibility.fromWebContents(mWebContents)
                                            : null;
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index ca52a92..b621d4b7 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -562,7 +562,7 @@
 }
 
 void Surface::SetEmbeddedSurfaceSize(const gfx::Size& size) {
-  embedded_surface_size_ = gfx::SizeF(size);
+  embedded_surface_size_ = size;
 }
 
 void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) {
@@ -1007,12 +1007,8 @@
   // Surface quads require the quad rect to be appropriately sized and need to
   // use the shared quad clip rect.
   if (get_current_surface_id_) {
-    quad_rect = gfx::Rect(content_size_);
-    // Scale the |embedded_surface_size_| to |content_size_|.
-    if (embedded_surface_size_.width() || embedded_surface_size_.height()) {
-      scale.Scale(1.0f / embedded_surface_size_.width(),
-                  1.0f / embedded_surface_size_.height());
-    }
+    quad_rect = gfx::Rect(embedded_surface_size_);
+    scale = gfx::PointF(1.0f, 1.0f);
 
     if (!state_.crop.IsEmpty()) {
       // In order to crop an AxB rect to CxD we need to scale by A/C, B/D.
@@ -1021,7 +1017,9 @@
       scale.Scale(content_size_.width() / state_.crop.width(),
                   content_size_.height() / state_.crop.height());
 
-      translate = -state_.crop.origin().OffsetFromOrigin();
+      auto offset = state_.crop.origin().OffsetFromOrigin();
+      translate =
+          gfx::Vector2dF(-offset.x() * scale.x(), -offset.y() * scale.y());
     }
   } else {
     scale.Scale(state_.buffer_scale);
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 4b7d1d32..b49e8e9 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -464,7 +464,7 @@
 
   // The embedded surface is actually |embedded_surface_size_|. This is used
   // for calculating clipping and scaling.
-  gfx::SizeF embedded_surface_size_;
+  gfx::Size embedded_surface_size_;
 
   DISALLOW_COPY_AND_ASSIGN(Surface);
 };
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc
index af68e2a..a2aedfb 100644
--- a/components/exo/surface_unittest.cc
+++ b/components/exo/surface_unittest.cc
@@ -894,6 +894,64 @@
   }
 }
 
+TEST_P(SurfaceTest, ScaledSurfaceQuad) {
+  gfx::Size buffer_size(1, 1);
+  auto buffer = std::make_unique<Buffer>(
+      exo_test_helper()->CreateGpuMemoryBuffer(buffer_size), GL_TEXTURE_2D, 0,
+      true, true, false);
+  auto surface = std::make_unique<Surface>();
+  auto shell_surface = std::make_unique<ShellSurface>(surface.get());
+  surface->Attach(buffer.get());
+  surface->SetAlpha(1.0f);
+
+  surface->SetEmbeddedSurfaceId(base::BindRepeating([]() -> viz::SurfaceId {
+    return viz::SurfaceId(
+        viz::FrameSinkId(1, 1),
+        viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()));
+  }));
+
+  // A 256x256 surface, of which as 128x128 chunk is selected, drawn into a
+  // 128x64 rect.
+  surface->SetEmbeddedSurfaceSize(gfx::Size(256, 256));
+
+  surface->SetViewport(gfx::Size(128, 64));
+  surface->SetCrop(
+      gfx::RectF(gfx::PointF(32.0f, 32.0f), gfx::SizeF(128.0f, 128.0f)));
+
+  {
+    surface->Commit();
+    base::RunLoop().RunUntilIdle();
+
+    const viz::CompositorFrame& frame =
+        GetFrameFromSurface(shell_surface.get());
+    EXPECT_EQ(1u, frame.render_pass_list.size());
+    EXPECT_EQ(1u, frame.render_pass_list.back()->quad_list.size());
+    EXPECT_EQ(1u, frame.resource_list.size());
+    // Ensure that the quad is correct and the resource is included.
+    EXPECT_EQ(1u, frame.resource_list.back().id);
+    EXPECT_EQ(viz::DrawQuad::Material::kSurfaceContent,
+              frame.render_pass_list.back()->quad_list.back()->material);
+    // We are outputting to 0,0 -> 128,64.
+    EXPECT_EQ(gfx::Rect(gfx::Point(), gfx::Size(128, 64)),
+              frame.render_pass_list.back()
+                  ->quad_list.back()
+                  ->shared_quad_state->clip_rect);
+    // Rect should be the unmodified surface size.
+    EXPECT_EQ(gfx::Rect(gfx::Point(0, 0), gfx::Size(256, 256)),
+              frame.render_pass_list.back()->quad_list.back()->rect);
+    // To get 32,32 -> 160,160 into the correct position it must be translated
+    // backwards and scaled 0.5x in Y, then everything is scaled by the scale
+    // factor.
+    EXPECT_EQ(gfx::Transform(1.0f * device_scale_factor(), 0.0f, 0.0f,
+                             0.5f * device_scale_factor(),
+                             -32.0f * device_scale_factor(),
+                             -16.0f * device_scale_factor()),
+              frame.render_pass_list.back()
+                  ->quad_list.back()
+                  ->shared_quad_state->quad_to_target_transform);
+  }
+}
+
 TEST_P(SurfaceTest, Commit) {
   std::unique_ptr<Surface> surface(new Surface);
 
diff --git a/components/gwp_asan/common/BUILD.gn b/components/gwp_asan/common/BUILD.gn
index dc451bb5..993b7298 100644
--- a/components/gwp_asan/common/BUILD.gn
+++ b/components/gwp_asan/common/BUILD.gn
@@ -13,9 +13,7 @@
     "pack_stack_trace.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
@@ -32,19 +30,11 @@
 }
 
 fuzzer_test("pack_stack_trace_unpack_fuzzer") {
-  sources = [
-    "pack_stack_trace_unpack_fuzzer.cc",
-  ]
-  deps = [
-    "//components/gwp_asan/common",
-  ]
+  sources = [ "pack_stack_trace_unpack_fuzzer.cc" ]
+  deps = [ "//components/gwp_asan/common" ]
 }
 
 fuzzer_test("pack_stack_trace_differential_fuzzer") {
-  sources = [
-    "pack_stack_trace_differential_fuzzer.cc",
-  ]
-  deps = [
-    "//components/gwp_asan/common",
-  ]
+  sources = [ "pack_stack_trace_differential_fuzzer.cc" ]
+  deps = [ "//components/gwp_asan/common" ]
 }
diff --git a/components/gwp_asan/crash_handler/BUILD.gn b/components/gwp_asan/crash_handler/BUILD.gn
index c9aa26ff..dbb66c0a 100644
--- a/components/gwp_asan/crash_handler/BUILD.gn
+++ b/components/gwp_asan/crash_handler/BUILD.gn
@@ -27,16 +27,12 @@
 }
 
 proto_library("crash_proto") {
-  sources = [
-    "crash.proto",
-  ]
+  sources = [ "crash.proto" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "crash_analyzer_unittest.cc",
-  ]
+  sources = [ "crash_analyzer_unittest.cc" ]
 
   deps = [
     ":crash_handler",
diff --git a/components/image_fetcher/core/BUILD.gn b/components/image_fetcher/core/BUILD.gn
index 1e8c44aa..1a4fc0a 100644
--- a/components/image_fetcher/core/BUILD.gn
+++ b/components/image_fetcher/core/BUILD.gn
@@ -25,9 +25,7 @@
     "request_metadata.cc",
     "request_metadata.h",
   ]
-  deps = [
-    ":metrics",
-  ]
+  deps = [ ":metrics" ]
   public_deps = [
     "cache",
     "//base",
@@ -45,9 +43,7 @@
     "image_fetcher_metrics_reporter.cc",
     "image_fetcher_metrics_reporter.h",
   ]
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 static_library("test_support") {
diff --git a/components/image_fetcher/core/cache/BUILD.gn b/components/image_fetcher/core/cache/BUILD.gn
index 4bb6a9ce..a9d97c8 100644
--- a/components/image_fetcher/core/cache/BUILD.gn
+++ b/components/image_fetcher/core/cache/BUILD.gn
@@ -22,9 +22,7 @@
     "//components/prefs",
     "//net",
   ]
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 source_set("cache_unit_tests") {
diff --git a/components/image_fetcher/core/cache/proto/BUILD.gn b/components/image_fetcher/core/cache/proto/BUILD.gn
index 4165d22..60f7184 100644
--- a/components/image_fetcher/core/cache/proto/BUILD.gn
+++ b/components/image_fetcher/core/cache/proto/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "cached_image_metadata.proto",
-  ]
+  sources = [ "cached_image_metadata.proto" ]
 }
diff --git a/components/infobars/core/BUILD.gn b/components/infobars/core/BUILD.gn
index acb9374..c14cdac 100644
--- a/components/infobars/core/BUILD.gn
+++ b/components/infobars/core/BUILD.gn
@@ -25,9 +25,7 @@
     "simple_alert_infobar_delegate.h",
   ]
 
-  public_deps = [
-    "//skia",
-  ]
+  public_deps = [ "//skia" ]
   deps = [
     "//base",
     "//ui/base",
@@ -44,8 +42,6 @@
 
 if (is_android) {
   java_cpp_enum("infobar_enums_java") {
-    sources = [
-      "infobar_delegate.h",
-    ]
+    sources = [ "infobar_delegate.h" ]
   }
 }
diff --git a/components/network_hints/common/BUILD.gn b/components/network_hints/common/BUILD.gn
index 34b399a..f2bfe21 100644
--- a/components/network_hints/common/BUILD.gn
+++ b/components/network_hints/common/BUILD.gn
@@ -6,11 +6,7 @@
 
 mojom("mojo_bindings") {
   generate_java = false
-  sources = [
-    "network_hints.mojom",
-  ]
+  sources = [ "network_hints.mojom" ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_gurl",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_gurl" ]
 }
diff --git a/components/optimization_guide/BUILD.gn b/components/optimization_guide/BUILD.gn
index 278d9f8..ff11d51a 100644
--- a/components/optimization_guide/BUILD.gn
+++ b/components/optimization_guide/BUILD.gn
@@ -45,9 +45,7 @@
     "url_pattern_with_wildcards.h",
   ]
 
-  public_deps = [
-    "//third_party/re2",
-  ]
+  public_deps = [ "//third_party/re2" ]
 
   deps = [
     "//base",
diff --git a/components/performance_manager/embedder/performance_manager_registry.h b/components/performance_manager/embedder/performance_manager_registry.h
index 6a9b3e4d8..022864b 100644
--- a/components/performance_manager/embedder/performance_manager_registry.h
+++ b/components/performance_manager/embedder/performance_manager_registry.h
@@ -8,21 +8,24 @@
 #include <memory>
 
 namespace content {
+class BrowserContext;
 class RenderProcessHost;
 class WebContents;
 }  // namespace content
 
 namespace performance_manager {
 
-// Allows tracking of WebContents and RenderProcessHosts in the
-// PerformanceManager.
+// Allows tracking of WebContents, RenderProcessHosts and SharedWorkerInstances
+// in the PerformanceManager.
 //
 // A process that embeds the PerformanceManager should create a single instance
-// of this and notify it when WebContents or RenderProcessHosts are created.
+// of this and notify it when WebContents, RenderProcessHosts or BrowserContexts
+// are created.
 //
 // TearDown() must be called prior to destroying this object. This will schedule
-// deletion of PageNodes and ProcessNodes retained by this registry, even if the
-// associated WebContents and RenderProcessHosts still exist.
+// deletion of PageNodes, ProcessNodes and WorkerNodes retained by this
+// registry, even if the associated WebContents, RenderProcessHosts and
+// SharedWorkerInstances still exist.
 //
 // This class can only be accessed on the main thread.
 class PerformanceManagerRegistry {
@@ -55,6 +58,14 @@
   virtual void CreateProcessNodeForRenderProcessHost(
       content::RenderProcessHost* render_process_host) = 0;
 
+  // Must be invoked when a BrowserContext is added/removed.
+  // Registers/unregisters an observer that creates WorkerNodes when
+  // SharedWorkerInstances are added in the BrowserContext.
+  virtual void NotifyBrowserContextAdded(
+      content::BrowserContext* browser_context) = 0;
+  virtual void NotifyBrowserContextRemoved(
+      content::BrowserContext* browser_context) = 0;
+
   // Must be invoked prior to destroying the object. Schedules deletion of
   // PageNodes and ProcessNodes retained by this registry, even if the
   // associated WebContents and RenderProcessHosts still exist.
diff --git a/components/performance_manager/performance_manager_registry_impl.cc b/components/performance_manager/performance_manager_registry_impl.cc
index 7a3c1c0d..a84cd39 100644
--- a/components/performance_manager/performance_manager_registry_impl.cc
+++ b/components/performance_manager/performance_manager_registry_impl.cc
@@ -8,12 +8,16 @@
 #include "components/performance_manager/performance_manager_tab_helper.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/performance_manager_main_thread_observer.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
 
 namespace performance_manager {
 
 namespace {
+
 PerformanceManagerRegistryImpl* g_instance = nullptr;
+
 }  // namespace
 
 PerformanceManagerRegistryImpl::PerformanceManagerRegistryImpl() {
@@ -84,6 +88,28 @@
   }
 }
 
+void PerformanceManagerRegistryImpl::NotifyBrowserContextAdded(
+    content::BrowserContext* browser_context) {
+  std::unique_ptr<WorkerWatcher> worker_watcher =
+      std::make_unique<WorkerWatcher>(
+          browser_context->UniqueId(),
+          content::BrowserContext::GetDefaultStoragePartition(browser_context)
+              ->GetSharedWorkerService(),
+          &process_node_source_, &frame_node_source_);
+  auto result = browser_contexts_with_worker_watcher_.insert(
+      {browser_context->UniqueId(), std::move(worker_watcher)});
+  DCHECK(result.second);
+}
+
+void PerformanceManagerRegistryImpl::NotifyBrowserContextRemoved(
+    content::BrowserContext* browser_context) {
+  auto it =
+      browser_contexts_with_worker_watcher_.find(browser_context->UniqueId());
+  DCHECK(it != browser_contexts_with_worker_watcher_.end());
+  it->second->TearDown();
+  browser_contexts_with_worker_watcher_.erase(it);
+}
+
 void PerformanceManagerRegistryImpl::TearDown() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -93,6 +119,14 @@
   // The registry should be torn down before the PerformanceManager.
   DCHECK(PerformanceManager::IsAvailable());
 
+  // Destroy WorkerNodes before ProcessNodes, because ProcessNode checks that it
+  // has no associated WorkerNode when torn down.
+  for (auto& browser_context_and_worker_watcher :
+       browser_contexts_with_worker_watcher_) {
+    browser_context_and_worker_watcher.second->TearDown();
+  }
+  browser_contexts_with_worker_watcher_.clear();
+
   for (auto* web_contents : web_contents_) {
     PerformanceManagerTabHelper* tab_helper =
         PerformanceManagerTabHelper::FromWebContents(web_contents);
diff --git a/components/performance_manager/performance_manager_registry_impl.h b/components/performance_manager/performance_manager_registry_impl.h
index 376989e5..5b885806db 100644
--- a/components/performance_manager/performance_manager_registry_impl.h
+++ b/components/performance_manager/performance_manager_registry_impl.h
@@ -5,12 +5,19 @@
 #ifndef COMPONENTS_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_REGISTRY_IMPL_H_
 #define COMPONENTS_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_REGISTRY_IMPL_H_
 
+#include <memory>
+#include <string>
+
+#include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "base/observer_list.h"
 #include "base/sequence_checker.h"
 #include "components/performance_manager/embedder/performance_manager_registry.h"
 #include "components/performance_manager/performance_manager_tab_helper.h"
+#include "components/performance_manager/process_node_source.h"
 #include "components/performance_manager/render_process_user_data.h"
+#include "components/performance_manager/tab_helper_frame_node_source.h"
+#include "components/performance_manager/worker_watcher.h"
 
 namespace content {
 class RenderProcessHost;
@@ -47,6 +54,10 @@
       content::WebContents* web_contents) override;
   void CreateProcessNodeForRenderProcessHost(
       content::RenderProcessHost* render_process_host) override;
+  void NotifyBrowserContextAdded(
+      content::BrowserContext* browser_context) override;
+  void NotifyBrowserContextRemoved(
+      content::BrowserContext* browser_context) override;
   void TearDown() override;
 
   // PerformanceManagerTabHelper::DestructionObserver:
@@ -65,6 +76,16 @@
   base::flat_set<content::WebContents*> web_contents_;
   base::flat_set<content::RenderProcessHost*> render_process_hosts_;
 
+  // Map of browser context ids for which a WorkerWatcher exists to
+  // corresponding WorkerWatcher.
+  base::flat_map<std::string, std::unique_ptr<WorkerWatcher>>
+      browser_contexts_with_worker_watcher_;
+
+  // Used by WorkerWatchers to access existing process nodes and frame
+  // nodes.
+  performance_manager::ProcessNodeSource process_node_source_;
+  performance_manager::TabHelperFrameNodeSource frame_node_source_;
+
   base::ObserverList<PerformanceManagerMainThreadObserver> observers_;
 };
 
diff --git a/components/safe_browsing/content/common/thread_utils.cc b/components/safe_browsing/content/common/thread_utils.cc
new file mode 100644
index 0000000..34d6ce3
--- /dev/null
+++ b/components/safe_browsing/content/common/thread_utils.cc
@@ -0,0 +1,38 @@
+// 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/safe_browsing/core/common/thread_utils.h"
+
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+namespace safe_browsing {
+
+namespace {
+
+BrowserThread::ID BrowserThreadID(ThreadID thread_id) {
+  switch (thread_id) {
+    case ThreadID::UI:
+      return BrowserThread::UI;
+    case ThreadID::IO:
+      return BrowserThread::IO;
+    default:
+      NOTREACHED();
+      return BrowserThread::UI;
+  }
+}
+
+}  // namespace
+
+bool CurrentlyOnThread(ThreadID thread_id) {
+  return BrowserThread::CurrentlyOn(BrowserThreadID(thread_id));
+}
+
+base::TaskTraits CreateTaskTraits(ThreadID thread_id) {
+  return {BrowserThreadID(thread_id)};
+}
+
+}  // namespace safe_browsing
diff --git a/components/safe_browsing/core/common/BUILD.gn b/components/safe_browsing/core/common/BUILD.gn
index ac5ce8df..278a854b 100644
--- a/components/safe_browsing/core/common/BUILD.gn
+++ b/components/safe_browsing/core/common/BUILD.gn
@@ -6,78 +6,102 @@
 import("//components/safe_browsing/buildflags.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
-source_set("common") {
+# TODO(crbug.com/1028755): Remove this condition once there are no longer any
+# dependencies on content/.
+if (!is_ios) {
+  source_set("common") {
+    sources = [
+      "safebrowsing_constants.cc",
+      "safebrowsing_constants.h",
+      "safebrowsing_switches.cc",
+      "safebrowsing_switches.h",
+      "utils.cc",
+      "utils.h",
+    ]
+
+    deps = [
+      "//base",
+      "//components/policy/core/browser:browser",
+      "//components/prefs:prefs",
+      "//components/safe_browsing/core:csd_proto",
+      "//components/safe_browsing/core:features",
+      "//crypto:crypto",
+      "//ipc",
+      "//url/ipc:url_ipc",
+    ]
+
+    public_deps = [
+      ":interfaces",
+    ]
+  }
+
+  static_library("safe_browsing_prefs") {
+    sources = [
+      "safe_browsing_prefs.cc",
+      "safe_browsing_prefs.h",
+    ]
+
+    deps = [
+      "//base:base",
+      "//components/pref_registry:pref_registry",
+      "//components/prefs",
+      "//components/safe_browsing/core:features",
+      "//content/public/browser:browser",
+      "//net:net",
+    ]
+  }
+
+  source_set("unit_tests") {
+    testonly = true
+    sources = [
+      "safe_browsing_prefs_unittest.cc",
+    ]
+    deps = [
+      ":safe_browsing_prefs",
+      "//base:base",
+      "//base/test:test_support",
+      "//components/prefs:test_support",
+      "//components/safe_browsing/core:features",
+      "//content/test:test_support",
+      "//testing/gtest",
+      "//url:url",
+    ]
+  }
+
+  mojom("interfaces") {
+    sources = [
+      "safe_browsing.mojom",
+    ]
+
+    public_deps = [
+      "//content/public/common:resource_type_bindings",
+      "//services/network/public/mojom",
+      "//url/mojom:url_mojom_gurl",
+    ]
+
+    enabled_features = []
+    if (safe_browsing_mode == 1) {
+      enabled_features += [ "full_safe_browsing" ]
+    }
+  }
+}
+
+source_set("thread_utils") {
   sources = [
-    "safebrowsing_constants.cc",
-    "safebrowsing_constants.h",
-    "safebrowsing_switches.cc",
-    "safebrowsing_switches.h",
-    "utils.cc",
-    "utils.h",
+    "thread_utils.h",
   ]
 
   deps = [
     "//base",
-    "//components/policy/core/browser:browser",
-    "//components/prefs:prefs",
-    "//components/safe_browsing/core:csd_proto",
-    "//components/safe_browsing/core:features",
-    "//crypto:crypto",
-    "//ipc",
-    "//url/ipc:url_ipc",
   ]
 
-  public_deps = [
-    ":interfaces",
-  ]
-}
+  if (is_ios) {
+    sources += [ "//components/safe_browsing/ios/thread_utils_ios.cc" ]
 
-static_library("safe_browsing_prefs") {
-  sources = [
-    "safe_browsing_prefs.cc",
-    "safe_browsing_prefs.h",
-  ]
+    deps += [ "//ios/web/public/thread" ]
+  } else {
+    sources += [ "//components/safe_browsing/content/common/thread_utils.cc" ]
 
-  deps = [
-    "//base:base",
-    "//components/pref_registry:pref_registry",
-    "//components/prefs",
-    "//components/safe_browsing/core:features",
-    "//content/public/browser:browser",
-    "//net:net",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "safe_browsing_prefs_unittest.cc",
-  ]
-  deps = [
-    ":safe_browsing_prefs",
-    "//base:base",
-    "//base/test:test_support",
-    "//components/prefs:test_support",
-    "//components/safe_browsing/core:features",
-    "//content/test:test_support",
-    "//testing/gtest",
-    "//url:url",
-  ]
-}
-
-mojom("interfaces") {
-  sources = [
-    "safe_browsing.mojom",
-  ]
-
-  public_deps = [
-    "//content/public/common:resource_type_bindings",
-    "//services/network/public/mojom",
-    "//url/mojom:url_mojom_gurl",
-  ]
-
-  enabled_features = []
-  if (safe_browsing_mode == 1) {
-    enabled_features += [ "full_safe_browsing" ]
+    deps += [ "//content/public/browser" ]
   }
 }
diff --git a/components/safe_browsing/core/common/thread_utils.h b/components/safe_browsing/core/common/thread_utils.h
new file mode 100644
index 0000000..3e16d449
--- /dev/null
+++ b/components/safe_browsing/core/common/thread_utils.h
@@ -0,0 +1,36 @@
+// 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_SAFE_BROWSING_CORE_COMMON_THREAD_UTILS_H_
+#define COMPONENTS_SAFE_BROWSING_CORE_COMMON_THREAD_UTILS_H_
+
+#include "base/task/task_traits.h"
+
+namespace safe_browsing {
+
+// Safe Browsing thread-related utility functions, which need separate
+// implementations for content/ clients and for ios/ since content/ and ios/
+// use distinct classes for representing threads (content::BrowserThread and
+// web::WebThread).
+
+// An enumeration of well-known threads.
+enum class ThreadID {
+  // The main thread in the browser.
+  UI,
+
+  // The thread that processes non-blocking IO (IPC and network).
+  IO,
+};
+
+// Callable on any thread. Returns true if the current thread matches the given
+// identifier.
+bool CurrentlyOnThread(ThreadID thread_id) WARN_UNUSED_RESULT;
+
+// Callable on any thread. Returns TaskTraits for running a task on the given
+// thread.
+base::TaskTraits CreateTaskTraits(ThreadID thread_id);
+
+}  // namespace safe_browsing
+
+#endif  // COMPONENTS_SAFE_BROWSING_CORE_COMMON_THREAD_UTILS_H_
diff --git a/components/safe_browsing/core/db/BUILD.gn b/components/safe_browsing/core/db/BUILD.gn
index e8a5e2c..ef7adf4 100644
--- a/components/safe_browsing/core/db/BUILD.gn
+++ b/components/safe_browsing/core/db/BUILD.gn
@@ -169,11 +169,12 @@
     "//base",
     "//build:branding_buildflags",
     "//components/safe_browsing/core:webui_proto",
+    "//components/safe_browsing/core/common:thread_utils",
     "//components/safe_browsing/core/realtime:policy_engine",
     "//components/safe_browsing/core/realtime:url_lookup_service",
-    "//content/public/browser",
     "//crypto",
     "//net",
+    "//services/network/public/cpp",
     "//url",
   ]
 }
diff --git a/components/safe_browsing/core/db/v4_local_database_manager.cc b/components/safe_browsing/core/db/v4_local_database_manager.cc
index a323cb16..7f85259 100644
--- a/components/safe_browsing/core/db/v4_local_database_manager.cc
+++ b/components/safe_browsing/core/db/v4_local_database_manager.cc
@@ -17,15 +17,12 @@
 #include "base/strings/string_tokenizer.h"
 #include "base/task/post_task.h"
 #include "build/branding_buildflags.h"
+#include "components/safe_browsing/core/common/thread_utils.h"
 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
 #include "components/safe_browsing/core/realtime/policy_engine.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
 #include "crypto/sha2.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
-using content::BrowserThread;
-
 namespace safe_browsing {
 
 namespace {
@@ -284,7 +281,7 @@
 //
 
 void V4LocalDatabaseManager::CancelCheck(Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
   DCHECK(enabled_);
 
   auto pending_it = std::find_if(
@@ -322,7 +319,7 @@
 bool V4LocalDatabaseManager::CheckBrowseUrl(const GURL& url,
                                             const SBThreatTypeSet& threat_types,
                                             Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
   DCHECK(!threat_types.empty());
   DCHECK(SBThreatTypeSetIsValidForCheckBrowseUrl(threat_types));
 
@@ -344,7 +341,7 @@
 bool V4LocalDatabaseManager::CheckDownloadUrl(
     const std::vector<GURL>& url_chain,
     Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   if (!enabled_ || url_chain.empty()) {
     return true;
@@ -360,7 +357,7 @@
 bool V4LocalDatabaseManager::CheckExtensionIDs(
     const std::set<FullHash>& extension_ids,
     Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   if (!enabled_) {
     return true;
@@ -374,7 +371,7 @@
 }
 
 bool V4LocalDatabaseManager::CheckResourceUrl(const GURL& url, Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check({GetChromeUrlClientIncidentId()});
 
@@ -397,7 +394,7 @@
 AsyncMatch V4LocalDatabaseManager::CheckUrlForHighConfidenceAllowlist(
     const GURL& url,
     Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check({GetUrlHighConfidenceAllowlistId()});
   if (!enabled_ || !CanCheckUrl(url) ||
@@ -418,7 +415,7 @@
 
 bool V4LocalDatabaseManager::CheckUrlForSubresourceFilter(const GURL& url,
                                                           Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check(
       {GetUrlSocEngId(), GetUrlSubresourceFilterId()});
@@ -435,7 +432,7 @@
 
 AsyncMatch V4LocalDatabaseManager::CheckCsdWhitelistUrl(const GURL& url,
                                                         Client* client) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check({GetUrlCsdWhitelistId()});
   if (!AreAllStoresAvailableNow(stores_to_check) || !CanCheckUrl(url)) {
@@ -457,7 +454,7 @@
 
 bool V4LocalDatabaseManager::MatchDownloadWhitelistString(
     const std::string& str) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check({GetCertCsdDownloadWhitelistId()});
   if (!AreAllStoresAvailableNow(stores_to_check)) {
@@ -471,7 +468,7 @@
 }
 
 bool V4LocalDatabaseManager::MatchDownloadWhitelistUrl(const GURL& url) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   StoresToCheck stores_to_check({GetUrlCsdDownloadWhitelistId()});
 
@@ -485,7 +482,7 @@
 }
 
 bool V4LocalDatabaseManager::MatchMalwareIP(const std::string& ip_address) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
   if (!enabled_ || !v4_database_) {
     return false;
   }
@@ -532,7 +529,7 @@
 }
 
 void V4LocalDatabaseManager::StopOnIOThread(bool shutdown) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   enabled_ = false;
 
@@ -564,7 +561,7 @@
 
 void V4LocalDatabaseManager::DatabaseReadyForChecks(
     std::unique_ptr<V4Database> v4_database) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   // The following check is needed because it is possible that by the time the
   // database is ready, StopOnIOThread has been called.
@@ -610,7 +607,7 @@
     UpdateListClientStates(GetStoreStateMap());
 
     base::PostTask(
-        FROM_HERE, {BrowserThread::UI},
+        FROM_HERE, CreateTaskTraits(ThreadID::UI),
         base::BindOnce(
             &SafeBrowsingDatabaseManager::NotifyDatabaseUpdateFinished, this));
   }
@@ -664,7 +661,7 @@
 
 bool V4LocalDatabaseManager::GetPrefixMatches(
     const std::unique_ptr<PendingCheck>& check) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
   DCHECK(enabled_);
 
   check->full_hash_to_store_and_hash_prefixes.clear();
@@ -800,7 +797,7 @@
 
 void V4LocalDatabaseManager::ScheduleFullHashCheck(
     std::unique_ptr<PendingCheck> check) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   // Add check to pending_checks_ before scheduling PerformFullHashCheck so that
   // even if the client calls CancelCheck before PerformFullHashCheck gets
@@ -820,14 +817,14 @@
         full_hash_infos.emplace_back(entry.first, list_id, next);
       }
     }
-    base::PostTask(FROM_HERE, {BrowserThread::IO},
+    base::PostTask(FROM_HERE, CreateTaskTraits(ThreadID::IO),
                    base::BindOnce(&V4LocalDatabaseManager::OnFullHashResponse,
                                   weak_factory_.GetWeakPtr(), std::move(check),
                                   full_hash_infos));
   } else {
     // Post on the IO thread to enforce async behavior.
     base::PostTask(
-        FROM_HERE, {BrowserThread::IO},
+        FROM_HERE, CreateTaskTraits(ThreadID::IO),
         base::BindOnce(&V4LocalDatabaseManager::PerformFullHashCheck,
                        weak_factory_.GetWeakPtr(), std::move(check)));
   }
@@ -836,7 +833,7 @@
 bool V4LocalDatabaseManager::HandleHashSynchronously(
     const FullHash& hash,
     const StoresToCheck& stores_to_check) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   std::set<FullHash> hashes{hash};
   std::unique_ptr<PendingCheck> check = std::make_unique<PendingCheck>(
@@ -848,7 +845,7 @@
 bool V4LocalDatabaseManager::HandleUrlSynchronously(
     const GURL& url,
     const StoresToCheck& stores_to_check) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   std::unique_ptr<PendingCheck> check = std::make_unique<PendingCheck>(
       nullptr, ClientCallbackType::CHECK_OTHER, stores_to_check,
@@ -860,7 +857,7 @@
 void V4LocalDatabaseManager::OnFullHashResponse(
     std::unique_ptr<PendingCheck> check,
     const std::vector<FullHashInfo>& full_hash_infos) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   if (!enabled_) {
     DCHECK(pending_checks_.empty());
@@ -884,7 +881,7 @@
 
 void V4LocalDatabaseManager::PerformFullHashCheck(
     std::unique_ptr<PendingCheck> check) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   DCHECK(enabled_);
   DCHECK(!check->full_hash_to_store_and_hash_prefixes.empty());
@@ -898,7 +895,7 @@
 }
 
 void V4LocalDatabaseManager::ProcessQueuedChecks() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   // Steal the queue to protect against reentrant CancelCheck() calls.
   QueuedChecks checks;
@@ -915,7 +912,7 @@
 }
 
 void V4LocalDatabaseManager::RespondSafeToQueuedChecks() {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   // Steal the queue to protect against reentrant CancelCheck() calls.
   QueuedChecks checks;
@@ -990,7 +987,7 @@
 void V4LocalDatabaseManager::SetupDatabase() {
   DCHECK(!base_path_.empty());
   DCHECK(!list_infos_.empty());
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   // Do not create the database on the IO thread since this may be an expensive
   // operation. Instead, do that on the task_runner and when the new database
@@ -1004,7 +1001,7 @@
 
 void V4LocalDatabaseManager::SetupRealTimeUrlLookupService(
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
 
   rt_url_lookup_service_ =
       std::make_unique<RealTimeUrlLookupService>(url_loader_factory);
@@ -1024,7 +1021,7 @@
 
 void V4LocalDatabaseManager::UpdateRequestCompleted(
     std::unique_ptr<ParsedServerResponse> parsed_server_response) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK(CurrentlyOnThread(ThreadID::IO));
   v4_database_->ApplyUpdate(std::move(parsed_server_response),
                             db_updated_callback_);
 }
diff --git a/components/safe_browsing/ios/BUILD.gn b/components/safe_browsing/ios/BUILD.gn
new file mode 100644
index 0000000..cfbbc6e2
--- /dev/null
+++ b/components/safe_browsing/ios/BUILD.gn
@@ -0,0 +1,12 @@
+# 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.
+
+# As parts of components/safe_browsing become buildable on iOS, they will
+# be added here.
+source_set("unit_tests") {
+  testonly = true
+  deps = [
+    "//components/safe_browsing/core/common:thread_utils",
+  ]
+}
diff --git a/components/safe_browsing/ios/DEPS b/components/safe_browsing/ios/DEPS
new file mode 100644
index 0000000..0fc0ddd
--- /dev/null
+++ b/components/safe_browsing/ios/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ios/web/public",
+]
diff --git a/components/safe_browsing/ios/thread_utils_ios.cc b/components/safe_browsing/ios/thread_utils_ios.cc
new file mode 100644
index 0000000..d155b24
--- /dev/null
+++ b/components/safe_browsing/ios/thread_utils_ios.cc
@@ -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.
+
+#include "components/safe_browsing/core/common/thread_utils.h"
+
+#include "ios/web/public/thread/web_task_traits.h"
+#include "ios/web/public/thread/web_thread.h"
+
+using web::WebThread;
+
+namespace safe_browsing {
+
+static WebThread::ID WebThreadID(ThreadID thread_id) {
+  switch (thread_id) {
+    case ThreadID::UI:
+      return WebThread::UI;
+    case ThreadID::IO:
+      return WebThread::IO;
+    default:
+      NOTREACHED();
+      return WebThread::UI;
+  }
+}
+
+bool CurrentlyOnThread(ThreadID thread_id) {
+  return WebThread::CurrentlyOn(WebThreadID(thread_id));
+}
+
+base::TaskTraits CreateTaskTraits(ThreadID thread_id) {
+  return {WebThreadID(thread_id)};
+}
+
+}  // namespace safe_browsing
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn
index 8f58aad..2cb036e4 100644
--- a/components/signin/core/browser/android/BUILD.gn
+++ b/components/signin/core/browser/android/BUILD.gn
@@ -80,9 +80,7 @@
     "//third_party/junit",
   ]
 
-  sources = [
-    "javatests/src/org/chromium/components/signin/test/AccountManagerFacadeTest.java",
-  ]
+  sources = [ "javatests/src/org/chromium/components/signin/test/AccountManagerFacadeTest.java" ]
 }
 
 android_library("signin_java_test_support") {
diff --git a/components/signin/public/base/BUILD.gn b/components/signin/public/base/BUILD.gn
index dea58bf..056d2e0 100644
--- a/components/signin/public/base/BUILD.gn
+++ b/components/signin/public/base/BUILD.gn
@@ -56,9 +56,7 @@
 
 if (is_android) {
   java_cpp_enum("signin_metrics_enum_javagen") {
-    sources = [
-      "signin_metrics.h",
-    ]
+    sources = [ "signin_metrics.h" ]
   }
 }
 
diff --git a/components/signin/public/identity_manager/BUILD.gn b/components/signin/public/identity_manager/BUILD.gn
index f388cb1e..bc263c6c0 100644
--- a/components/signin/public/identity_manager/BUILD.gn
+++ b/components/signin/public/identity_manager/BUILD.gn
@@ -78,9 +78,7 @@
 
 if (is_android) {
   java_cpp_enum("identity_manager_enum_javagen") {
-    sources = [
-      "primary_account_mutator.h",
-    ]
+    sources = [ "primary_account_mutator.h" ]
   }
 }
 
diff --git a/components/signin/public/identity_manager/ios/BUILD.gn b/components/signin/public/identity_manager/ios/BUILD.gn
index 0f06fb4..7ab9b68 100644
--- a/components/signin/public/identity_manager/ios/BUILD.gn
+++ b/components/signin/public/identity_manager/ios/BUILD.gn
@@ -10,9 +10,7 @@
     "device_accounts_provider.mm",
   ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 source_set("test_support") {
diff --git a/components/signin/public/identity_manager/objc/BUILD.gn b/components/signin/public/identity_manager/objc/BUILD.gn
index ba323fe7..950157c 100644
--- a/components/signin/public/identity_manager/objc/BUILD.gn
+++ b/components/signin/public/identity_manager/objc/BUILD.gn
@@ -9,7 +9,5 @@
     "identity_manager_observer_bridge.mm",
   ]
 
-  public_deps = [
-    "//components/signin/public/identity_manager",
-  ]
+  public_deps = [ "//components/signin/public/identity_manager" ]
 }
diff --git a/components/signin/public/webdata/BUILD.gn b/components/signin/public/webdata/BUILD.gn
index a301f77..b805aa0 100644
--- a/components/signin/public/webdata/BUILD.gn
+++ b/components/signin/public/webdata/BUILD.gn
@@ -24,9 +24,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "token_service_table_unittest.cc",
-  ]
+  sources = [ "token_service_table_unittest.cc" ]
 
   deps = [
     ":webdata",
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 0cd3c22..dabba2b0 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -148,9 +148,7 @@
     "test_installer.h",
   ]
 
-  public_deps = [
-    ":update_client",
-  ]
+  public_deps = [ ":update_client" ]
 
   deps = [
     ":network_impl",
@@ -188,22 +186,16 @@
     "//components/test/data/update_client/updatecheck_reply_parse_error.json",
     "//components/test/data/update_client/updatecheck_reply_unknownapp.json",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 bundle_data("recovery_component_tests_bundle_data") {
   visibility = [ "//chrome/test:unit_tests" ]
   testonly = true
-  sources = [
-    "//components/test/data/update_client/ChromeRecovery.crx3",
-  ]
-  outputs = [
-    "{{bundle_resources_dir}}/" +
-        "{{source_root_relative_dir}}/{{source_file_part}}",
-  ]
+  sources = [ "//components/test/data/update_client/ChromeRecovery.crx3" ]
+  outputs = [ "{{bundle_resources_dir}}/" +
+              "{{source_root_relative_dir}}/{{source_file_part}}" ]
 }
 
 source_set("unit_tests") {
@@ -255,9 +247,7 @@
 }
 
 fuzzer_test("update_client_protocol_serializer_fuzzer") {
-  sources = [
-    "protocol_serializer_fuzzer.cc",
-  ]
+  sources = [ "protocol_serializer_fuzzer.cc" ]
   deps = [
     ":update_client",
     "//base:base",
@@ -266,9 +256,7 @@
 }
 
 fuzzer_test("update_client_protocol_parser_fuzzer") {
-  sources = [
-    "protocol_parser_fuzzer.cc",
-  ]
+  sources = [ "protocol_parser_fuzzer.cc" ]
   deps = [
     ":update_client",
     "//base:base",
diff --git a/components/url_formatter/BUILD.gn b/components/url_formatter/BUILD.gn
index 1d35ee87..6902e60 100644
--- a/components/url_formatter/BUILD.gn
+++ b/components/url_formatter/BUILD.gn
@@ -51,9 +51,7 @@
     "//url",
   ]
 
-  public_deps = [
-    "//third_party/icu",
-  ]
+  public_deps = [ "//third_party/icu" ]
 
   if (is_android) {
     deps += [ "android:jni_headers" ]
diff --git a/components/url_formatter/android/BUILD.gn b/components/url_formatter/android/BUILD.gn
index 523bd8c..45cbb07 100644
--- a/components/url_formatter/android/BUILD.gn
+++ b/components/url_formatter/android/BUILD.gn
@@ -11,13 +11,11 @@
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
 
-  sources = [
-    "java/src/org/chromium/components/url_formatter/UrlFormatter.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/components/url_formatter/UrlFormatter.java" ]
 }
 
 generate_jni("jni_headers") {
-  sources = [
-    "java/src/org/chromium/components/url_formatter/UrlFormatter.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/components/url_formatter/UrlFormatter.java" ]
 }
diff --git a/components/url_formatter/spoof_checks/top_domains/BUILD.gn b/components/url_formatter/spoof_checks/top_domains/BUILD.gn
index 17db64b..e92e939 100644
--- a/components/url_formatter/spoof_checks/top_domains/BUILD.gn
+++ b/components/url_formatter/spoof_checks/top_domains/BUILD.gn
@@ -6,9 +6,7 @@
 
 if (!is_ios && !is_android) {
   executable("make_top_domain_skeletons") {
-    sources = [
-      "make_top_domain_skeletons.cc",
-    ]
+    sources = [ "make_top_domain_skeletons.cc" ]
 
     deps = [
       "//base",
@@ -46,9 +44,7 @@
     "//components/url_formatter/spoof_checks/top_domains/domains.skeletons",
     "//components/url_formatter/spoof_checks/top_domains/top_domains_trie.template",
   ]
-  outputs = [
-    "$target_gen_dir/domains-trie-inc.cc",
-  ]
+  outputs = [ "$target_gen_dir/domains-trie-inc.cc" ]
   args =
       rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
 }
@@ -63,9 +59,7 @@
     "//components/url_formatter/spoof_checks/top_domains/test_domains.skeletons",
     "//components/url_formatter/spoof_checks/top_domains/top_domains_trie.template",
   ]
-  outputs = [
-    "$target_gen_dir/test_domains-trie-inc.cc",
-  ]
+  outputs = [ "$target_gen_dir/test_domains-trie-inc.cc" ]
 
   # Passing --for_testing flag marks only the first site with is_top_500.
   args = rebase_path(inputs, root_build_dir) +
@@ -73,9 +67,7 @@
 }
 
 executable("make_top_domain_list_variables") {
-  sources = [
-    "make_top_domain_list_variables.cc",
-  ]
+  sources = [ "make_top_domain_list_variables.cc" ]
   deps = [
     ":common",
     "//base",
@@ -101,9 +93,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "top_domain_util_unittest.cc",
-  ]
+  sources = [ "top_domain_util_unittest.cc" ]
   deps = [
     ":common",
     "//testing/gtest",
@@ -116,12 +106,9 @@
   tool = ":make_top_domain_list_variables"
 
   # Inputs in order expected by the command line of the tool.
-  inputs = [
-    "//components/url_formatter/spoof_checks/top_domains/domains.list",
-  ]
-  outputs = [
-    "$target_gen_dir/top500-domains-inc.cc",
-  ]
+  inputs =
+      [ "//components/url_formatter/spoof_checks/top_domains/domains.list" ]
+  outputs = [ "$target_gen_dir/top500-domains-inc.cc" ]
   args =
       rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
 }
@@ -133,9 +120,7 @@
   # This empty public is intentional to remove unnecessary build dependency.
   public = []
 
-  sources = [
-    "$target_gen_dir/top500-domains-inc.cc",
-  ]
+  sources = [ "$target_gen_dir/top500-domains-inc.cc" ]
 
   deps = [
     ":generate_top_domain_list_variables_file",
@@ -144,7 +129,5 @@
 }
 
 source_set("top500_domains_header") {
-  sources = [
-    "top500_domains.h",
-  ]
+  sources = [ "top500_domains.h" ]
 }
diff --git a/components/url_formatter/tools/BUILD.gn b/components/url_formatter/tools/BUILD.gn
index c46bcfa4..cb471141 100644
--- a/components/url_formatter/tools/BUILD.gn
+++ b/components/url_formatter/tools/BUILD.gn
@@ -3,9 +3,7 @@
 # found in the LICENSE file.
 
 executable("format_url") {
-  sources = [
-    "format_url.cc",
-  ]
+  sources = [ "format_url.cc" ]
   deps = [
     "//base",
     "//base:i18n",
diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn
index 4132923e4..c4b12fd 100644
--- a/components/user_manager/BUILD.gn
+++ b/components/user_manager/BUILD.gn
@@ -20,9 +20,7 @@
     "//ui/gfx",
   ]
 
-  deps = [
-    "//google_apis",
-  ]
+  deps = [ "//google_apis" ]
 
   defines = [ "USER_MANAGER_IMPLEMENTATION" ]
 
@@ -65,16 +63,12 @@
       "//components/account_id",
     ]
 
-    deps = [
-      "//chromeos/constants",
-    ]
+    deps = [ "//chromeos/constants" ]
   }
 
   source_set("unit_tests") {
     testonly = true
-    sources = [
-      "user_unittest.cc",
-    ]
+    sources = [ "user_unittest.cc" ]
     deps = [
       ":user_manager",
       "//components/account_id",
diff --git a/components/viz/BUILD.gn b/components/viz/BUILD.gn
index b71518b..391870a 100644
--- a/components/viz/BUILD.gn
+++ b/components/viz/BUILD.gn
@@ -6,9 +6,7 @@
 import("//testing/test.gni")
 
 viz_test("viz_unittests") {
-  sources = [
-    "test/run_all_unittests.cc",
-  ]
+  sources = [ "test/run_all_unittests.cc" ]
   deps = [
     "//base",
     "//base/test:test_support",
@@ -22,9 +20,7 @@
     "//mojo/core/embedder",
   ]
 
-  data = [
-    "test/data/",
-  ]
+  data = [ "test/data/" ]
 
   data_deps = [
     "//testing/buildbot/filters:viz_unittests_filters",
@@ -38,9 +34,7 @@
 }
 
 viz_test("viz_perftests") {
-  sources = [
-    "test/run_all_perftests.cc",
-  ]
+  sources = [ "test/run_all_perftests.cc" ]
 
   deps = [
     "//base",
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 57613d5..304cdb98 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -8,9 +8,7 @@
 import("//testing/test.gni")
 
 source_set("resource_format") {
-  sources = [
-    "resources/resource_format.h",
-  ]
+  sources = [ "resources/resource_format.h" ]
 }
 
 viz_component("resource_format_utils") {
@@ -27,9 +25,7 @@
 
   configs = [ "//third_party/khronos:khronos_headers" ]
 
-  public_deps = [
-    ":resource_format",
-  ]
+  public_deps = [ ":resource_format" ]
 
   deps = [
     "//base",
@@ -58,9 +54,7 @@
       "viz_metal_context_provider_export.h",
     ]
 
-    public_deps = [
-      "//skia",
-    ]
+    public_deps = [ "//skia" ]
 
     deps = [
       "//base",
@@ -98,9 +92,7 @@
     ]
     configs = [ "//third_party/vulkan:vulkan_config" ]
 
-    public_deps = [
-      "//skia",
-    ]
+    public_deps = [ "//skia" ]
 
     deps = [
       "//base",
@@ -391,9 +383,7 @@
 # Microbenchmark to measure performance of GLHelper code, for use in
 # debugging, profiling, and optimizing.
 viz_test("viz_benchmark") {
-  sources = [
-    "gl_helper_benchmark.cc",
-  ]
+  sources = [ "gl_helper_benchmark.cc" ]
 
   configs = [
     "//build/config/compiler:no_size_t_to_int_warning",
@@ -415,16 +405,12 @@
     "//ui/gfx",
   ]
 
-  data_deps = [
-    "//third_party/mesa_headers",
-  ]
+  data_deps = [ "//third_party/mesa_headers" ]
 }
 
 viz_source_set("perf_tests") {
   testonly = true
-  sources = [
-    "quads/draw_quad_perftest.cc",
-  ]
+  sources = [ "quads/draw_quad_perftest.cc" ]
 
   deps = [
     ":common",
@@ -438,9 +424,7 @@
 
 if (is_android) {
   android_library("common_java") {
-    deps = [
-      "//base:base_java",
-    ]
+    deps = [ "//base:base_java" ]
     sources = [
       "java/src/org/chromium/components/viz/common/VizSwitches.java",
       "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
diff --git a/components/viz/demo/BUILD.gn b/components/viz/demo/BUILD.gn
index c1b15ad..9f6678a4 100644
--- a/components/viz/demo/BUILD.gn
+++ b/components/viz/demo/BUILD.gn
@@ -51,9 +51,7 @@
 }
 
 executable("viz_demo") {
-  sources = [
-    "demo_main.cc",
-  ]
+  sources = [ "demo_main.cc" ]
 
   deps = [
     "//base",
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn
index fe68a699..4b95bb4c 100644
--- a/components/viz/host/BUILD.gn
+++ b/components/viz/host/BUILD.gn
@@ -95,9 +95,7 @@
 }
 
 fuzzer_test("hit_test_query_fuzzer") {
-  sources = [
-    "hit_test/hit_test_query_fuzzer.cc",
-  ]
+  sources = [ "hit_test/hit_test_query_fuzzer.cc" ]
 
   libfuzzer_options = [ "max_len=4096" ]
 
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 135c8bd4..3ae55c4 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -571,9 +571,7 @@
 }
 
 fuzzer_test("hit_test_manager_fuzzer") {
-  sources = [
-    "hit_test/hit_test_manager_fuzzer.cc",
-  ]
+  sources = [ "hit_test/hit_test_manager_fuzzer.cc" ]
 
   libfuzzer_options = [ "max_len=81920" ]
 
diff --git a/components/viz/service/compositor_frame_fuzzer/BUILD.gn b/components/viz/service/compositor_frame_fuzzer/BUILD.gn
index b2b1c76..175cc8f5 100644
--- a/components/viz/service/compositor_frame_fuzzer/BUILD.gn
+++ b/components/viz/service/compositor_frame_fuzzer/BUILD.gn
@@ -10,9 +10,7 @@
 }
 
 proto_library("compositor_frame_fuzzer_proto") {
-  sources = [
-    "compositor_frame_fuzzer.proto",
-  ]
+  sources = [ "compositor_frame_fuzzer.proto" ]
 }
 
 # Encodes text-format protobuf messages into binary-format protobuf
@@ -33,9 +31,7 @@
     "$input_dir/overlapping_quads_in_render_pass_draw_quad.asciipb",
     "$input_dir/solid_color_tiled_background_with_2_quads_on_top.asciipb",
   ]
-  outputs = [
-    "$seed_corpus_dir/{{source_name_part}}.pb",
-  ]
+  outputs = [ "$seed_corpus_dir/{{source_name_part}}.pb" ]
 
   deps = [
     ":compositor_frame_fuzzer_proto",
diff --git a/components/viz/service/main/BUILD.gn b/components/viz/service/main/BUILD.gn
index 80537bf..9fa3198 100644
--- a/components/viz/service/main/BUILD.gn
+++ b/components/viz/service/main/BUILD.gn
@@ -38,9 +38,7 @@
     "//ui/gl/init",
   ]
 
-  public_deps = [
-    "//services/network/public/mojom",
-  ]
+  public_deps = [ "//services/network/public/mojom" ]
 
   if (use_ozone) {
     deps += [ "//ui/ozone:ozone" ]
diff --git a/components/webdata_services/BUILD.gn b/components/webdata_services/BUILD.gn
index 7c7e85b..9ca146b 100644
--- a/components/webdata_services/BUILD.gn
+++ b/components/webdata_services/BUILD.gn
@@ -31,9 +31,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "web_data_service_wrapper_unittest.cc",
-  ]
+  sources = [ "web_data_service_wrapper_unittest.cc" ]
 
   deps = [
     ":webdata_services",
diff --git a/components/zoom/BUILD.gn b/components/zoom/BUILD.gn
index f2813cef..a81c62e 100644
--- a/components/zoom/BUILD.gn
+++ b/components/zoom/BUILD.gn
@@ -45,9 +45,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "page_zoom_unittests.cc",
-  ]
+  sources = [ "page_zoom_unittests.cc" ]
   deps = [
     ":zoom",
     "//components/prefs",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 9eaa65f..c14ff8b9 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -111,7 +111,6 @@
     case ax::mojom::IntAttribute::kColor:
     case ax::mojom::IntAttribute::kColorValue:
     case ax::mojom::IntAttribute::kDOMNodeId:
-    case ax::mojom::IntAttribute::kDetailsId:
     case ax::mojom::IntAttribute::kErrormessageId:
     case ax::mojom::IntAttribute::kHierarchicalLevel:
     case ax::mojom::IntAttribute::kInPageLinkTargetId:
diff --git a/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc b/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
index e282906..230b7099 100644
--- a/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
+++ b/content/browser/accessibility/one_shot_accessibility_tree_search_unittest.cc
@@ -38,19 +38,10 @@
 
 }  // namespace
 
-// These tests prevent other tests from being run. crbug.com/514632
-#if defined(ANDROID) && defined(ADDRESS_SANITIZER)
-#define MAYBE_OneShotAccessibilityTreeSearchTest \
-  DISABLED_OneShotAccessibilityTreeSearchTest
-#else
-#define MAYBE_OneShotAccessibilityTreeSearchTest \
-  OneShotAccessibilityTreeSearchTest
-#endif
-class MAYBE_OneShotAccessibilityTreeSearchTest
-    : public testing::TestWithParam<bool> {
+class OneShotAccessibilityTreeSearchTest : public testing::TestWithParam<bool> {
  public:
-  MAYBE_OneShotAccessibilityTreeSearchTest() {}
-  ~MAYBE_OneShotAccessibilityTreeSearchTest() override {}
+  OneShotAccessibilityTreeSearchTest() {}
+  ~OneShotAccessibilityTreeSearchTest() override {}
 
  protected:
   void SetUp() override;
@@ -60,10 +51,10 @@
   std::unique_ptr<BrowserAccessibilityManager> tree_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MAYBE_OneShotAccessibilityTreeSearchTest);
+  DISALLOW_COPY_AND_ASSIGN(OneShotAccessibilityTreeSearchTest);
 };
 
-void MAYBE_OneShotAccessibilityTreeSearchTest::SetUp() {
+void OneShotAccessibilityTreeSearchTest::SetUp() {
   ui::AXNodeData root;
   root.id = 1;
   root.SetName("Document");
@@ -139,12 +130,12 @@
       table_column_header_2, list, list_item_1, list_item_2, footer)));
 }
 
-TEST_F(MAYBE_OneShotAccessibilityTreeSearchTest, GetAll) {
+TEST_F(OneShotAccessibilityTreeSearchTest, GetAll) {
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   ASSERT_EQ(10U, search.CountMatches());
 }
 
-TEST_F(MAYBE_OneShotAccessibilityTreeSearchTest, BackwardsWrapFromRoot) {
+TEST_F(OneShotAccessibilityTreeSearchTest, BackwardsWrapFromRoot) {
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetDirection(OneShotAccessibilityTreeSearch::BACKWARDS);
   search.SetResultLimit(100);
@@ -162,7 +153,7 @@
   EXPECT_EQ(2, search.GetMatchAtIndex(9)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, NoCycle) {
+TEST_P(OneShotAccessibilityTreeSearchTest, NoCycle) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   // If you set a result limit of 1, you won't get the root node back as
   // the first match.
@@ -172,7 +163,7 @@
   EXPECT_NE(1, search.GetMatchAtIndex(0)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, ForwardsWithStartNode) {
+TEST_P(OneShotAccessibilityTreeSearchTest, ForwardsWithStartNode) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetStartNode(tree_->GetFromID(7));
@@ -182,7 +173,7 @@
   EXPECT_EQ(10, search.GetMatchAtIndex(2)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, BackwardsWithStartNode) {
+TEST_P(OneShotAccessibilityTreeSearchTest, BackwardsWithStartNode) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetStartNode(tree_->GetFromID(4));
@@ -193,8 +184,7 @@
   EXPECT_EQ(1, search.GetMatchAtIndex(2)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest,
-       BackwardsWithStartNodeForAndroid) {
+TEST_P(OneShotAccessibilityTreeSearchTest, BackwardsWithStartNodeForAndroid) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetStartNode(tree_->GetFromID(4));
@@ -207,8 +197,7 @@
   EXPECT_EQ(1, search.GetMatchAtIndex(2)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest,
-       ForwardsWithStartNodeAndScope) {
+TEST_P(OneShotAccessibilityTreeSearchTest, ForwardsWithStartNodeAndScope) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetFromID(7));
   search.SetStartNode(tree_->GetFromID(8));
@@ -217,21 +206,21 @@
   EXPECT_EQ(10, search.GetMatchAtIndex(1)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, ResultLimitZero) {
+TEST_P(OneShotAccessibilityTreeSearchTest, ResultLimitZero) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetResultLimit(0);
   ASSERT_EQ(0U, search.CountMatches());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, ResultLimitFive) {
+TEST_P(OneShotAccessibilityTreeSearchTest, ResultLimitFive) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetResultLimit(5);
   ASSERT_EQ(5U, search.CountMatches());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, DescendantsOnlyOfRoot) {
+TEST_P(OneShotAccessibilityTreeSearchTest, DescendantsOnlyOfRoot) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetStartNode(tree_->GetFromID(1));
@@ -243,7 +232,7 @@
   EXPECT_EQ(10, search.GetMatchAtIndex(3)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, DescendantsOnlyOfNode) {
+TEST_P(OneShotAccessibilityTreeSearchTest, DescendantsOnlyOfNode) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetFromID(7));
   search.SetImmediateDescendantsOnly(true);
@@ -252,8 +241,7 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(1)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest,
-       DescendantsOnlyOfNodeWithStartNode) {
+TEST_P(OneShotAccessibilityTreeSearchTest, DescendantsOnlyOfNodeWithStartNode) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetFromID(7));
   search.SetStartNode(tree_->GetFromID(8));
@@ -262,7 +250,7 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(0)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest,
+TEST_P(OneShotAccessibilityTreeSearchTest,
        DescendantsOnlyOfNodeWithStartNodeBackwardsTableCell) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetFromID(3));
@@ -272,7 +260,7 @@
   ASSERT_EQ(0U, search.CountMatches());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest,
+TEST_P(OneShotAccessibilityTreeSearchTest,
        DescendantsOnlyOfNodeWithStartNodeBackwardsListItem) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetFromID(7));
@@ -283,7 +271,7 @@
   EXPECT_EQ(8, search.GetMatchAtIndex(0)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, OnscreenOnly) {
+TEST_P(OneShotAccessibilityTreeSearchTest, OnscreenOnly) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetOnscreenOnly(true);
@@ -297,7 +285,7 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(6)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, CaseInsensitiveStringMatch) {
+TEST_P(OneShotAccessibilityTreeSearchTest, CaseInsensitiveStringMatch) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.SetSearchText("eCEptiCOn");
@@ -305,7 +293,7 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(0)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, OnePredicateTableCell) {
+TEST_P(OneShotAccessibilityTreeSearchTest, OnePredicateTableCell) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.AddPredicate(
@@ -317,7 +305,7 @@
   EXPECT_EQ(6, search.GetMatchAtIndex(1)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, OnePredicateListItem) {
+TEST_P(OneShotAccessibilityTreeSearchTest, OnePredicateListItem) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.AddPredicate(
@@ -329,7 +317,7 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(1)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, TwoPredicatesTableRowAndCell) {
+TEST_P(OneShotAccessibilityTreeSearchTest, TwoPredicatesTableRowAndCell) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.AddPredicate(
@@ -346,7 +334,7 @@
   EXPECT_EQ(6, search.GetMatchAtIndex(1)->GetId());
 }
 
-TEST_P(MAYBE_OneShotAccessibilityTreeSearchTest, TwoPredicatesListItem) {
+TEST_P(OneShotAccessibilityTreeSearchTest, TwoPredicatesListItem) {
   tree_->ax_tree()->SetEnableExtraMacNodes(GetParam());
   OneShotAccessibilityTreeSearch search(tree_->GetRoot());
   search.AddPredicate(
@@ -363,12 +351,21 @@
   EXPECT_EQ(9, search.GetMatchAtIndex(1)->GetId());
 }
 
-INSTANTIATE_TEST_SUITE_P(EnableExtraMacNodes,
-                         MAYBE_OneShotAccessibilityTreeSearchTest,
+// These tests prevent other tests from being run. crbug.com/514632
+#if defined(ANDROID) && defined(ADDRESS_SANITIZER)
+#define MAYBE_EnableExtraMacNodes DISABLED_EnableExtraMacNodes
+#define MAYBE_DisableExtraMacNodes DISABLED_DisableExtraMacNodes
+#else
+#define MAYBE_EnableExtraMacNodes EnableExtraMacNodes
+#define MAYBE_DisableExtraMacNodes DisableExtraMacNodes
+#endif
+
+INSTANTIATE_TEST_SUITE_P(MAYBE_EnableExtraMacNodes,
+                         OneShotAccessibilityTreeSearchTest,
                          testing::Values(true));
 
-INSTANTIATE_TEST_SUITE_P(DisableExtraMacNodes,
-                         MAYBE_OneShotAccessibilityTreeSearchTest,
+INSTANTIATE_TEST_SUITE_P(MAYBE_DisableExtraMacNodes,
+                         OneShotAccessibilityTreeSearchTest,
                          testing::Values(false));
 
 }  // namespace content
diff --git a/content/browser/cache_storage/BUILD.gn b/content/browser/cache_storage/BUILD.gn
index 7b33ea1..23a1ac6e 100644
--- a/content/browser/cache_storage/BUILD.gn
+++ b/content/browser/cache_storage/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("cache_storage_proto") {
-  sources = [
-    "cache_storage.proto",
-  ]
+  sources = [ "cache_storage.proto" ]
 }
diff --git a/content/browser/frame_host/navigation_request_browsertest.cc b/content/browser/frame_host/navigation_request_browsertest.cc
index 1ff7285..38de5db 100644
--- a/content/browser/frame_host/navigation_request_browsertest.cc
+++ b/content/browser/frame_host/navigation_request_browsertest.cc
@@ -1643,7 +1643,7 @@
 
   EXPECT_TRUE(observer.has_committed());
   EXPECT_TRUE(observer.is_error());
-  EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.net_error_code());
+  EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, observer.net_error_code());
   EXPECT_EQ(net::ERR_DNS_TIMED_OUT, observer.resolve_error_info().error);
 }
 
diff --git a/content/browser/tracing/startup_tracing_browsertest.cc b/content/browser/tracing/startup_tracing_browsertest.cc
index 925d120e..dad4966 100644
--- a/content/browser/tracing/startup_tracing_browsertest.cc
+++ b/content/browser/tracing/startup_tracing_browsertest.cc
@@ -27,7 +27,7 @@
 // Wait until |condition| returns true.
 void WaitForCondition(base::RepeatingCallback<bool()> condition,
                       const std::string& description) {
-  const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(15);
+  const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(30);
   const base::TimeTicks start_time = base::TimeTicks::Now();
   while (!condition.Run() && (base::TimeTicks::Now() - start_time < kTimeout)) {
     base::RunLoop run_loop;
@@ -68,8 +68,8 @@
   DISALLOW_COPY_AND_ASSIGN(CommandlineStartupTracingTest);
 };
 
-// Flaky on ASAN. crbug.com/1041392
-#if defined(ADDRESS_SANITIZER)
+// Failing on Android ASAN. crbug.com/1041392
+#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
 #define MAYBE_TestStartupTracing DISABLED_TestStartupTracing
 #else
 #define MAYBE_TestStartupTracing TestStartupTracing
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index e2754d8b..018cffef 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -816,4 +816,10 @@
   rvh->OnWebkitPreferencesChanged();
 }
 
+void WebContentsAndroid::NotifyBrowserControlsHeightChanged(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  web_contents_->GetNativeView()->OnBrowserControlsHeightChanged();
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index bda40d8..4381a9a 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -242,6 +242,10 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
 
+  void NotifyBrowserControlsHeightChanged(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj);
+
   base::android::ScopedJavaLocalRef<jobject> GetRenderWidgetHostView(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 5a1e940..8c293cd 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -623,4 +623,11 @@
     web_contents_->SendScreenRects();
 }
 
+void WebContentsViewAndroid::OnBrowserControlsHeightChanged() {
+  auto* rwhv = GetRenderWidgetHostViewAndroid();
+  if (rwhv)
+    rwhv->SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
+                                      base::nullopt);
+}
+
 } // namespace content
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index ae1395d..2ac1ffc 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -121,6 +121,7 @@
   bool ScrollTo(float x, float y) override;
   void OnSizeChanged() override;
   void OnPhysicalBackingSizeChanged() override;
+  void OnBrowserControlsHeightChanged() override;
 
   void SetFocus(bool focused);
   void set_device_orientation(int orientation) {
diff --git a/content/browser/webui/url_data_manager_backend.cc b/content/browser/webui/url_data_manager_backend.cc
index 7360544b..1059c5e 100644
--- a/content/browser/webui/url_data_manager_backend.cc
+++ b/content/browser/webui/url_data_manager_backend.cc
@@ -98,6 +98,14 @@
 
 URLDataSourceImpl* URLDataManagerBackend::GetDataSourceFromURL(
     const GURL& url) {
+  // chrome-untrusted:// sources keys are of the form "chrome-untrusted://host".
+  if (url.scheme() == kChromeUIUntrustedScheme) {
+    auto i = data_sources_.find(url.GetOrigin().spec());
+    if (i == data_sources_.end())
+      return nullptr;
+    return i->second.get();
+  }
+
   // The input usually looks like: chrome://source_name/extra_bits?foo
   // so do a lookup using the host of the URL.
   auto i = data_sources_.find(url.host());
@@ -170,6 +178,7 @@
 bool URLDataManagerBackend::CheckURLIsValid(const GURL& url) {
   std::vector<std::string> additional_schemes;
   DCHECK(url.SchemeIs(kChromeUIScheme) ||
+         url.SchemeIs(kChromeUIUntrustedScheme) ||
          (GetContentClient()->browser()->GetAdditionalWebUISchemes(
               &additional_schemes),
           SchemeIsInSchemes(url.scheme(), additional_schemes)));
@@ -209,6 +218,7 @@
 std::vector<std::string> URLDataManagerBackend::GetWebUISchemes() {
   std::vector<std::string> schemes;
   schemes.push_back(kChromeUIScheme);
+  schemes.push_back(kChromeUIUntrustedScheme);
   GetContentClient()->browser()->GetAdditionalWebUISchemes(&schemes);
   return schemes;
 }
diff --git a/content/browser/webui/web_ui_browsertest.cc b/content/browser/webui/web_ui_browsertest.cc
index 7842aa3..082a48e 100644
--- a/content/browser/webui/web_ui_browsertest.cc
+++ b/content/browser/webui/web_ui_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
@@ -19,12 +20,14 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui_data_source.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_utils.h"
+#include "content/public/test/web_ui_browsertest_util.h"
 #include "content/shell/browser/shell.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
@@ -133,6 +136,8 @@
   // Capture the SiteInstance before navigating for later comparison.
   scoped_refptr<SiteInstance> orig_site_instance(
       web_contents->GetSiteInstance());
+  int32_t orig_browsing_instance_id =
+      orig_site_instance->GetBrowsingInstanceId();
 
   // Navigate to a different WebUI type and ensure that the SiteInstance
   // has changed and the new process also has WebUI bindings.
@@ -140,7 +145,74 @@
   EXPECT_TRUE(ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
       web_contents->GetBrowserContext(), web_ui_url2));
   ASSERT_TRUE(NavigateToURL(web_contents, web_ui_url2));
-  EXPECT_NE(orig_site_instance, web_contents->GetSiteInstance());
+  auto* new_site_instance = web_contents->GetSiteInstance();
+  EXPECT_NE(orig_site_instance, new_site_instance);
+  EXPECT_NE(orig_browsing_instance_id,
+            new_site_instance->GetBrowsingInstanceId());
+  EXPECT_TRUE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+      web_contents->GetMainFrame()->GetProcess()->GetID()));
+}
+
+// Tests that navigating from chrome:// to chrome-untrusted:// results in
+// SiteInstance swap.
+IN_PROC_BROWSER_TEST_F(WebUIImplBrowserTest, ForceSwapOnFromChromeToUntrusted) {
+  WebContents* web_contents = shell()->web_contents();
+  AddUntrustedDataSource(web_contents->GetBrowserContext(), "test-host");
+
+  const GURL web_ui_url(GetWebUIURL(kChromeUIHistogramHost));
+  EXPECT_TRUE(ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
+      web_contents->GetBrowserContext(), web_ui_url));
+
+  ASSERT_TRUE(NavigateToURL(web_contents, web_ui_url));
+  EXPECT_TRUE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+      web_contents->GetMainFrame()->GetProcess()->GetID()));
+
+  // Capture the SiteInstance before navigating for later comparison.
+  scoped_refptr<SiteInstance> orig_site_instance(
+      web_contents->GetSiteInstance());
+  int32_t orig_browsing_instance_id =
+      orig_site_instance->GetBrowsingInstanceId();
+
+  // Navigate to chrome-untrusted:// and ensure that the SiteInstance
+  // has changed and the new process has no WebUI bindings.
+  ASSERT_TRUE(NavigateToURL(web_contents,
+                            GetChromeUntrustedUIURL("test-host/title1.html")));
+  auto* new_site_instance = web_contents->GetSiteInstance();
+  EXPECT_NE(orig_site_instance, new_site_instance);
+  EXPECT_NE(orig_browsing_instance_id,
+            new_site_instance->GetBrowsingInstanceId());
+  EXPECT_FALSE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+      web_contents->GetMainFrame()->GetProcess()->GetID()));
+}
+
+// Tests that navigating from chrome-untrusted:// to chrome:// results in
+// SiteInstance swap.
+IN_PROC_BROWSER_TEST_F(WebUIImplBrowserTest, ForceSwapOnFromUntrustedToChrome) {
+  WebContents* web_contents = shell()->web_contents();
+  AddUntrustedDataSource(web_contents->GetBrowserContext(), "test-host");
+
+  ASSERT_TRUE(NavigateToURL(web_contents,
+                            GetChromeUntrustedUIURL("test-host/title1.html")));
+  EXPECT_FALSE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
+      web_contents->GetMainFrame()->GetProcess()->GetID()));
+
+  // Capture the SiteInstance before navigating for later comparison.
+  scoped_refptr<SiteInstance> orig_site_instance(
+      web_contents->GetSiteInstance());
+  int32_t orig_browsing_instance_id =
+      orig_site_instance->GetBrowsingInstanceId();
+
+  // Navigate to a WebUI and ensure that the SiteInstance has changed and the
+  // new process has WebUI bindings.
+  const GURL web_ui_url(GetWebUIURL(kChromeUIHistogramHost));
+  EXPECT_TRUE(ContentWebUIControllerFactory::GetInstance()->UseWebUIForURL(
+      web_contents->GetBrowserContext(), web_ui_url));
+
+  ASSERT_TRUE(NavigateToURL(web_contents, web_ui_url));
+  auto* new_site_instance = web_contents->GetSiteInstance();
+  EXPECT_NE(orig_site_instance, new_site_instance);
+  EXPECT_NE(orig_browsing_instance_id,
+            new_site_instance->GetBrowsingInstanceId());
   EXPECT_TRUE(ChildProcessSecurityPolicy::GetInstance()->HasWebUIBindings(
       web_contents->GetMainFrame()->GetProcess()->GetID()));
 }
@@ -230,4 +302,15 @@
   EXPECT_EQ(2, test_handler()->message_requiring_gesture_count());
 }
 
+// Verify that we can successfully navigate to a chrome-untrusted:// URL.
+IN_PROC_BROWSER_TEST_F(WebUIImplBrowserTest, UntrustedSchemeLoads) {
+  auto* web_contents = shell()->web_contents();
+  AddUntrustedDataSource(web_contents->GetBrowserContext(), "test-host");
+
+  const GURL untrusted_url(GetChromeUntrustedUIURL("test-host/title2.html"));
+  EXPECT_TRUE(NavigateToURL(web_contents, untrusted_url));
+  EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"),
+            web_contents->GetTitle());
+}
+
 }  // namespace content
diff --git a/content/browser/webui/web_ui_navigation_browsertest.cc b/content/browser/webui/web_ui_navigation_browsertest.cc
index d317a8c..ce52703 100644
--- a/content/browser/webui/web_ui_navigation_browsertest.cc
+++ b/content/browser/webui/web_ui_navigation_browsertest.cc
@@ -7,7 +7,6 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/webui/web_ui_browsertest_util.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_switches.h"
@@ -17,14 +16,25 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_frame_navigation_observer.h"
 #include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/web_ui_browsertest_util.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
+#include "ipc/ipc_security_test_util.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/url_constants.h"
 
 namespace content {
 
+namespace {
+
+const char kAddIframeScript[] =
+    "var frame = document.createElement('iframe');\n"
+    "frame.src = $1;\n"
+    "document.body.appendChild(frame);\n";
+
+}  // namespace
+
 class WebUINavigationBrowserTest : public ContentBrowserTest {
  public:
   WebUINavigationBrowserTest() {
@@ -161,16 +171,11 @@
   EXPECT_EQ(BINDINGS_POLICY_WEB_UI,
             root->current_frame_host()->GetEnabledBindings());
 
-  std::string add_iframe_script =
-      "var frame = document.createElement('iframe');\n"
-      "frame.src = $1;\n"
-      "document.body.appendChild(frame);\n";
-
   // Navigate to a Web URL and verify that the navigation was blocked.
   {
     TestNavigationObserver observer(shell()->web_contents());
     GURL web_url(embedded_test_server()->GetURL("/title2.html"));
-    EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, web_url),
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, web_url),
                        EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
     observer.Wait();
     EXPECT_FALSE(observer.last_navigation_succeeded());
@@ -180,12 +185,44 @@
   {
     TestNavigationObserver observer(shell()->web_contents());
     GURL data_url("data:text/html,foo");
-    EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, data_url),
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, data_url),
                        EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
     observer.Wait();
     EXPECT_FALSE(observer.last_navigation_succeeded());
   }
 
+  // Navigate to a chrome-untrusted URL and verify that the navigation was
+  // blocked by a renderer-side check.
+  {
+    // Add a DataSource for chrome-untrusted:// that can be iframe'd.
+    AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                           "test-host", /*child_src=*/base::nullopt,
+                           /*disable_xfo=*/true);
+    GURL untrusted_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+
+    auto console_delegate = std::make_unique<ConsoleObserverDelegate>(
+        shell()->web_contents(),
+        "Not allowed to load local resource: " + untrusted_url.spec());
+
+    // Save the delegate since we are about to replace it.
+    auto* web_contents_delegate = shell()->web_contents()->GetDelegate();
+    shell()->web_contents()->SetDelegate(console_delegate.get());
+
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, untrusted_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+
+    console_delegate->Wait();
+    FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                              ->GetFrameTree()
+                              ->root();
+    EXPECT_EQ(3U, root->child_count());
+    RenderFrameHost* child = root->child_at(2)->current_frame_host();
+    EXPECT_EQ(GURL(), child->GetLastCommittedURL());
+
+    // Restore the delegate that we replaced.
+    shell()->web_contents()->SetDelegate(web_contents_delegate);
+  }
+
   // Verify that an iframe with "about:blank" URL is actually allowed. Not
   // sure why this would be useful, but from a security perspective it can
   // only host content coming from the parent document, so it effectively
@@ -193,7 +230,57 @@
   {
     TestNavigationObserver observer(shell()->web_contents());
     GURL about_blank_url("about:blank");
-    EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, about_blank_url),
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, about_blank_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_TRUE(observer.last_navigation_succeeded());
+  }
+}
+
+// Verify that a chrome-untrusted:// scheme document can add iframes with web
+// content when the CSP allows it. This is different from chrome:// URLs where
+// no web content can be loaded, even if the CSP allows it.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+                       WebFrameInChromeUntrustedSchemeAllowedByCSP) {
+  // Add a DataSource with no iframe restrictions.
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-host", /*child_src=*/"");
+  GURL main_frame_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(0, root->current_frame_host()->GetEnabledBindings());
+
+  // Add iframe and navigate it to a Web URL and verify that the navigation
+  // succeeded.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, web_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_TRUE(observer.last_navigation_succeeded());
+  }
+
+  // Add iframe and navigate it to a data URL and verify that the navigation
+  // succeeded.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL data_url("data:text/html,foo");
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, data_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_TRUE(observer.last_navigation_succeeded());
+  }
+
+  // Add iframe and navigate it to "about:blank" and verify that the navigation
+  // succeeded.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL about_blank_url("about:blank");
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, about_blank_url),
                        EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
     observer.Wait();
     EXPECT_TRUE(observer.last_navigation_succeeded());
@@ -216,19 +303,272 @@
   {
     GURL web_url(embedded_test_server()->GetURL("/title2.html"));
     TestNavigationObserver navigation_observer(shell()->web_contents());
-    EXPECT_TRUE(
-        ExecJs(shell(),
-               JsReplace("var frame = document.createElement('iframe');\n"
-                         "frame.src = $1;\n"
-                         "document.body.appendChild(frame);\n",
-                         web_url),
-               EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, web_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
     navigation_observer.Wait();
 
     EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
   }
 }
 
+// Verify that a chrome-untrusted:// scheme document cannot add iframes with web
+// content when the CSP disallows it.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+                       WebFrameInChromeUntrustedSchemeDisallowedByCSP) {
+  // Add a DataSource which disallows iframes by default.
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-host");
+  GURL main_frame_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(0, root->current_frame_host()->GetEnabledBindings());
+
+  // Add iframe and navigate it to a Web URL and verify that the navigation was
+  // blocked.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL web_url(embedded_test_server()->GetURL("/title2.html"));
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, web_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_FALSE(observer.last_navigation_succeeded());
+  }
+
+  // Add iframe and navigate it to a data URL and verify that the navigation was
+  // blocked.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL data_url("data:text/html,foo");
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, data_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_FALSE(observer.last_navigation_succeeded());
+  }
+
+  // Add iframe and navigate it to a chrome-untrusted URL and verify that the
+  // navigation was blocked.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    // Add a DataSource for chrome-untrusted:// that can be iframe'd.
+    AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                           "test-iframe-host", /*child_src=*/base::nullopt,
+                           /*disable_xfo=*/true);
+    GURL untrusted_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, untrusted_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_FALSE(observer.last_navigation_succeeded());
+  }
+
+  // Add iframe and verify that an iframe with "about:blank" URL is actually
+  // allowed. Not sure why this would be useful, but from a security perspective
+  // it can only host content coming from the parent document, so it effectively
+  // has the same security context.
+  {
+    TestNavigationObserver observer(shell()->web_contents());
+    GURL about_blank_url("about:blank");
+    EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, about_blank_url),
+                       EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+    observer.Wait();
+    EXPECT_TRUE(observer.last_navigation_succeeded());
+  }
+}
+
+// Verify that a browser check stops websites from embeding chrome:// iframes.
+// This tests the FrameHostMsg_OpenURL path.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+                       DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  GURL webui_url(GetWebUIURL("web-ui/title1.html?noxfo=true"));
+
+  // Add iframe but don't navigate it to a chrome:// URL yet.
+  EXPECT_TRUE(ExecJs(shell(),
+                     "var frame = document.createElement('iframe');\n"
+                     "document.body.appendChild(frame);\n",
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+  // Simulate an IPC message to navigate the subframe to a chrome:// URL.
+  // This bypasses the renderer-side check that would have stopped the
+  // navigation.
+  TestNavigationObserver observer(shell()->web_contents());
+  content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+                                     webui_url);
+  observer.Wait();
+
+  child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(kBlockedURL, child->GetLastCommittedURL());
+}
+
+// Verify that a browser check stops websites from embeding chrome-untrusted://
+// iframes. This tests the FrameHostMsg_OpenURL path.
+IN_PROC_BROWSER_TEST_F(
+    WebUINavigationBrowserTest,
+    DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-iframe-host", /*child_src=*/base::nullopt,
+                         /*disable_xfo=*/true);
+
+  GURL untrusted_url(GetChromeUntrustedUIURL("test-iframe-host/title1.html"));
+
+  // Add iframe but don't navigate it to a chrome-untrusted:// URL yet.
+  EXPECT_TRUE(ExecJs(shell(),
+                     "var frame = document.createElement('iframe');\n"
+                     "document.body.appendChild(frame);\n",
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+  // Simulate an IPC message to navigate the subframe to a
+  // chrome-untrusted:// URL. This bypasses the renderer-side check that would
+  // have stopped the navigation.
+  TestNavigationObserver observer(shell()->web_contents());
+  content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+                                     untrusted_url);
+  observer.Wait();
+
+  child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(kBlockedURL, child->GetLastCommittedURL());
+}
+
+// Verify that a renderer check stops websites from embeding chrome:// iframes.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+                       DisallowEmbeddingChromeSchemeFromWebFrameRendererCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  GURL webui_url(GetWebUIURL("web-ui/title1.html?noxfo=true"));
+  auto console_delegate = std::make_unique<ConsoleObserverDelegate>(
+      shell()->web_contents(),
+      "Not allowed to load local resource: " + webui_url.spec());
+  shell()->web_contents()->SetDelegate(console_delegate.get());
+
+  // Add iframe and navigate it to a chrome:// URL and verify that the
+  // navigation was blocked.
+  EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, webui_url),
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+  console_delegate->Wait();
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(GURL(), child->GetLastCommittedURL());
+}
+
+// Verify that a renderer check stops websites from embeding chrome-untrusted://
+// iframes.
+IN_PROC_BROWSER_TEST_F(
+    WebUINavigationBrowserTest,
+    DisallowEmbeddingChromeUntrustedSchemeFromWebFrameRendererCheck) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-iframe-host", /*child_src=*/base::nullopt,
+                         /*disable_xfo=*/true);
+
+  GURL untrusted_url(GetChromeUntrustedUIURL("test-iframe-host/title1.html"));
+  auto console_delegate = std::make_unique<ConsoleObserverDelegate>(
+      shell()->web_contents(),
+      "Not allowed to load local resource: " + untrusted_url.spec());
+  shell()->web_contents()->SetDelegate(console_delegate.get());
+
+  // Add iframe and navigate it to a chrome-untrusted:// URL and verify that the
+  // navigation was blocked.
+  EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, untrusted_url),
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+  console_delegate->Wait();
+
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(GURL(), child->GetLastCommittedURL());
+}
+
+// Used to test browser-side checks by disabling some renderer-side checks.
+class WebUINavigationDisabledWebSecurityBrowserTest
+    : public WebUINavigationBrowserTest {
+ protected:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Disable Web Security to skip renderer-side checks so that we can test
+    // browser-side checks.
+    command_line->AppendSwitch(switches::kDisableWebSecurity);
+  }
+};
+
+// Verify that a browser check stops websites from embeding chrome:// iframes.
+// This tests the Frame::BeginNavigation path.
+IN_PROC_BROWSER_TEST_F(WebUINavigationDisabledWebSecurityBrowserTest,
+                       DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck2) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  GURL webui_url(GetWebUIURL("web-ui/title1.html?noxfo=true"));
+
+  TestNavigationObserver observer(shell()->web_contents());
+  EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, webui_url),
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+  observer.Wait();
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(kBlockedURL, child->GetLastCommittedURL());
+}
+
+// Verify that a browser check stops websites from embeding chrome-untrusted://
+// iframes. This tests the Frame::BeginNavigation path.
+IN_PROC_BROWSER_TEST_F(
+    WebUINavigationDisabledWebSecurityBrowserTest,
+    DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck2) {
+  GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
+
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-iframe-host", /*child_src=*/base::nullopt,
+                         /*disable_xfo=*/true);
+
+  GURL untrusted_url(GetChromeUntrustedUIURL("test-iframe-host/title1.html"));
+
+  TestNavigationObserver observer(shell()->web_contents());
+  EXPECT_TRUE(ExecJs(shell(), JsReplace(kAddIframeScript, untrusted_url),
+                     EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
+  observer.Wait();
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  EXPECT_EQ(1U, root->child_count());
+  RenderFrameHost* child = root->child_at(0)->current_frame_host();
+  EXPECT_EQ(kBlockedURL, child->GetLastCommittedURL());
+}
+
 // Verify that a WebUI document in the main frame is allowed to navigate to
 // web content and it properly does cross-process navigation.
 IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
@@ -338,6 +678,47 @@
             SiteInstance::GetSiteForURL(browser_context, blob_url));
 }
 
+// Verify chrome-untrusted:// uses a dedicated process.
+IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
+                       UntrustedWebUIOriginsRequireDedicatedProcess) {
+  // Add a DataSource which disallows iframes by default.
+  AddUntrustedDataSource(shell()->web_contents()->GetBrowserContext(),
+                         "test-host");
+  GURL chrome_untrusted_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+  GURL expected_site_url(GetChromeUntrustedUIURL("test-host"));
+
+  // chrome-untrusted:// URLs should require a dedicated process.
+  WebContents* web_contents = shell()->web_contents();
+  BrowserContext* browser_context = web_contents->GetBrowserContext();
+  EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
+      IsolationContext(browser_context), chrome_untrusted_url));
+
+  // Navigate to a chrome-untrusted:// page.
+  EXPECT_TRUE(NavigateToURL(shell(), chrome_untrusted_url));
+
+  // Verify that the "hostname" is also part of the site URL.
+  GURL site_url = web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL();
+  EXPECT_EQ(expected_site_url, site_url);
+
+  // Ask the page to create a blob URL and return back the blob URL.
+  const char* kScript = R"(
+          var blob = new Blob(['foo'], {type : 'text/html'});
+          var url = URL.createObjectURL(blob);
+          url;
+      )";
+  GURL blob_url(
+      EvalJs(shell(), kScript, EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */)
+          .ExtractString());
+  EXPECT_EQ(url::kBlobScheme, blob_url.scheme());
+
+  // Verify that the blob also requires a dedicated process and that it would
+  // use the same site url as the original page.
+  EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
+      IsolationContext(browser_context), blob_url));
+  EXPECT_EQ(expected_site_url,
+            SiteInstance::GetSiteForURL(browser_context, blob_url));
+}
+
 // Verify that navigating back/forward between WebUI and an error page for a
 // failed WebUI navigation works correctly.
 IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
diff --git a/content/browser/webui/web_ui_security_browsertest.cc b/content/browser/webui/web_ui_security_browsertest.cc
index 370f052..c9c78af 100644
--- a/content/browser/webui/web_ui_security_browsertest.cc
+++ b/content/browser/webui/web_ui_security_browsertest.cc
@@ -12,7 +12,6 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/web_contents/web_contents_impl.h"
-#include "content/browser/webui/web_ui_browsertest_util.h"
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_ui.h"
@@ -26,6 +25,7 @@
 #include "content/public/test/test_frame_navigation_observer.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
+#include "content/public/test/web_ui_browsertest_util.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "net/base/url_util.h"
@@ -49,6 +49,19 @@
   DISALLOW_COPY_AND_ASSIGN(WebUISecurityTest);
 };
 
+// Verify chrome-untrusted:// have no bindings.
+IN_PROC_BROWSER_TEST_F(WebUISecurityTest, UntrustedNoBindings) {
+  auto* web_contents = shell()->web_contents();
+  AddUntrustedDataSource(web_contents->GetBrowserContext(), "test-host");
+
+  const GURL untrusted_url(GetChromeUntrustedUIURL("test-host/title1.html"));
+  EXPECT_TRUE(NavigateToURL(web_contents, untrusted_url));
+
+  EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+      shell()->web_contents()->GetMainFrame()->GetProcess()->GetID()));
+  EXPECT_EQ(0, shell()->web_contents()->GetMainFrame()->GetEnabledBindings());
+}
+
 // Loads a WebUI which does not have any bindings.
 IN_PROC_BROWSER_TEST_F(WebUISecurityTest, NoBindings) {
   GURL test_url(GetWebUIURL("web-ui/title1.html?bindings=0"));
diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
index 73cae86..ea162df 100644
--- a/content/common/url_schemes.cc
+++ b/content/common/url_schemes.cc
@@ -59,6 +59,7 @@
 
   url::AddStandardScheme(kChromeDevToolsScheme, url::SCHEME_WITH_HOST);
   url::AddStandardScheme(kChromeUIScheme, url::SCHEME_WITH_HOST);
+  url::AddStandardScheme(kChromeUIUntrustedScheme, url::SCHEME_WITH_HOST);
   url::AddStandardScheme(kGuestScheme, url::SCHEME_WITH_HOST);
   url::AddStandardScheme(kChromeErrorScheme, url::SCHEME_WITH_HOST);
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index be6087b28..0da65260 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -994,6 +994,13 @@
                 mNativeWebContentsAndroid, WebContentsImpl.this);
     }
 
+    @Override
+    public void notifyBrowserControlsHeightChanged() {
+        if (mNativeWebContentsAndroid == 0) return;
+        WebContentsImplJni.get().notifyBrowserControlsHeightChanged(
+                mNativeWebContentsAndroid, WebContentsImpl.this);
+    }
+
     private void checkNotDestroyed() {
         if (mNativeWebContentsAndroid != 0) return;
         throw new IllegalStateException(
@@ -1088,6 +1095,8 @@
         void setDisplayCutoutSafeArea(long nativeWebContentsAndroid, WebContentsImpl caller,
                 int top, int left, int bottom, int right);
         void notifyRendererPreferenceUpdate(long nativeWebContentsAndroid, WebContentsImpl caller);
+        void notifyBrowserControlsHeightChanged(
+                long nativeWebContentsAndroid, WebContentsImpl caller);
         boolean isBeingDestroyed(long nativeWebContentsAndroid, WebContentsImpl caller);
     }
 }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index cf07460..44f80e24 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -483,4 +483,11 @@
      * Notify that web preferences needs update for various properties.
      */
     void notifyRendererPreferenceUpdate();
+
+    /**
+     * Notify that the browser controls heights have changed. Any change to the top controls height,
+     * bottom controls height, top controls min-height, and bottom controls min-height will call
+     * this. Min-height is the minimum visible height the controls can have.
+     */
+    void notifyBrowserControlsHeightChanged();
 }
diff --git a/content/public/browser/url_data_source.cc b/content/public/browser/url_data_source.cc
index 9ca008d..2a669a0 100644
--- a/content/public/browser/url_data_source.cc
+++ b/content/public/browser/url_data_source.cc
@@ -115,7 +115,8 @@
 bool URLDataSource::ShouldServiceRequest(const GURL& url,
                                          ResourceContext* resource_context,
                                          int render_process_id) {
-  return url.SchemeIs(kChromeDevToolsScheme) || url.SchemeIs(kChromeUIScheme);
+  return url.SchemeIs(kChromeDevToolsScheme) || url.SchemeIs(kChromeUIScheme) ||
+         url.SchemeIs(kChromeUIUntrustedScheme);
 }
 
 bool URLDataSource::ShouldServeMimeTypeAsContentTypeHeader() {
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc
index 688e84d5..9ae5fd3 100644
--- a/content/public/common/url_constants.cc
+++ b/content/public/common/url_constants.cc
@@ -12,6 +12,7 @@
 const char kChromeDevToolsScheme[] = "devtools";
 const char kChromeErrorScheme[] = "chrome-error";
 const char kChromeUIScheme[] = "chrome";
+const char kChromeUIUntrustedScheme[] = "chrome-untrusted";
 const char kGuestScheme[] = "chrome-guest";
 const char kViewSourceScheme[] = "view-source";
 #if defined(OS_CHROMEOS)
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h
index e7e283d8..6569c60f 100644
--- a/content/public/common/url_constants.h
+++ b/content/public/common/url_constants.h
@@ -20,6 +20,7 @@
 CONTENT_EXPORT extern const char kChromeDevToolsScheme[];
 CONTENT_EXPORT extern const char kChromeErrorScheme[];
 CONTENT_EXPORT extern const char kChromeUIScheme[];  // Used for WebUIs.
+CONTENT_EXPORT extern const char kChromeUIUntrustedScheme[];
 CONTENT_EXPORT extern const char kGuestScheme[];
 CONTENT_EXPORT extern const char kViewSourceScheme[];
 #if defined(OS_CHROMEOS)
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
index 3fabae6..efbd806 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockWebContents.java
@@ -271,4 +271,7 @@
 
     @Override
     public void notifyRendererPreferenceUpdate() {}
+
+    @Override
+    public void notifyBrowserControlsHeightChanged() {}
 }
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 452f324c..a3b4c84 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -3170,6 +3170,18 @@
                               request_unadjusted_movement));
 }
 
+void PwnMessageHelper::OpenURL(RenderProcessHost* process,
+                               int routing_id,
+                               const GURL& url) {
+  FrameHostMsg_OpenURL_Params params;
+  params.url = url;
+  params.disposition = WindowOpenDisposition::CURRENT_TAB;
+  params.should_replace_current_entry = false;
+  params.user_gesture = true;
+  IPC::IpcSecurityTestUtil::PwnMessageReceived(
+      process->GetChannel(), FrameHostMsg_OpenURL(routing_id, params));
+}
+
 #if defined(USE_AURA)
 namespace {
 
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 4b4ada81..dbdb0f2 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -1655,6 +1655,11 @@
                         bool privileged,
                         bool request_unadjusted_movement);
 
+  // Sends FrameHostMsg_OpenURL
+  static void OpenURL(RenderProcessHost* process,
+                      int routing_id,
+                      const GURL& url);
+
  private:
   PwnMessageHelper();  // Not instantiable.
 
diff --git a/content/public/test/test_host_resolver.cc b/content/public/test/test_host_resolver.cc
index 4c040d2..3d13d11 100644
--- a/content/public/test/test_host_resolver.cc
+++ b/content/public/test/test_host_resolver.cc
@@ -45,6 +45,8 @@
     // queries, rather than perform them.
     // If you really need to make an external DNS query, use
     // net::RuleBasedHostResolverProc and its AllowDirectLookup method.
+    // TODO(crbug.com/1040686): Simulate failure using ERR_NAME_NOT_RESOLVED
+    // rather than ERR_NOT_IMPLEMENTED.
     if (!local) {
       DVLOG(1) << "To avoid external dependencies, simulating failure for "
                   "external DNS lookup of "
diff --git a/content/browser/webui/web_ui_browsertest_util.cc b/content/public/test/web_ui_browsertest_util.cc
similarity index 80%
rename from content/browser/webui/web_ui_browsertest_util.cc
rename to content/public/test/web_ui_browsertest_util.cc
index 0b2a161..4ee3435 100644
--- a/content/browser/webui/web_ui_browsertest_util.cc
+++ b/content/public/test/web_ui_browsertest_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/webui/web_ui_browsertest_util.h"
+#include "content/public/test/web_ui_browsertest_util.h"
 
 #include <memory>
 #include <string>
@@ -82,6 +82,30 @@
 
 }  // namespace
 
+void AddUntrustedDataSource(BrowserContext* browser_context,
+                            const std::string& host,
+                            base::Optional<std::string> child_src,
+                            bool no_xfo) {
+  auto* untrusted_data_source =
+      WebUIDataSource::Create(GetChromeUntrustedUIURL(host).spec());
+  untrusted_data_source->SetRequestFilter(
+      base::BindRepeating([](const std::string& path) { return true; }),
+      base::BindRepeating(&GetResource));
+  if (child_src.has_value())
+    untrusted_data_source->OverrideContentSecurityPolicyChildSrc(
+        child_src.value());
+  if (no_xfo)
+    untrusted_data_source->DisableDenyXFrameOptions();
+
+  WebUIDataSource::Add(browser_context, untrusted_data_source);
+}
+
+// static
+GURL GetChromeUntrustedUIURL(const std::string& host_and_path) {
+  return GURL(std::string(content::kChromeUIUntrustedScheme) +
+              url::kStandardSchemeSeparator + host_and_path);
+}
+
 TestWebUIControllerFactory::TestWebUIControllerFactory() = default;
 
 std::unique_ptr<WebUIController>
diff --git a/content/browser/webui/web_ui_browsertest_util.h b/content/public/test/web_ui_browsertest_util.h
similarity index 71%
rename from content/browser/webui/web_ui_browsertest_util.h
rename to content/public/test/web_ui_browsertest_util.h
index 331efcb..7511c68 100644
--- a/content/browser/webui/web_ui_browsertest_util.h
+++ b/content/public/test/web_ui_browsertest_util.h
@@ -2,15 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
-#define CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
+#ifndef CONTENT_PUBLIC_TEST_WEB_UI_BROWSERTEST_UTIL_H_
+#define CONTENT_PUBLIC_TEST_WEB_UI_BROWSERTEST_UTIL_H_
 
 #include <memory>
+#include <string>
+#include <utility>
 
-#include "content/browser/webui/content_web_ui_controller_factory.h"
+#include "base/optional.h"
+#include "content/public/browser/web_ui_controller_factory.h"
 
 namespace content {
 
+// Adds a DataSource for chrome-untrusted://|host| URLs.
+void AddUntrustedDataSource(
+    BrowserContext* browser_context,
+    const std::string& host,
+    base::Optional<std::string> child_src = base::nullopt,
+    bool no_xfo = false);
+
+// Returns chrome-untrusted://|host_and_path| as a GURL.
+GURL GetChromeUntrustedUIURL(const std::string& host_and_path);
+
 // Returns WebUIControllers whose CSPs and headers can be controlled through
 // query parameters.
 // - "bindings" controls the bindings e.g. Mojo, chrome.send() or both, with
@@ -46,4 +59,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
+#endif  // CONTENT_PUBLIC_TEST_WEB_UI_BROWSERTEST_UTIL_H_
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index 446862f..858d5fa 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -164,10 +164,6 @@
         // more information than the sparse interface does.
         // ******** Why is this a TODO? ********
         break;
-      case WebAXObjectAttribute::kAriaDetails:
-        dst_->AddIntAttribute(ax::mojom::IntAttribute::kDetailsId,
-                              value.AxID());
-        break;
       case WebAXObjectAttribute::kAriaErrorMessage:
         // Use WebAXObject::ErrorMessage(), which provides both ARIA error
         // messages as well as built-in HTML form validation messages.
@@ -185,6 +181,10 @@
         AddIntListAttributeFromWebObjects(
             ax::mojom::IntListAttribute::kControlsIds, value, dst_);
         break;
+      case WebAXObjectVectorAttribute::kAriaDetails:
+        AddIntListAttributeFromWebObjects(
+            ax::mojom::IntListAttribute::kDetailsIds, value, dst_);
+        break;
       case WebAXObjectVectorAttribute::kAriaFlowTo:
         AddIntListAttributeFromWebObjects(
             ax::mojom::IntListAttribute::kFlowtoIds, value, dst_);
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index faaa4cc2..ce5afdf 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -1034,6 +1034,14 @@
   WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
       chrome_scheme);
 
+  // chrome-untrusted:
+  WebString chrome_untrusted_scheme(
+      WebString::FromASCII(kChromeUIUntrustedScheme));
+  WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(
+      chrome_untrusted_scheme);
+  WebSecurityPolicy::RegisterURLSchemeAsNotAllowingJavascriptURLs(
+      chrome_untrusted_scheme);
+
   // devtools:
   WebString devtools_scheme(WebString::FromASCII(kChromeDevToolsScheme));
   WebSecurityPolicy::RegisterURLSchemeAsDisplayIsolated(devtools_scheme);
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index b207bf9c..5b74241 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -182,10 +182,10 @@
   if (!url.is_valid())
     return false;
   static const char* const kProtocolList[] = {
-      url::kHttpScheme, url::kHttpsScheme,     url::kWsScheme,
-      url::kWssScheme,  url::kBlobScheme,      url::kFileSystemScheme,
-      kChromeUIScheme,  kChromeDevToolsScheme, url::kDataScheme,
-      url::kFileScheme,
+      url::kHttpScheme, url::kHttpsScheme,        url::kWsScheme,
+      url::kWssScheme,  url::kBlobScheme,         url::kFileSystemScheme,
+      kChromeUIScheme,  kChromeUIUntrustedScheme, kChromeDevToolsScheme,
+      url::kDataScheme, url::kFileScheme,
   };
   for (const char* supported_protocol : kProtocolList) {
     if (url.scheme_piece() == supported_protocol)
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc
index 7c59faa..677c292 100644
--- a/content/shell/test_runner/web_ax_object_proxy.cc
+++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -776,7 +776,8 @@
                  &WebAXObjectProxy::AriaActiveDescendantElement)
       .SetMethod("ariaControlsElementAtIndex",
                  &WebAXObjectProxy::AriaControlsElementAtIndex)
-      .SetMethod("ariaDetailsElement", &WebAXObjectProxy::AriaDetailsElement)
+      .SetMethod("ariaDetailsElementAtIndex",
+                 &WebAXObjectProxy::AriaDetailsElementAtIndex)
       .SetMethod("ariaErrorMessageElement",
                  &WebAXObjectProxy::AriaErrorMessageElement)
       .SetMethod("ariaFlowToElementAtIndex",
@@ -1543,14 +1544,19 @@
   return factory_->GetOrCreate(elements[index]);
 }
 
-v8::Local<v8::Object> WebAXObjectProxy::AriaDetailsElement() {
+v8::Local<v8::Object> WebAXObjectProxy::AriaDetailsElementAtIndex(
+    unsigned index) {
   accessibility_object_.UpdateLayoutAndCheckValidity();
   SparseAttributeAdapter attribute_adapter;
   accessibility_object_.GetSparseAXAttributes(attribute_adapter);
-  blink::WebAXObject element =
-      attribute_adapter
-          .object_attributes[blink::WebAXObjectAttribute::kAriaDetails];
-  return factory_->GetOrCreate(element);
+  blink::WebVector<blink::WebAXObject> elements =
+      attribute_adapter.object_vector_attributes
+          [blink::WebAXObjectVectorAttribute::kAriaDetails];
+  size_t elementCount = elements.size();
+  if (index >= elementCount)
+    return v8::Local<v8::Object>();
+
+  return factory_->GetOrCreate(elements[index]);
 }
 
 v8::Local<v8::Object> WebAXObjectProxy::AriaErrorMessageElement() {
diff --git a/content/shell/test_runner/web_ax_object_proxy.h b/content/shell/test_runner/web_ax_object_proxy.h
index c074365..5d34e3b 100644
--- a/content/shell/test_runner/web_ax_object_proxy.h
+++ b/content/shell/test_runner/web_ax_object_proxy.h
@@ -160,7 +160,7 @@
   // Bound methods.
   v8::Local<v8::Object> AriaActiveDescendantElement();
   v8::Local<v8::Object> AriaControlsElementAtIndex(unsigned index);
-  v8::Local<v8::Object> AriaDetailsElement();
+  v8::Local<v8::Object> AriaDetailsElementAtIndex(unsigned index);
   v8::Local<v8::Object> AriaErrorMessageElement();
   v8::Local<v8::Object> AriaFlowToElementAtIndex(unsigned index);
   v8::Local<v8::Object> AriaOwnsElementAtIndex(unsigned index);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 330724875..d54c66b 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -226,6 +226,8 @@
     "../public/test/web_contents_receiver_set_test_binder.h",
     "../public/test/web_contents_tester.cc",
     "../public/test/web_contents_tester.h",
+    "../public/test/web_ui_browsertest_util.cc",
+    "../public/test/web_ui_browsertest_util.h",
     "appcache_test_helper.cc",
     "appcache_test_helper.h",
     "content_browser_sanity_checker.cc",
@@ -1031,8 +1033,6 @@
     "../browser/webrtc/webrtc_webcam_browsertest.cc",
     "../browser/webrtc/webrtc_webcam_browsertest.h",
     "../browser/webui/web_ui_browsertest.cc",
-    "../browser/webui/web_ui_browsertest_util.cc",
-    "../browser/webui/web_ui_browsertest_util.h",
     "../browser/webui/web_ui_mojo_browsertest.cc",
     "../browser/webui/web_ui_navigation_browsertest.cc",
     "../browser/webui/web_ui_security_browsertest.cc",
diff --git a/content/test/data/accessibility/aria/aria-details-expected-blink.txt b/content/test/data/accessibility/aria/aria-details-expected-blink.txt
index 45c7c8c..9913372 100644
--- a/content/test/data/accessibility/aria/aria-details-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-details-expected-blink.txt
@@ -1,7 +1,7 @@
 rootWebArea
 ++genericContainer ignored
 ++++genericContainer
-++++++textField detailsId=paragraph
+++++++textField detailsIds=paragraph
 ++++++++genericContainer
 ++++paragraph
 ++++++staticText name='Details'
@@ -9,7 +9,7 @@
 ++++paragraph
 ++++++staticText name='This '
 ++++++++inlineTextBox name='This '
-++++++genericContainer detailsId=group
+++++++genericContainer detailsIds=group,image
 ++++++++staticText name='text'
 ++++++++++inlineTextBox name='text'
 ++++++staticText name=' has details'
@@ -17,3 +17,4 @@
 ++++group
 ++++++staticText name='Text details'
 ++++++++inlineTextBox name='Text details'
+++++image name='Image details'
diff --git a/content/test/data/accessibility/aria/aria-details-expected-win.txt b/content/test/data/accessibility/aria/aria-details-expected-win.txt
index 94422f96..8ab23ea 100644
--- a/content/test/data/accessibility/aria/aria-details-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-details-expected-win.txt
@@ -10,3 +10,4 @@
 ++++ROLE_SYSTEM_STATICTEXT name=' has details' n_relations=0
 ++ROLE_SYSTEM_GROUPING n_relations=1
 ++++ROLE_SYSTEM_STATICTEXT name='Text details' n_relations=0
+++ROLE_SYSTEM_GRAPHIC name='Image details' READONLY n_relations=1
diff --git a/content/test/data/accessibility/aria/aria-details.html b/content/test/data/accessibility/aria/aria-details.html
index fee4577..34a4380 100644
--- a/content/test/data/accessibility/aria/aria-details.html
+++ b/content/test/data/accessibility/aria/aria-details.html
@@ -10,7 +10,8 @@
     </div>
     <p id="details">Details</p>
 
-    <p>This <span aria-details="details2">text</span> has details</p>
+    <p>This <span aria-details="details2 details3">text</span> has details</p>
     <div role="group" id="details2">Text details</div>
+    <img id="details3" alt="Image details">
   </body>
 </html>
diff --git a/content/test/data/accessibility/html/area-crash-expected-blink.txt b/content/test/data/accessibility/html/area-crash-expected-blink.txt
index 6cf6d0df8..3e4ba7f2 100644
--- a/content/test/data/accessibility/html/area-crash-expected-blink.txt
+++ b/content/test/data/accessibility/html/area-crash-expected-blink.txt
@@ -1,6 +1,6 @@
 rootWebArea
 ++genericContainer
-++++link name='foo'
+++++staticText name='foo'
 ++++++staticText name='foo'
 ++++++++inlineTextBox name='foo'
 ++++staticText name=' '
diff --git a/content/test/data/accessibility/html/area-expected-auralinux.txt b/content/test/data/accessibility/html/area-expected-auralinux.txt
index a7e76218..9ff7ce9 100644
--- a/content/test/data/accessibility/html/area-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/area-expected-auralinux.txt
@@ -2,4 +2,4 @@
 ++[section]
 ++++[image map] name='pipe'
 ++++++[link] name='pipe1'
-++++++[link] name='pipe2'
+++++++[static] name='pipe2'
diff --git a/content/test/data/accessibility/html/area-expected-blink.txt b/content/test/data/accessibility/html/area-expected-blink.txt
index 54804e4..7f05c0a9 100644
--- a/content/test/data/accessibility/html/area-expected-blink.txt
+++ b/content/test/data/accessibility/html/area-expected-blink.txt
@@ -2,4 +2,4 @@
 ++genericContainer
 ++++imageMap name='pipe'
 ++++++link name='pipe1'
-++++++link name='pipe2'
+++++++staticText name='pipe2'
diff --git a/content/test/data/accessibility/html/area-expected-mac.txt b/content/test/data/accessibility/html/area-expected-mac.txt
index ce5d07a7..d5c833d 100644
--- a/content/test/data/accessibility/html/area-expected-mac.txt
+++ b/content/test/data/accessibility/html/area-expected-mac.txt
@@ -2,4 +2,4 @@
 ++AXGroup AXRoleDescription='group'
 ++++AXGroup AXRoleDescription='group' AXDescription='pipe'
 ++++++AXLink AXRoleDescription='link' AXDescription='pipe1'
-++++++AXLink AXRoleDescription='link' AXDescription='pipe2'
+++++++AXStaticText AXRoleDescription='text' AXValue='pipe2'
diff --git a/content/test/data/accessibility/html/area-expected-uia-win.txt b/content/test/data/accessibility/html/area-expected-uia-win.txt
index 704aac3..238e9253 100644
--- a/content/test/data/accessibility/html/area-expected-uia-win.txt
+++ b/content/test/data/accessibility/html/area-expected-uia-win.txt
@@ -2,4 +2,4 @@
 ++group IsControlElement=false
 ++++document Name='pipe'
 ++++++link Name='pipe1'
-++++++link Name='pipe2'
+++++++description Name='pipe2'
diff --git a/content/test/data/accessibility/html/area-expected-win.txt b/content/test/data/accessibility/html/area-expected-win.txt
index b0a2682..7f58f8ed 100644
--- a/content/test/data/accessibility/html/area-expected-win.txt
+++ b/content/test/data/accessibility/html/area-expected-win.txt
@@ -2,4 +2,4 @@
 ++IA2_ROLE_SECTION
 ++++IA2_ROLE_IMAGE_MAP name='pipe' READONLY
 ++++++ROLE_SYSTEM_LINK name='pipe1' FOCUSABLE LINKED
-++++++ROLE_SYSTEM_LINK name='pipe2' LINKED
+++++++ROLE_SYSTEM_STATICTEXT name='pipe2' LINKED
diff --git a/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt b/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt
index bdc6a4a..42b66faf 100644
--- a/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt
+++ b/content/test/data/accessibility/html/area-serialization-crash-expected-blink.txt
@@ -1,6 +1,6 @@
 rootWebArea
 ++genericContainer
-++++link
+++++staticText
 ++++++genericContainer invisible
 ++++staticText name='done'
 ++++++inlineTextBox name='done'
diff --git a/extensions/browser/api/hid/BUILD.gn b/extensions/browser/api/hid/BUILD.gn
index 9e9ef37..d6506b22 100644
--- a/extensions/browser/api/hid/BUILD.gn
+++ b/extensions/browser/api/hid/BUILD.gn
@@ -28,7 +28,5 @@
     "//extensions/common/api",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/networking_private/BUILD.gn b/extensions/browser/api/networking_private/BUILD.gn
index c778cdb..dc33633 100644
--- a/extensions/browser/api/networking_private/BUILD.gn
+++ b/extensions/browser/api/networking_private/BUILD.gn
@@ -31,9 +31,7 @@
     "//net",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 
   if (!is_chromeos && is_linux && use_dbus) {
     sources = default_sources + [
@@ -61,8 +59,6 @@
               ]
   } else {
     not_needed([ "default_sources" ])
-    sources = [
-      "networking_private_stubs.cc",
-    ]
+    sources = [ "networking_private_stubs.cc" ]
   }
 }
diff --git a/extensions/browser/api/storage/BUILD.gn b/extensions/browser/api/storage/BUILD.gn
index a5e4fa08..90f8831 100644
--- a/extensions/browser/api/storage/BUILD.gn
+++ b/extensions/browser/api/storage/BUILD.gn
@@ -28,11 +28,7 @@
     "weak_unlimited_settings_storage.h",
   ]
 
-  deps = [
-    "//extensions/common/api",
-  ]
+  deps = [ "//extensions/common/api" ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc
index e6754765..4039a32 100644
--- a/extensions/browser/api/web_request/web_request_permissions.cc
+++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -10,6 +10,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "content/public/browser/child_process_security_policy.h"
+#include "content/public/common/url_constants.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/web_request/permission_helper.h"
 #include "extensions/browser/api/web_request/web_request_api_constants.h"
@@ -310,6 +311,15 @@
     return true;
   }
 
+  // Treat requests from chrome-untrusted:// as sensitive to ensure that the
+  // Web Request API doesn't see them. Note that Extensions are never allowed to
+  // request permission for chrome-untrusted:// URLs so this is check is here
+  // just in case.
+  if (request.initiator.has_value() &&
+      request.initiator->scheme() == content::kChromeUIUntrustedScheme) {
+    return true;
+  }
+
   // Allow the extension embedder to hide the request.
   if (permission_helper->ShouldHideBrowserNetworkRequest(request))
     return true;
diff --git a/extensions/browser/api/web_request/web_request_permissions_unittest.cc b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
index 9907fec..3544791 100644
--- a/extensions/browser/api/web_request/web_request_permissions_unittest.cc
+++ b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
@@ -91,6 +91,10 @@
       // Unsupported scheme.
       {"blob:https://chrome.google.com/fc3f440b-78ed-469f-8af8-7a1717ff39ae",
        HIDE_ALL},
+      // Unsupported scheme.
+      {"chrome://test/", HIDE_ALL},
+      // Unsupported scheme.
+      {"chrome-untrusted://test/", HIDE_ALL},
       {"notregisteredscheme://www.foobar.com", HIDE_ALL},
       {"https://chrome.google.com:80/webstore", HIDE_ALL},
       {"https://chrome.google.com/webstore?query", HIDE_ALL},
@@ -136,6 +140,21 @@
     }
 
     {
+      SCOPED_TRACE(
+          "Renderer initiated sub-resource request from "
+          "chrome-untrusted://");
+      auto request_init_params = create_request_params(
+          request_url, content::ResourceType::kSubResource, kRendererProcessId);
+      GURL url("chrome-untrusted://test/");
+      request_init_params.initiator = url::Origin::Create(url);
+
+      WebRequestInfo request(std::move(request_init_params));
+      // Always hide requests from chrome-untrusted://
+      EXPECT_TRUE(
+          WebRequestPermissions::HideRequest(permission_helper, request));
+    }
+
+    {
       SCOPED_TRACE("Browser initiated sub-resource request");
       WebRequestInfo request(create_request_params(
           request_url, content::ResourceType::kSubResource, kBrowserProcessId));
diff --git a/extensions/browser/guest_view/web_view/web_ui/BUILD.gn b/extensions/browser/guest_view/web_view/web_ui/BUILD.gn
index dd31920..ec8dab8 100644
--- a/extensions/browser/guest_view/web_view/web_ui/BUILD.gn
+++ b/extensions/browser/guest_view/web_view/web_ui/BUILD.gn
@@ -17,7 +17,5 @@
     "//net",
     "//url",
   ]
-  deps = [
-    "//content/public/browser",
-  ]
+  deps = [ "//content/public/browser" ]
 }
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl
index 4979a511..56edd27 100644
--- a/extensions/common/api/automation.idl
+++ b/extensions/common/api/automation.idl
@@ -674,7 +674,7 @@
     AutomationNode? inPageLinkTarget;
 
     // A node that provides more details about the current node.
-    AutomationNode? details;
+    AutomationNode[]? details;
 
     // A node that provides an error message for a current node.
     AutomationNode? errorMessage;
diff --git a/extensions/renderer/resources/automation/automation_node.js b/extensions/renderer/resources/automation/automation_node.js
index 7af56d88..f68facf 100644
--- a/extensions/renderer/resources/automation/automation_node.js
+++ b/extensions/renderer/resources/automation/automation_node.js
@@ -1242,7 +1242,6 @@
 // Int attribute, relation property to expose, reverse relation to expose.
 var nodeRefAttributes = [
     ['activedescendantId', 'activeDescendant', 'activeDescendantFor'],
-    ['detailsId', 'details', 'detailsFor'],
     ['errormessageId', 'errorMessage', 'errorMessageFor'],
     ['inPageLinkTargetId', 'inPageLinkTarget', null],
     ['nextFocusId', 'nextFocus', null],
@@ -1262,6 +1261,7 @@
 var nodeRefListAttributes = [
     ['controlsIds', 'controls', 'controlledBy'],
     ['describedbyIds', 'describedBy', 'descriptionFor'],
+    ['detailsIds', 'details', 'detailsFor'],
     ['flowtoIds', 'flowTo', 'flowFrom'],
     ['labelledbyIds', 'labelledBy', 'labelFor']];
 
diff --git a/gpu/config/BUILD.gn b/gpu/config/BUILD.gn
index e6dd3da..b93e783 100644
--- a/gpu/config/BUILD.gn
+++ b/gpu/config/BUILD.gn
@@ -10,13 +10,9 @@
 
 group("config") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu",
-    ]
+    public_deps = [ "//gpu" ]
   } else {
-    public_deps = [
-      ":config_sources",
-    ]
+    public_deps = [ ":config_sources" ]
   }
 }
 
@@ -63,9 +59,7 @@
     args += [ "linux" ]
   }
 
-  public_deps = [
-    ":workaround_list",
-  ]
+  public_deps = [ ":workaround_list" ]
 }
 
 action("workaround_list") {
@@ -77,9 +71,7 @@
     skia_workaround_list,
   ]
 
-  outputs = [
-    "$target_gen_dir/gpu_driver_bug_workaround_autogen.h",
-  ]
+  outputs = [ "$target_gen_dir/gpu_driver_bug_workaround_autogen.h" ]
 
   args = [
     "--output-file",
@@ -99,9 +91,7 @@
 
     configs += [ "//gpu:gpu_implementation" ]
 
-    deps = [
-      "//gpu/ipc/common:vulkan_interface",
-    ]
+    deps = [ "//gpu/ipc/common:vulkan_interface" ]
 
     all_dependent_configs = [ "//third_party/vulkan:vulkan_config" ]
 
@@ -176,9 +166,7 @@
 
   configs += [ "//gpu:gpu_implementation" ]
 
-  public_deps = [
-    "//components/crash/core/common:crash_key",
-  ]
+  public_deps = [ "//components/crash/core/common:crash_key" ]
 
   if (enable_vulkan) {
     public_deps += [ ":vulkan_info" ]
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star
index 9f733a8..4a570f0eb 100644
--- a/infra/config/lib/builders.star
+++ b/infra/config/lib/builders.star
@@ -31,28 +31,40 @@
 )
 
 
+# The category for an os: a more generic grouping than specific OS versions that
+# can be used for computing defaults
+os_category = struct(
+    ANDROID = 'Android',
+    LINUX = 'Linux',
+    MAC = 'Mac',
+    WINDOWS = 'Windows',
+)
+
 # The os constants to be used for the os parameter of the builder function
 # The *_DEFAULT members enable distinguishing between a use that runs the
 # "current" version of the OS and a use that runs against a specific version
 # that happens to be the "current" version
+def os_enum(dimension, category):
+  return struct(dimension=dimension, category=category)
+
 os = struct(
-    ANDROID = 'Android',
+    ANDROID = os_enum('Android', os_category.ANDROID),
 
-    LINUX_TRUSTY = 'Ubuntu-14.04',
-    LINUX_XENIAL = 'Ubuntu-16.04',
-    LINUX_DEFAULT = 'Ubuntu-16.04',
+    LINUX_TRUSTY = os_enum('Ubuntu-14.04', os_category.LINUX),
+    LINUX_XENIAL = os_enum('Ubuntu-16.04', os_category.LINUX),
+    LINUX_DEFAULT = os_enum('Ubuntu-16.04', os_category.LINUX),
 
-    MAC_10_12 = 'Mac-10.12',
-    MAC_10_13 = 'Mac-10.13',
-    MAC_10_14 = 'Mac-10.14',
-    MAC_DEFAULT = 'Mac-10.13',
-    MAC_ANY = 'Mac',
+    MAC_10_12 = os_enum('Mac-10.12', os_category.MAC),
+    MAC_10_13 = os_enum('Mac-10.13', os_category.MAC),
+    MAC_10_14 = os_enum('Mac-10.14', os_category.MAC),
+    MAC_DEFAULT = os_enum('Mac-10.13', os_category.MAC),
+    MAC_ANY = os_enum('Mac', os_category.MAC),
 
-    WINDOWS_7 = 'Windows-7',
-    WINDOWS_8_1 = 'Windows-8.1',
-    WINDOWS_10 = 'Windows-10',
-    WINDOWS_DEFAULT = 'Windows-10',
-    WINDOWS_ANY = 'Windows',
+    WINDOWS_7 = os_enum('Windows-7', os_category.WINDOWS),
+    WINDOWS_8_1 = os_enum('Windows-8.1', os_category.WINDOWS),
+    WINDOWS_10 = os_enum('Windows-10', os_category.WINDOWS),
+    WINDOWS_DEFAULT = os_enum('Windows-10', os_category.WINDOWS),
+    WINDOWS_ANY = os_enum('Windows', os_category.WINDOWS),
 )
 
 
@@ -108,7 +120,7 @@
 # Implementation details                                                       #
 ################################################################################
 
-_DEFAULT_BUILDERLESS_OSES = [os.LINUX_TRUSTY, os.LINUX_XENIAL]
+_DEFAULT_BUILDERLESS_OS_CATEGORIES = [os_category.LINUX]
 
 
 def _sentinel(tag):
@@ -319,11 +331,11 @@
 
   os = _default('os', os)
   if os:
-    dimensions['os'] = os
+    dimensions['os'] = os.dimension
 
   builderless = _default('builderless', builderless)
   if builderless == _COMPUTE:
-    builderless = os in _DEFAULT_BUILDERLESS_OSES
+    builderless = os != None and os.category in _DEFAULT_BUILDERLESS_OS_CATEGORIES
   if builderless:
     dimensions['builderless'] = '1'
 
diff --git a/ios/chrome/browser/infobars/BUILD.gn b/ios/chrome/browser/infobars/BUILD.gn
index 520b8fb2..6fbb243 100644
--- a/ios/chrome/browser/infobars/BUILD.gn
+++ b/ios/chrome/browser/infobars/BUILD.gn
@@ -29,9 +29,7 @@
     "//ios/web",
     "//ui/gfx",
   ]
-  public_deps = [
-    "//components/infobars/core",
-  ]
+  public_deps = [ "//components/infobars/core" ]
 }
 
 source_set("badge_public") {
@@ -80,9 +78,7 @@
     "infobar_metrics_recorder.mm",
     "infobar_type.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/infobars/overlays/BUILD.gn b/ios/chrome/browser/infobars/overlays/BUILD.gn
index 60a5ca7..8562b8c 100644
--- a/ios/chrome/browser/infobars/overlays/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/BUILD.gn
@@ -45,6 +45,7 @@
     "//base",
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays:overlay_type",
     "//ios/chrome/browser/overlays",
     "//ios/chrome/browser/overlays/public/common/infobars",
   ]
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
index 99e25e3..f6c25a7 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
@@ -4,13 +4,8 @@
 
 source_set("browser_agent") {
   configs += [ "//build/config/compiler:enable_arc" ]
-  friend = [ ":unit_tests" ]
   public = [ "infobar_overlay_browser_agent.h" ]
-  sources = [
-    "infobar_banner_overlay_request_callback_installer.h",
-    "infobar_banner_overlay_request_callback_installer.mm",
-    "infobar_overlay_browser_agent.mm",
-  ]
+  sources = [ "infobar_overlay_browser_agent.mm" ]
   deps = [
     "//base",
     "//ios/chrome/browser/infobars:public",
@@ -44,16 +39,14 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "infobar_banner_overlay_request_callback_installer_unittest.mm",
-    "infobar_overlay_browser_agent_unittest.mm",
-  ]
+  sources = [ "infobar_overlay_browser_agent_unittest.mm" ]
   deps = [
     ":browser_agent",
     "//base/test:test_support",
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays:overlay_type",
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test",
     "//ios/chrome/browser/infobars/test",
     "//ios/chrome/browser/main",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h
index ee85f199..031bead 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h
@@ -24,13 +24,12 @@
  public:
   ~InfobarOverlayBrowserAgent() override;
 
-  // Sets the InfobarInteractionHandler to make model-layer updates for
-  // interactions with infobars with |type|.  OverlayCallbackInstallers will be
-  // created to forward interaction events to each interaction handler.
-  // |interaction_handler| must not be null.  Must only be set once for each
-  // InfobarType.
-  void SetInfobarInteractionHandler(
-      InfobarType type,
+  // Adds an InfobarInteractionHandler to make model-layer updates for
+  // interactions with infobars.  An OverlayCallbackInstaller will be created
+  // from each added handler for each InfobarOverlayType.  |interaction_handler|
+  // must not be null.  Only one interaction handler for a given InfobarType
+  // can be added.
+  void AddInfobarInteractionHandler(
       std::unique_ptr<InfobarInteractionHandler> interaction_handler);
 
  private:
@@ -40,21 +39,21 @@
   BROWSER_USER_DATA_KEY_DECL();
 
   // Returns the interaction handler for the InfobarType of the infobar used to
-  // configure |request|.
+  // configure |request|, or nullptr if |request| is not supported.
   InfobarInteractionHandler* GetInteractionHandler(OverlayRequest* request);
 
-  // Helper object that notifies interaction handler of changes in banner
+  // Helper object that notifies interaction handler of changes in infobar UI
   // visibility.
-  class BannerVisibilityObserver : public OverlayPresenterObserver {
+  class OverlayVisibilityObserver : public OverlayPresenterObserver {
    public:
-    BannerVisibilityObserver(Browser* browser,
-                             InfobarOverlayBrowserAgent* browser_agent);
-    ~BannerVisibilityObserver() override;
+    OverlayVisibilityObserver(Browser* browser,
+                              InfobarOverlayBrowserAgent* browser_agent);
+    ~OverlayVisibilityObserver() override;
 
    private:
     // Notifies the BrowserAgent's interaction handler that the visibility of
-    // |request|'s banner UI has changed.
-    void BannerVisibilityChanged(OverlayRequest* request, bool visible);
+    // |request|'s UI has changed.
+    void OverlayVisibilityChanged(OverlayRequest* request, bool visible);
 
     // OverlayPresenterObserver:
     const OverlayRequestSupport* GetRequestSupport(
@@ -73,7 +72,7 @@
   std::map<InfobarType, std::unique_ptr<InfobarInteractionHandler>>
       interaction_handlers_;
   // The observer for infobar banner presentations and dismissals.
-  BannerVisibilityObserver banner_visibility_observer_;
+  OverlayVisibilityObserver overlay_visibility_observer_;
 };
 
 #endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INFOBAR_OVERLAY_BROWSER_AGENT_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.mm b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.mm
index 65e6b97..641f764 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h"
 
 #include "base/logging.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
 #include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
 
@@ -19,34 +18,33 @@
 
 InfobarOverlayBrowserAgent::InfobarOverlayBrowserAgent(Browser* browser)
     : OverlayBrowserAgentBase(browser),
-      banner_visibility_observer_(browser, this) {}
+      overlay_visibility_observer_(browser, this) {}
 
 InfobarOverlayBrowserAgent::~InfobarOverlayBrowserAgent() = default;
 
 #pragma mark Public
 
-void InfobarOverlayBrowserAgent::SetInfobarInteractionHandler(
-    InfobarType type,
+void InfobarOverlayBrowserAgent::AddInfobarInteractionHandler(
     std::unique_ptr<InfobarInteractionHandler> interaction_handler) {
-  // Only one installer should be set for a single request type.  Otherwise, the
-  // previously-set handler will be destroyed and callbacks forwarded to it will
-  // crash.
+  // Only one installer should be set for a single request type.
+  InfobarType type = interaction_handler->infobar_type();
   DCHECK(!interaction_handlers_[type]);
-  // Create callback installers for each supported handler.
-  const OverlayRequestSupport* support = interaction_handler->request_support();
-  AddInstaller(std::make_unique<InfobarBannerOverlayRequestCallbackInstaller>(
-                   support, interaction_handler->banner_handler()),
+  // Add the banner installer.  Every InfobarType supports banners, so the added
+  // installer is gauranteed to be non-null.
+  AddInstaller(interaction_handler->CreateBannerCallbackInstaller(),
                OverlayModality::kInfobarBanner);
-  InfobarDetailSheetInteractionHandler* sheet_handler =
-      interaction_handler->sheet_handler();
-  if (sheet_handler) {
-    // TODO(crbug.com/1030357): Install callbacks for detail sheet when
-    // implemented.
+  // Add the detail sheet and modal installers.  Not all InfobarTypes support
+  // sheet and modal UI, so the installers must be checked before being added.
+  std::unique_ptr<OverlayRequestCallbackInstaller> detail_sheet_installer =
+      interaction_handler->CreateDetailSheetCallbackInstaller();
+  if (detail_sheet_installer) {
+    AddInstaller(std::move(detail_sheet_installer),
+                 OverlayModality::kInfobarModal);
   }
-  InfobarModalInteractionHandler* modal_handler =
-      interaction_handler->modal_handler();
-  if (modal_handler) {
-    // TODO(crbug.com/1030357): Install callbacks for modal when implemented.
+  std::unique_ptr<OverlayRequestCallbackInstaller> modal_installer =
+      interaction_handler->CreateModalCallbackInstaller();
+  if (modal_installer) {
+    AddInstaller(std::move(modal_installer), OverlayModality::kInfobarModal);
   }
   // Add the interaction handler to the list.
   interaction_handlers_[type] = std::move(interaction_handler);
@@ -56,53 +54,53 @@
 
 InfobarInteractionHandler* InfobarOverlayBrowserAgent::GetInteractionHandler(
     OverlayRequest* request) {
-  auto& interaction_handler =
-      interaction_handlers_[GetOverlayRequestInfobarType(request)];
-  DCHECK(interaction_handler);
-  DCHECK(interaction_handler->request_support()->IsRequestSupported(request));
-  return interaction_handler.get();
+  if (!request)
+    return nullptr;
+  return interaction_handlers_[GetOverlayRequestInfobarType(request)].get();
 }
 
-#pragma mark - InfobarOverlayBrowserAgent::BannerVisibilityObserver
+#pragma mark - InfobarOverlayBrowserAgent::OverlayVisibilityObserver
 
-InfobarOverlayBrowserAgent::BannerVisibilityObserver::BannerVisibilityObserver(
-    Browser* browser,
-    InfobarOverlayBrowserAgent* browser_agent)
+InfobarOverlayBrowserAgent::OverlayVisibilityObserver::
+    OverlayVisibilityObserver(Browser* browser,
+                              InfobarOverlayBrowserAgent* browser_agent)
     : browser_agent_(browser_agent), scoped_observer_(this) {
   DCHECK(browser_agent_);
   scoped_observer_.Add(
       OverlayPresenter::FromBrowser(browser, OverlayModality::kInfobarBanner));
+  scoped_observer_.Add(
+      OverlayPresenter::FromBrowser(browser, OverlayModality::kInfobarModal));
 }
 
-InfobarOverlayBrowserAgent::BannerVisibilityObserver::
-    ~BannerVisibilityObserver() = default;
+InfobarOverlayBrowserAgent::OverlayVisibilityObserver::
+    ~OverlayVisibilityObserver() = default;
 
-void InfobarOverlayBrowserAgent::BannerVisibilityObserver::
-    BannerVisibilityChanged(OverlayRequest* request, bool visible) {
-  browser_agent_->GetInteractionHandler(request)
-      ->banner_handler()
-      ->BannerVisibilityChanged(GetOverlayRequestInfobar(request), visible);
+void InfobarOverlayBrowserAgent::OverlayVisibilityObserver::
+    OverlayVisibilityChanged(OverlayRequest* request, bool visible) {
+  browser_agent_->GetInteractionHandler(request)->InfobarVisibilityChanged(
+      GetOverlayRequestInfobar(request),
+      GetOverlayRequestInfobarOverlayType(request), visible);
 }
 
 const OverlayRequestSupport*
-InfobarOverlayBrowserAgent::BannerVisibilityObserver::GetRequestSupport(
+InfobarOverlayBrowserAgent::OverlayVisibilityObserver::GetRequestSupport(
     OverlayPresenter* presenter) const {
   return browser_agent_->GetRequestSupport(presenter->GetModality());
 }
 
-void InfobarOverlayBrowserAgent::BannerVisibilityObserver::DidShowOverlay(
+void InfobarOverlayBrowserAgent::OverlayVisibilityObserver::DidShowOverlay(
     OverlayPresenter* presenter,
     OverlayRequest* request) {
-  BannerVisibilityChanged(request, /*visible=*/true);
+  OverlayVisibilityChanged(request, /*visible=*/true);
 }
 
-void InfobarOverlayBrowserAgent::BannerVisibilityObserver::DidHideOverlay(
+void InfobarOverlayBrowserAgent::OverlayVisibilityObserver::DidHideOverlay(
     OverlayPresenter* presenter,
     OverlayRequest* request) {
-  BannerVisibilityChanged(request, /*visible=*/false);
+  OverlayVisibilityChanged(request, /*visible=*/false);
 }
 
-void InfobarOverlayBrowserAgent::BannerVisibilityObserver::
+void InfobarOverlayBrowserAgent::OverlayVisibilityObserver::
     OverlayPresenterDestroyed(OverlayPresenter* presenter) {
   scoped_observer_.Remove(presenter);
 }
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_unittest.mm b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_unittest.mm
index 5f8db11..6a20967 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_unittest.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_unittest.mm
@@ -4,14 +4,14 @@
 
 #import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h"
 
+#include <map>
+
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
 #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
-#import "ios/chrome/browser/main/browser_user_data.h"
 #import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
-#include "ios/chrome/browser/overlays/public/infobar_banner/infobar_banner_overlay_responses.h"
 #include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
 #import "ios/chrome/browser/overlays/public/overlay_presenter.h"
 #include "ios/chrome/browser/overlays/public/overlay_request.h"
@@ -32,12 +32,41 @@
 #error "This file requires ARC support."
 #endif
 
+using testing::ByMove;
+using testing::Return;
+
+namespace {
+// Fake dispatch response InfoType for use in tests.
+DEFINE_TEST_OVERLAY_RESPONSE_INFO(DispatchInfo);
+
+// Fake OverlayRequestSupport that supports requests configured with
+// InfobarOverlayRequestConfigs with a specified InfobarOverlayType.
+class FakeInfobarOverlayRequestSupport : public OverlayRequestSupport {
+ public:
+  FakeInfobarOverlayRequestSupport(InfobarOverlayType overlay_type)
+      : overlay_type_(overlay_type) {}
+  FakeInfobarOverlayRequestSupport(FakeInfobarOverlayRequestSupport&& other)
+      : overlay_type_(other.overlay_type_) {}
+
+  bool IsRequestSupported(OverlayRequest* request) const override {
+    InfobarOverlayRequestConfig* config =
+        request->GetConfig<InfobarOverlayRequestConfig>();
+    return config && config->overlay_type() == overlay_type_;
+  }
+
+ private:
+  InfobarOverlayType overlay_type_;
+};
+}  // namespace
+
 // Test fixture for InfobarOverlayBrowserAgent.
-class InfobarOverlayBrowserAgentTest : public PlatformTest {
+class InfobarOverlayBrowserAgentTest
+    : public testing::TestWithParam<InfobarOverlayType> {
  public:
   InfobarOverlayBrowserAgentTest()
       : browser_state_(browser_state_builder_.Build()),
         web_state_list_(&web_state_list_delegate_),
+        interaction_handler_builder_(InfobarType::kInfobarTypeConfirm),
         browser_(browser_state_.get(), &web_state_list_) {
     // Add an activated WebState into whose queues infobar OverlayRequests will
     // be added.
@@ -47,31 +76,82 @@
     web_state_list_.InsertWebState(/*index=*/0, std::move(web_state),
                                    WebStateList::INSERT_ACTIVATE,
                                    WebStateOpener());
-    // Set up the infobar banner OverlayPresenter's presentation context so that
-    // presentation can be faked.
-    banner_presenter()->SetPresentationContext(&banner_presentation_context_);
-    // Set up the browser agent.
+    // Set up the OverlayPresenter's presentation context so that presentation
+    // can be faked.
+    presenter()->SetPresentationContext(&presentation_context_);
+    // Create the request supports for each InfobarOverlayType.
+    request_supports_.emplace(
+        InfobarOverlayType::kBanner,
+        FakeInfobarOverlayRequestSupport(InfobarOverlayType::kBanner));
+    request_supports_.emplace(
+        InfobarOverlayType::kDetailSheet,
+        FakeInfobarOverlayRequestSupport(InfobarOverlayType::kDetailSheet));
+    request_supports_.emplace(
+        InfobarOverlayType::kModal,
+        FakeInfobarOverlayRequestSupport(InfobarOverlayType::kModal));
+    // Create the interaction handler and set up the mock handlers to return
+    // fake callback installers.
+    std::unique_ptr<InfobarInteractionHandler> interaction_handler =
+        interaction_handler_builder_.Build();
+    EXPECT_CALL(*mock_handler(InfobarOverlayType::kBanner), CreateInstaller())
+        .WillOnce(Return(ByMove(CreateInstaller(InfobarOverlayType::kBanner))));
+    EXPECT_CALL(*mock_handler(InfobarOverlayType::kDetailSheet),
+                CreateInstaller())
+        .WillOnce(
+            Return(ByMove(CreateInstaller(InfobarOverlayType::kDetailSheet))));
+    EXPECT_CALL(*mock_handler(InfobarOverlayType::kModal), CreateInstaller())
+        .WillOnce(Return(ByMove(CreateInstaller(InfobarOverlayType::kModal))));
+    // Set up the browser agent and mock interaction handler.
     InfobarOverlayBrowserAgent::CreateForBrowser(&browser_);
-    std::unique_ptr<MockInfobarInteractionHandler> interaction_handler =
-        std::make_unique<MockInfobarInteractionHandler>();
-    mock_interaction_handler_ = interaction_handler.get();
-    browser_agent()->SetInfobarInteractionHandler(
-        InfobarType::kInfobarTypeConfirm, std::move(interaction_handler));
+    InfobarOverlayBrowserAgent::FromBrowser(&browser_)
+        ->AddInfobarInteractionHandler(std::move(interaction_handler));
   }
   ~InfobarOverlayBrowserAgentTest() override {
-    banner_presenter()->SetPresentationContext(nullptr);
+    presenter()->SetPresentationContext(nullptr);
   }
 
-  InfobarOverlayBrowserAgent* browser_agent() {
-    return InfobarOverlayBrowserAgent::FromBrowser(&browser_);
+  // Creates the OverlayRequestCallbackInstaller to return from
+  // CreateInstaller() for the mock interaction handler for |overlay_type|.
+  // Returned installers forwards callbacks to the receivers in
+  // |mock_callback_receivers_|.
+  std::unique_ptr<FakeOverlayRequestCallbackInstaller> CreateInstaller(
+      InfobarOverlayType overlay_type) {
+    std::unique_ptr<FakeOverlayRequestCallbackInstaller> installer =
+        std::make_unique<FakeOverlayRequestCallbackInstaller>(
+            &mock_callback_receivers_[overlay_type]);
+    installer->StartInstallingDispatchCallbacksWithSupport(
+        DispatchInfo::ResponseSupport());
+    installer->SetRequestSupport(&request_supports_.at(overlay_type));
+    return installer;
   }
-  OverlayPresenter* banner_presenter() {
-    return OverlayPresenter::FromBrowser(&browser_,
-                                         OverlayModality::kInfobarBanner);
+
+  // Creates an OverlayRequest configured with an InfobarOverlayRequestConfig
+  // that has the same InfobarOverlayType as the test fixture.
+  std::unique_ptr<OverlayRequest> CreateRequest() {
+    return OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
+        &infobar_, GetParam());
   }
-  OverlayRequestQueue* banner_queue() const {
-    return OverlayRequestQueue::FromWebState(web_state_,
-                                             OverlayModality::kInfobarBanner);
+
+  OverlayModality modality() {
+    return GetParam() == InfobarOverlayType::kBanner
+               ? OverlayModality::kInfobarBanner
+               : OverlayModality::kInfobarModal;
+  }
+  OverlayPresenter* presenter() {
+    return OverlayPresenter::FromBrowser(&browser_, modality());
+  }
+  OverlayRequestQueue* queue() {
+    return OverlayRequestQueue::FromWebState(web_state_, modality());
+  }
+  MockInfobarInteractionHandler::Handler* mock_handler(
+      InfobarOverlayType overlay_type) {
+    return interaction_handler_builder_.mock_handler(overlay_type);
+  }
+  MockInfobarInteractionHandler::Handler* mock_handler() {
+    return mock_handler(GetParam());
+  }
+  MockOverlayRequestCallbackReceiver* mock_callback_receiver() {
+    return &mock_callback_receivers_[GetParam()];
   }
 
  protected:
@@ -81,31 +161,47 @@
   FakeWebStateListDelegate web_state_list_delegate_;
   WebStateList web_state_list_;
   web::WebState* web_state_ = nullptr;
-  TestBrowser browser_;
-  FakeOverlayPresentationContext banner_presentation_context_;
+  std::map<InfobarOverlayType, FakeInfobarOverlayRequestSupport>
+      request_supports_;
+  std::map<InfobarOverlayType, MockOverlayRequestCallbackReceiver>
+      mock_callback_receivers_;
+  MockInfobarInteractionHandler::Builder interaction_handler_builder_;
+  FakeOverlayPresentationContext presentation_context_;
   FakeInfobarIOS infobar_;
-  MockInfobarInteractionHandler* mock_interaction_handler_ = nullptr;
+  TestBrowser browser_;
 };
 
-// Tests that the interaction handler is notified of banner presentation and
-// dismissal.  The rest of InfobarBannerInteractionHandler's interface is tested
-// by InfobarBannerOverlayRequestCallbackInstallerTest.
-TEST_F(InfobarOverlayBrowserAgentTest, BannerPresentation) {
-  // Add an infobar request to the banner modality, expecting
-  // InfobarBannerInteractionHandler::BannerVisibilityChanged() to be called.
-  std::unique_ptr<OverlayRequest> added_request =
-      OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
-          &infobar_, InfobarOverlayType::kBanner);
+// Tests the overlay presentation flow for a given InfobarOverlayType.
+TEST_P(InfobarOverlayBrowserAgentTest, OverlayPresentation) {
+  // Add a supported infobar request to the queue, expecting
+  // MockInfobarBannerInteractionHandler::Handler::InfobarVisibilityChanged() to
+  // be called.
+  std::unique_ptr<OverlayRequest> added_request = CreateRequest();
   OverlayRequest* request = added_request.get();
-  MockInfobarBannerInteractionHandler& mock_banner_handler =
-      *mock_interaction_handler_->mock_banner_handler();
-  EXPECT_CALL(mock_banner_handler,
-              BannerVisibilityChanged(&infobar_, /*visible=*/true));
-  banner_queue()->AddRequest(std::move(added_request));
+  EXPECT_CALL(*mock_handler(),
+              InfobarVisibilityChanged(&infobar_, /*visible=*/true));
+  queue()->AddRequest(std::move(added_request));
+  // Verify that dispatched responses sent through |request|'s callback manager
+  // are received by the expected receiver.
+  std::unique_ptr<OverlayResponse> response =
+      OverlayResponse::CreateWithInfo<DispatchInfo>();
+  EXPECT_CALL(*mock_callback_receiver(),
+              DispatchCallback(request, DispatchInfo::ResponseSupport(),
+                               response.get()));
+  request->GetCallbackManager()->DispatchResponse(std::move(response));
   // Simulate dismissal of the request's UI, expecting
-  // InfobarBannerInteractionHandler::BannerVisibilityChanged() to be called.
-  EXPECT_CALL(mock_banner_handler,
-              BannerVisibilityChanged(&infobar_, /*visible=*/false));
-  banner_presentation_context_.SimulateDismissalForRequest(
+  // MockInfobarBannerInteractionHandler::Handler::InfobarVisibilityChanged()
+  // and MockOverlayRequestCallbackReceiver::CompletionCallback() to
+  // be called.
+  EXPECT_CALL(*mock_handler(),
+              InfobarVisibilityChanged(&infobar_, /*visible=*/false));
+  EXPECT_CALL(*mock_callback_receiver(), CompletionCallback(request, nullptr));
+  presentation_context_.SimulateDismissalForRequest(
       request, OverlayDismissalReason::kUserInteraction);
 }
+
+INSTANTIATE_TEST_SUITE_P(/* No InstantiationName */,
+                         InfobarOverlayBrowserAgentTest,
+                         testing::Values(InfobarOverlayType::kBanner,
+                                         InfobarOverlayType::kDetailSheet,
+                                         InfobarOverlayType::kModal));
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
index 5050696..b6c4e75ee 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
@@ -19,8 +19,7 @@
   InfobarOverlayBrowserAgent::CreateForBrowser(browser);
   InfobarOverlayBrowserAgent* browser_agent =
       InfobarOverlayBrowserAgent::FromBrowser(browser);
-  browser_agent->SetInfobarInteractionHandler(
-      InfobarType::kInfobarTypePasswordSave,
+  browser_agent->AddInfobarInteractionHandler(
       std::make_unique<PasswordInfobarInteractionHandler>());
   // TODO(crbug.com/1030357): Add InfobarInteractionHandlers for each
   // InfobarType when implemented.
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/BUILD.gn
index 6ab7295..b2cb69a0 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/BUILD.gn
@@ -11,6 +11,8 @@
   ]
   deps = [
     "//base",
+    "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays:overlay_type",
     "//ios/chrome/browser/overlays",
   ]
 }
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/BUILD.gn
new file mode 100644
index 0000000..f482e1d
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("common") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  friend = [ ":unit_tests" ]
+  sources = [
+    "infobar_banner_interaction_handler.h",
+    "infobar_banner_interaction_handler.mm",
+    "infobar_banner_overlay_request_callback_installer.h",
+    "infobar_banner_overlay_request_callback_installer.mm",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/infobars/overlays:util",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/common/infobars",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+  ]
+}
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [ "infobar_banner_overlay_request_callback_installer_unittest.mm" ]
+  deps = [
+    ":common",
+    "//base/test:test_support",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test",
+    "//ios/chrome/browser/infobars/test",
+    "//ios/chrome/browser/main",
+    "//ios/chrome/browser/main:test_support",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/common/infobars",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/overlays/test",
+    "//ios/chrome/browser/web_state_list",
+    "//ios/chrome/browser/web_state_list:test_support",
+    "//ios/chrome/test:test_support",
+    "//ios/web/public/test",
+    "//ios/web/public/test/fakes",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h
new file mode 100644
index 0000000..209a7ca
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_INTERACTION_HANDLER_H_
+#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_INTERACTION_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
+
+class OverlayRequestSupport;
+namespace web {
+class WebState;
+}
+
+// A InfobarInteractionHandler::InteractionHandler, intended to be subclassed,
+// that handles interaction events for an infobar banner.
+class InfobarBannerInteractionHandler
+    : public InfobarInteractionHandler::Handler {
+ public:
+  ~InfobarBannerInteractionHandler() override;
+
+  // Updates the model when the visibility of |infobar|'s banner is changed.
+  virtual void BannerVisibilityChanged(InfoBarIOS* infobar, bool visible) = 0;
+  // Updates the model when the main button is tapped for |infobar|'s banner.
+  virtual void MainButtonTapped(InfoBarIOS* infobar) = 0;
+  // Shows the modal when the modal button is tapped for |infobar|'s banner.
+  // |web_state| is the WebState associated with |infobar|'s InfoBarManager.
+  virtual void ShowModalButtonTapped(InfoBarIOS* infobar,
+                                     web::WebState* web_state) = 0;
+  // Notifies the model that the upcoming dismissal is user-initiated (i.e.
+  // swipe dismissal in the refresh UI).
+  virtual void BannerDismissedByUser(InfoBarIOS* infobar) = 0;
+
+ protected:
+  // Constructor for a banner interaction handler that creates callback
+  // installers with |request_support|.
+  explicit InfobarBannerInteractionHandler(
+      const OverlayRequestSupport* request_support);
+
+  // InfobarInteractionHandler::Handler:
+  std::unique_ptr<OverlayRequestCallbackInstaller> CreateInstaller() override;
+  void InfobarVisibilityChanged(InfoBarIOS* infobar, bool visible) override;
+
+ private:
+  // The request support passed on initialization.  Only interactions with
+  // supported requests should be handled by this instance.
+  const OverlayRequestSupport* request_support_ = nullptr;
+};
+
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.mm
new file mode 100644
index 0000000..d4c2984
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.mm
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h"
+
+#include "base/logging.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+InfobarBannerInteractionHandler::InfobarBannerInteractionHandler(
+    const OverlayRequestSupport* request_support)
+    : request_support_(request_support) {
+  DCHECK(request_support_);
+}
+
+InfobarBannerInteractionHandler::~InfobarBannerInteractionHandler() = default;
+
+std::unique_ptr<OverlayRequestCallbackInstaller>
+InfobarBannerInteractionHandler::CreateInstaller() {
+  return std::make_unique<InfobarBannerOverlayRequestCallbackInstaller>(
+      request_support_, this);
+}
+
+void InfobarBannerInteractionHandler::InfobarVisibilityChanged(
+    InfoBarIOS* infobar,
+    bool visible) {
+  BannerVisibilityChanged(infobar, visible);
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h
similarity index 86%
rename from ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h
rename to ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h
index 5051cd2d..4900357 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
+#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
+#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
 
 #include "ios/chrome/browser/overlays/public/overlay_request_callback_installer.h"
 
@@ -18,7 +18,7 @@
   // Constructor for an instance that installs callbacks for OverlayRequests
   // supported by |request_support| that forward interaction events to
   // |interaction_handler|.
-  explicit InfobarBannerOverlayRequestCallbackInstaller(
+  InfobarBannerOverlayRequestCallbackInstaller(
       const OverlayRequestSupport* request_support,
       InfobarBannerInteractionHandler* interaction_handler);
   ~InfobarBannerOverlayRequestCallbackInstaller() override;
@@ -56,4 +56,4 @@
       weak_factory_{this};
 };
 
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_INFOBAR_BANNER_OVERLAY_REQUEST_CALLBACK_INSTALLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm
similarity index 92%
rename from ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.mm
rename to ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm
index 87ac0215..c17abc15 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.mm
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h"
 
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/logging.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
 #include "ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h"
 #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer_unittest.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer_unittest.mm
similarity index 92%
rename from ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer_unittest.mm
rename to ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer_unittest.mm
index 5012fc7..34b805ba 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer_unittest.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer_unittest.mm
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_banner_overlay_request_callback_installer.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_overlay_request_callback_installer.h"
 
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h"
 #import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
 #import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/BUILD.gn
new file mode 100644
index 0000000..d0931fba
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [
+    "mock_infobar_banner_interaction_handler.h",
+    "mock_infobar_banner_interaction_handler.mm",
+  ]
+  deps = [
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common",
+    "//ios/chrome/browser/overlays",
+    "//testing/gmock",
+  ]
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.h
new file mode 100644
index 0000000..be8b78c
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.h
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_TEST_MOCK_INFOBAR_BANNER_INTERACTION_HANDLER_H_
+#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_TEST_MOCK_INFOBAR_BANNER_INTERACTION_HANDLER_H_
+
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class MockInfobarBannerInteractionHandler
+    : public InfobarBannerInteractionHandler {
+ public:
+  MockInfobarBannerInteractionHandler();
+  ~MockInfobarBannerInteractionHandler();
+
+  MOCK_METHOD2(BannerVisibilityChanged,
+               void(InfoBarIOS* infobar, bool visible));
+  MOCK_METHOD1(MainButtonTapped, void(InfoBarIOS* infobar));
+  MOCK_METHOD2(ShowModalButtonTapped,
+               void(InfoBarIOS* infobar, web::WebState* web_state));
+  MOCK_METHOD1(BannerDismissedByUser, void(InfoBarIOS* infobar));
+};
+
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_COMMON_TEST_MOCK_INFOBAR_BANNER_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.mm
new file mode 100644
index 0000000..95e7fd6
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.mm
@@ -0,0 +1,17 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/test/mock_infobar_banner_interaction_handler.h"
+
+#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+MockInfobarBannerInteractionHandler::MockInfobarBannerInteractionHandler()
+    : InfobarBannerInteractionHandler(OverlayRequestSupport::All()) {}
+
+MockInfobarBannerInteractionHandler::~MockInfobarBannerInteractionHandler() =
+    default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h
index 244fcf1..a35a3f7e 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h
@@ -7,44 +7,11 @@
 
 #include <memory>
 
-#include "ios/chrome/browser/overlays/public/overlay_request_support.h"
+#import "ios/chrome/browser/infobars/infobar_type.h"
+#import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
+#include "ios/chrome/browser/overlays/public/overlay_request_callback_installer.h"
 
 class InfoBarIOS;
-namespace web {
-class WebState;
-}
-
-// Handler for infobar banner user interaction events.
-class InfobarBannerInteractionHandler {
- public:
-  virtual ~InfobarBannerInteractionHandler() = default;
-
-  // Updates the model when the visibility of |infobar|'s banner is changed.
-  virtual void BannerVisibilityChanged(InfoBarIOS* infobar, bool visible) = 0;
-  // Updates the model when the main button is tapped for |infobar|'s banner.
-  virtual void MainButtonTapped(InfoBarIOS* infobar) = 0;
-  // Shows the modal when the modal button is tapped for |infobar|'s banner.
-  // |web_state| is the WebState associated with |infobar|'s InfoBarManager.
-  virtual void ShowModalButtonTapped(InfoBarIOS* infobar,
-                                     web::WebState* web_state) = 0;
-  // Notifies the model that the upcoming dismissal is user-initiated (i.e.
-  // a swipe dismissal in the refresh UI).
-  virtual void BannerDismissedByUser(InfoBarIOS* infobar) = 0;
-};
-
-// Handler for infobar detail sheet user interaction events.
-class InfobarDetailSheetInteractionHandler {
- public:
-  virtual ~InfobarDetailSheetInteractionHandler() = default;
-  // TODO(crbug.com/1030357): Add interaction handling for detail sheets.
-};
-
-// Handler for infobar modal user interaction events.
-class InfobarModalInteractionHandler {
- public:
-  virtual ~InfobarModalInteractionHandler() = default;
-  // TODO(crbug.com/1030357): Add interaction handling for modals.
-};
 
 // Helper object, intended to be subclassed, that encapsulates the model-layer
 // updates required for interaction with each type of UI used to display an
@@ -52,46 +19,65 @@
 // user interaction for InfoBars of that type.
 class InfobarInteractionHandler {
  public:
+  // Helper object used by InfobarInteractionHandler to handle interaction for
+  // a single InfobarOverlayType.
+  class Handler {
+   public:
+    Handler() = default;
+    virtual ~Handler() = default;
+
+    // Creates a callback installer used to make model-layer updates for this
+    // handler's InfobarOverlayType.
+    virtual std::unique_ptr<OverlayRequestCallbackInstaller>
+    CreateInstaller() = 0;
+    // Notifies the handler that |infobar|'s UI with the handler's InfobarType
+    virtual void InfobarVisibilityChanged(InfoBarIOS* infobar,
+                                          bool visible) = 0;
+  };
+
+  // Constructor for an InfobarInteractionHandler that uses the provided
+  // handlers for each InfobarOverlayType.  |banner_handler| must be non-null.
+  // |detail_sheet_handler| and |modal_handler| may be null if their
+  // corresponding InfobarOverlayTypes are not supported for |infobar_type|.
+  InfobarInteractionHandler(InfobarType infobar_type,
+                            std::unique_ptr<Handler> banner_handler,
+                            std::unique_ptr<Handler> detail_sheet_handler,
+                            std::unique_ptr<Handler> modal_handler);
   virtual ~InfobarInteractionHandler();
 
-  // Returns the request support for the handler.  Interaction events will only
-  // be handled for supported requests.  Guaranteed to be non-null.
-  const OverlayRequestSupport* request_support() const {
-    return request_support_;
-  }
+  // Returns the InfobarType whose interactions are handled by this instance.
+  InfobarType infobar_type() const { return infobar_type_; }
 
-  // Returns the handlers for each InfobarOverlayType.  Guaranteed to be
-  // non-null.
-  InfobarBannerInteractionHandler* banner_handler() const {
-    return banner_handler_.get();
-  }
-  // Returns the detail sheet handler for this interaction handler.
-  InfobarDetailSheetInteractionHandler* sheet_handler() const {
-    return sheet_handler_.get();
-  }
-  // Returns the modal handler for this interaction handler.
-  InfobarModalInteractionHandler* modal_handler() const {
-    return modal_handler_.get();
-  }
+  // Creates an OverlayRequestCallbackInstaller that handles model-layer updates
+  // the the infobar's banner UI.  Guaranteed to be non-null.
+  std::unique_ptr<OverlayRequestCallbackInstaller>
+  CreateBannerCallbackInstaller();
+
+  // Creates an OverlayRequestCallbackInstaller that handles model-layer updates
+  // the the infobar's detail sheet UI.  Returns null  if detail sheets are not
+  // supported for this InfobarType.
+  std::unique_ptr<OverlayRequestCallbackInstaller>
+  CreateDetailSheetCallbackInstaller();
+
+  // Creates an OverlayRequestCallbackInstaller that handles model-layer updates
+  // the the infobar's modal UI.  Returns null  if modals are not
+  // supported for this InfobarType.
+  std::unique_ptr<OverlayRequestCallbackInstaller>
+  CreateModalCallbackInstaller();
+
+  // Called to notify the interaction handler that |infobar|'s overlay UI with
+  // |overlay_type|'s visibility has changed.
+  void InfobarVisibilityChanged(InfoBarIOS* infobar,
+                                InfobarOverlayType overlay_type,
+                                bool visible);
 
  protected:
-  // Initializer used by subclasses that return the passed handlers from the
-  // getters above.  |banner_handler| must be non-null for all InfobarTypes.
-  // |sheet_handler| and |modal_handler| may be null if the infobar whose
-  // interactions are being handled do not support these overlay types.
-  InfobarInteractionHandler(
-      const OverlayRequestSupport* request_support,
-      std::unique_ptr<InfobarBannerInteractionHandler> banner_handler,
-      std::unique_ptr<InfobarDetailSheetInteractionHandler> sheet_handler,
-      std::unique_ptr<InfobarModalInteractionHandler> modal_handler);
-
-  // The request support passed on initialization.  Only interactions with
-  // supported requests should be handled by this instance.
-  const OverlayRequestSupport* request_support_ = nullptr;
-  // The interaction handlers passed on initialization.
-  std::unique_ptr<InfobarBannerInteractionHandler> banner_handler_;
-  std::unique_ptr<InfobarDetailSheetInteractionHandler> sheet_handler_;
-  std::unique_ptr<InfobarModalInteractionHandler> modal_handler_;
+  // The type of infobar whose interactions are handled by this instance.
+  InfobarType infobar_type_;
+  // The handlers for each InfobarOverlayType.
+  std::unique_ptr<Handler> banner_handler_;
+  std::unique_ptr<Handler> detail_sheet_handler_;
+  std::unique_ptr<Handler> modal_handler_;
 };
 
 #endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.mm
index c32775a..45497bd 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.mm
@@ -11,16 +11,51 @@
 #endif
 
 InfobarInteractionHandler::InfobarInteractionHandler(
-    const OverlayRequestSupport* request_support,
-    std::unique_ptr<InfobarBannerInteractionHandler> banner_handler,
-    std::unique_ptr<InfobarDetailSheetInteractionHandler> sheet_handler,
-    std::unique_ptr<InfobarModalInteractionHandler> modal_handler)
-    : request_support_(request_support),
+    InfobarType infobar_type,
+    std::unique_ptr<Handler> banner_handler,
+    std::unique_ptr<Handler> detail_sheet_handler,
+    std::unique_ptr<Handler> modal_handler)
+    : infobar_type_(infobar_type),
       banner_handler_(std::move(banner_handler)),
-      sheet_handler_(std::move(sheet_handler)),
+      detail_sheet_handler_(std::move(detail_sheet_handler)),
       modal_handler_(std::move(modal_handler)) {
-  DCHECK(request_support_);
-  DCHECK(banner_handler_.get());
+  DCHECK(banner_handler_);
 }
 
 InfobarInteractionHandler::~InfobarInteractionHandler() = default;
+
+std::unique_ptr<OverlayRequestCallbackInstaller>
+InfobarInteractionHandler::CreateBannerCallbackInstaller() {
+  return banner_handler_->CreateInstaller();
+}
+
+std::unique_ptr<OverlayRequestCallbackInstaller>
+InfobarInteractionHandler::CreateDetailSheetCallbackInstaller() {
+  return detail_sheet_handler_ ? detail_sheet_handler_->CreateInstaller()
+                               : nullptr;
+}
+
+std::unique_ptr<OverlayRequestCallbackInstaller>
+InfobarInteractionHandler::CreateModalCallbackInstaller() {
+  return modal_handler_ ? modal_handler_->CreateInstaller() : nullptr;
+}
+
+void InfobarInteractionHandler::InfobarVisibilityChanged(
+    InfoBarIOS* infobar,
+    InfobarOverlayType overlay_type,
+    bool visible) {
+  Handler* handler = nullptr;
+  switch (overlay_type) {
+    case InfobarOverlayType::kBanner:
+      handler = banner_handler_.get();
+      break;
+    case InfobarOverlayType::kDetailSheet:
+      handler = detail_sheet_handler_.get();
+      break;
+    case InfobarOverlayType::kModal:
+      handler = modal_handler_.get();
+      break;
+  }
+  if (handler)
+    handler->InfobarVisibilityChanged(infobar, visible);
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
index 27a7a64..25249927 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
@@ -13,7 +13,9 @@
   deps = [
     "//base",
     "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/infobars:public",
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common",
     "//ios/chrome/browser/overlays/public/infobar_banner",
     "//ios/chrome/browser/passwords:infobar_delegates",
   ]
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h
index baa678f..60e8088 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h
@@ -5,7 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_BANNER_INTERACTION_HANDLER_H_
 #define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_BANNER_INTERACTION_HANDLER_H_
 
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h"
 
 class IOSChromeSavePasswordInfoBarDelegate;
 
@@ -14,6 +14,9 @@
 class PasswordInfobarBannerInteractionHandler
     : public InfobarBannerInteractionHandler {
  public:
+  PasswordInfobarBannerInteractionHandler();
+  ~PasswordInfobarBannerInteractionHandler() override;
+
   // InfobarBannerInteractionHandler:
   void BannerVisibilityChanged(InfoBarIOS* infobar, bool visible) override;
   void MainButtonTapped(InfoBarIOS* infobar) override;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.mm
index 3d686681..61155b8 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.mm
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "ios/chrome/browser/infobars/infobar_ios.h"
+#import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
 #import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -14,6 +15,14 @@
 
 #pragma mark - InfobarBannerInteractionHandler
 
+PasswordInfobarBannerInteractionHandler::
+    PasswordInfobarBannerInteractionHandler()
+    : InfobarBannerInteractionHandler(
+          SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport()) {}
+
+PasswordInfobarBannerInteractionHandler::
+    ~PasswordInfobarBannerInteractionHandler() = default;
+
 void PasswordInfobarBannerInteractionHandler::BannerVisibilityChanged(
     InfoBarIOS* infobar,
     bool visible) {
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.mm
index 8287687..9cb2ff91 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.h"
 
+#import "ios/chrome/browser/infobars/infobar_type.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h"
 #import "ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.h"
 
@@ -13,7 +14,7 @@
 
 PasswordInfobarInteractionHandler::PasswordInfobarInteractionHandler()
     : InfobarInteractionHandler(
-          SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport(),
+          InfobarType::kInfobarTypePasswordSave,
           std::make_unique<PasswordInfobarBannerInteractionHandler>(),
           /*sheet_handler=*/nullptr,
           /*modal_handler=*/nullptr) {
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/BUILD.gn
index 0e8919e..dd9040c 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/BUILD.gn
@@ -13,6 +13,8 @@
 
   deps = [
     "//base",
+    "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays",
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers",
     "//ios/chrome/browser/overlays",
     "//ios/chrome/browser/overlays/public/common/infobars",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h
index e740ad37..bb5eb4b 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h
@@ -5,67 +5,50 @@
 #ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TEST_MOCK_INFOBAR_INTERACTION_HANDLER_H_
 #define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TEST_MOCK_INFOBAR_INTERACTION_HANDLER_H_
 
+#include <map>
+
+#import "ios/chrome/browser/infobars/infobar_type.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
-// Mock version of InfobarBannerInteractionHandler.
-class MockInfobarBannerInteractionHandler
-    : public InfobarBannerInteractionHandler {
- public:
-  MockInfobarBannerInteractionHandler();
-  ~MockInfobarBannerInteractionHandler() override;
-
-  MOCK_METHOD2(BannerVisibilityChanged,
-               void(InfoBarIOS* infobar, bool visible));
-  MOCK_METHOD1(MainButtonTapped, void(InfoBarIOS* infobar));
-  MOCK_METHOD2(ShowModalButtonTapped,
-               void(InfoBarIOS* infobar, web::WebState* web_state));
-  MOCK_METHOD1(BannerDismissedByUser, void(InfoBarIOS* infobar));
-};
-
-// Mock version of InfobarDetailSheetInteractionHandler.
-class MockInfobarDetailSheetInteractionHandler
-    : public InfobarDetailSheetInteractionHandler {
- public:
-  MockInfobarDetailSheetInteractionHandler();
-  ~MockInfobarDetailSheetInteractionHandler() override;
-
-  // TODO(crbug.com/1030357): Add mock interaction handling for detail sheets.
-};
-
-// Mock version of MockInfobarModalInteractionHandler.
-class MockInfobarModalInteractionHandler
-    : public InfobarModalInteractionHandler {
- public:
-  MockInfobarModalInteractionHandler();
-  ~MockInfobarModalInteractionHandler() override;
-
-  // TODO(crbug.com/1030357): Add mock interaction handling for modals.
-};
-
-// InfobarModalInteractionHandler subclass that returns mock versions of the
-// banner, detail sheet, and modal interaction handlers.
+// Mock implementation of InfobarInteractionHandler for use in tests.
 class MockInfobarInteractionHandler : public InfobarInteractionHandler {
  public:
-  MockInfobarInteractionHandler();
-  ~MockInfobarInteractionHandler() override;
+  // Mock handler object used by the builder
+  class Handler : public InfobarInteractionHandler::Handler {
+   public:
+    Handler();
+    ~Handler() override;
 
-  MockInfobarBannerInteractionHandler* mock_banner_handler() {
-    return mock_banner_handler_;
-  }
-  MockInfobarDetailSheetInteractionHandler* mock_sheet_handler() {
-    return mock_sheet_handler_;
-  }
-  MockInfobarModalInteractionHandler* mock_modal_handler() {
-    return mock_modal_handler_;
-  }
+    MOCK_METHOD0(CreateInstaller,
+                 std::unique_ptr<OverlayRequestCallbackInstaller>(void));
+    MOCK_METHOD2(InfobarVisibilityChanged,
+                 void(InfoBarIOS* infobar, bool visible));
+  };
 
- private:
-  // Pointers to the mock handlers passed to the InfobarInteractionHandler
-  // constructor.  Guaranteed to be non-null for the lifetime of the object.
-  MockInfobarBannerInteractionHandler* mock_banner_handler_ = nullptr;
-  MockInfobarDetailSheetInteractionHandler* mock_sheet_handler_ = nullptr;
-  MockInfobarModalInteractionHandler* mock_modal_handler_ = nullptr;
+  // Helper object that builds InfobarInteractionHandlers with mock handlers.
+  class Builder {
+   public:
+    explicit Builder(InfobarType infobar_type);
+    ~Builder();
+
+    // Constructs an InfobarInteractionHandler using mock handlers.  Calling
+    // this function also populates |mock_handlers_|.  Must only be called once
+    // per Builder.
+    std::unique_ptr<InfobarInteractionHandler> Build();
+
+    // Returns the mock handler for |overlay_type| used to build the
+    // InfobarInteractionHandler.  Returns null before Build() is called.
+    Handler* mock_handler(InfobarOverlayType overlay_type) {
+      return mock_handlers_[overlay_type];
+    }
+
+   private:
+    InfobarType infobar_type_;
+    bool has_built_ = false;
+    std::map<InfobarOverlayType, Handler*> mock_handlers_;
+  };
 };
 
 #endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TEST_MOCK_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.mm
index 60fa1a6..a87eee1 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.mm
@@ -4,50 +4,39 @@
 
 #import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/mock_infobar_interaction_handler.h"
 
-#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
+#include "base/logging.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-#pragma mark - MockInfobarBannerInteractionHandler
+#pragma mark - MockInfobarInteractionHandler::Handler
 
-MockInfobarBannerInteractionHandler::MockInfobarBannerInteractionHandler() =
-    default;
+MockInfobarInteractionHandler::Handler::Handler() = default;
+MockInfobarInteractionHandler::Handler::~Handler() = default;
 
-MockInfobarBannerInteractionHandler::~MockInfobarBannerInteractionHandler() =
-    default;
+#pragma mark - MockInfobarInteractionHandler::Builder
 
-#pragma mark - MockInfobarDetailSheetInteractionHandler
+MockInfobarInteractionHandler::Builder::Builder(InfobarType infobar_type)
+    : infobar_type_(infobar_type) {}
 
-MockInfobarDetailSheetInteractionHandler::
-    MockInfobarDetailSheetInteractionHandler() = default;
+MockInfobarInteractionHandler::Builder::~Builder() = default;
 
-MockInfobarDetailSheetInteractionHandler::
-    ~MockInfobarDetailSheetInteractionHandler() = default;
+std::unique_ptr<InfobarInteractionHandler>
+MockInfobarInteractionHandler::Builder::Build() {
+  DCHECK(!has_built_);
+  has_built_ = true;
 
-#pragma mark - MockInfobarModalInteractionHandler
-
-MockInfobarModalInteractionHandler::MockInfobarModalInteractionHandler() =
-    default;
-
-MockInfobarModalInteractionHandler::~MockInfobarModalInteractionHandler() =
-    default;
-
-#pragma mark - MockInfobarModalInteractionHandler
-
-MockInfobarInteractionHandler::MockInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarOverlayRequestConfig::RequestSupport(),
-          std::make_unique<MockInfobarBannerInteractionHandler>(),
-          std::make_unique<MockInfobarDetailSheetInteractionHandler>(),
-          std::make_unique<MockInfobarModalInteractionHandler>()) {
-  mock_banner_handler_ =
-      static_cast<MockInfobarBannerInteractionHandler*>(banner_handler());
-  mock_sheet_handler_ =
-      static_cast<MockInfobarDetailSheetInteractionHandler*>(sheet_handler());
-  mock_modal_handler_ =
-      static_cast<MockInfobarModalInteractionHandler*>(modal_handler());
+  std::unique_ptr<MockInfobarInteractionHandler::Handler> banner_handler =
+      std::make_unique<MockInfobarInteractionHandler::Handler>();
+  std::unique_ptr<MockInfobarInteractionHandler::Handler> sheet_handler =
+      std::make_unique<MockInfobarInteractionHandler::Handler>();
+  std::unique_ptr<MockInfobarInteractionHandler::Handler> modal_handler =
+      std::make_unique<MockInfobarInteractionHandler::Handler>();
+  mock_handlers_[InfobarOverlayType::kBanner] = banner_handler.get();
+  mock_handlers_[InfobarOverlayType::kDetailSheet] = sheet_handler.get();
+  mock_handlers_[InfobarOverlayType::kModal] = modal_handler.get();
+  return std::make_unique<InfobarInteractionHandler>(
+      infobar_type_, std::move(banner_handler), std::move(sheet_handler),
+      std::move(modal_handler));
 }
-
-MockInfobarInteractionHandler::~MockInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h b/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h
index eaa158a..581ffac8 100644
--- a/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h
+++ b/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_OVERLAY_REQUEST_INFOBAR_UTIL_H_
 
 #import "ios/chrome/browser/infobars/infobar_type.h"
+#import "ios/chrome/browser/infobars/overlays/infobar_overlay_type.h"
 
 class InfoBarIOS;
 class OverlayRequest;
@@ -21,4 +22,8 @@
 // InfobarType::kNone once added.
 InfobarType GetOverlayRequestInfobarType(OverlayRequest* request);
 
+// Returns the InfobarOverlayType for |request|.  |request| must be non-null and
+// configured with an InfobarOverlayRequestConfig.
+InfobarOverlayType GetOverlayRequestInfobarOverlayType(OverlayRequest* request);
+
 #endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_OVERLAY_REQUEST_INFOBAR_UTIL_H_
diff --git a/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.mm b/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.mm
index 1e9b919b..3c74675 100644
--- a/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.mm
+++ b/ios/chrome/browser/infobars/overlays/overlay_request_infobar_util.mm
@@ -21,3 +21,8 @@
 InfobarType GetOverlayRequestInfobarType(OverlayRequest* request) {
   return request->GetConfig<InfobarOverlayRequestConfig>()->infobar_type();
 }
+
+InfobarOverlayType GetOverlayRequestInfobarOverlayType(
+    OverlayRequest* request) {
+  return request->GetConfig<InfobarOverlayRequestConfig>()->overlay_type();
+}
diff --git a/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn b/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
index 35830f2..ef73c7a 100644
--- a/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
+++ b/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
@@ -4,8 +4,6 @@
 
 source_set("infobars") {
   sources = [
-    "infobar_banner_overlay_request_config.h",
-    "infobar_banner_overlay_request_config.mm",
     "infobar_overlay_request_config.h",
     "infobar_overlay_request_config.mm",
   ]
diff --git a/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.h b/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.h
deleted file mode 100644
index b5747c0..0000000
--- a/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.h
+++ /dev/null
@@ -1,52 +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 IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_COMMON_INFOBARS_INFOBAR_BANNER_OVERLAY_REQUEST_CONFIG_H_
-#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_COMMON_INFOBARS_INFOBAR_BANNER_OVERLAY_REQUEST_CONFIG_H_
-
-#import <Foundation/Foundation.h>
-
-#include "ios/chrome/browser/overlays/public/overlay_user_data.h"
-
-// OverlayUserData used to configure an InfobarBannerConsumer.  Used as
-// auxiliary data for OverlayRequests for InfoBars.
-class InfobarBannerOverlayRequestConfig
-    : public OverlayUserData<InfobarBannerOverlayRequestConfig> {
- public:
-  ~InfobarBannerOverlayRequestConfig() override;
-
-  // The optional accessibility label to use for the banner UI.
-  NSString* banner_accessibility_label() const {
-    return banner_accessibility_label_;
-  }
-  // The text to add to the button.
-  NSString* button_text() const { return button_text_; }
-  // The name of the image to use for the banner icon.
-  NSString* icon_image_name() const { return icon_image_name_; }
-  // Whether the banner can present a modal.
-  bool presents_modal() const { return presents_modal_; }
-  // The title text of the banner.
-  NSString* title_text() const { return title_text_; }
-  // The subtitle text of the banner.
-  NSString* subtitle_text() const { return subtitle_text_; }
-
- private:
-  OVERLAY_USER_DATA_SETUP(InfobarBannerOverlayRequestConfig);
-  explicit InfobarBannerOverlayRequestConfig(
-      NSString* banner_accessibility_label,
-      NSString* button_text,
-      NSString* icon_image_name,
-      bool presents_modal,
-      NSString* title_text,
-      NSString* subtitle_text);
-
-  NSString* banner_accessibility_label_;
-  NSString* button_text_;
-  NSString* icon_image_name_;
-  bool presents_modal_ = false;
-  NSString* title_text_;
-  NSString* subtitle_text_;
-};
-
-#endif  // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_COMMON_INFOBARS_INFOBAR_BANNER_OVERLAY_REQUEST_CONFIG_H_
diff --git a/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.mm b/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.mm
deleted file mode 100644
index c8dbe16..0000000
--- a/ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.mm
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/overlays/public/common/infobars/infobar_banner_overlay_request_config.h"
-
-#include "base/logging.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-OVERLAY_USER_DATA_SETUP_IMPL(InfobarBannerOverlayRequestConfig);
-
-InfobarBannerOverlayRequestConfig::InfobarBannerOverlayRequestConfig(
-    NSString* banner_accessibility_label,
-    NSString* button_text,
-    NSString* icon_image_name,
-    bool presents_modal,
-    NSString* title_text,
-    NSString* subtitle_text)
-    : banner_accessibility_label_(banner_accessibility_label),
-      button_text_(button_text),
-      icon_image_name_(icon_image_name),
-      presents_modal_(presents_modal),
-      title_text_(title_text),
-      subtitle_text_(subtitle_text) {}
-
-InfobarBannerOverlayRequestConfig::~InfobarBannerOverlayRequestConfig() =
-    default;
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn b/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn
new file mode 100644
index 0000000..e5dc84e
--- /dev/null
+++ b/ios/chrome/browser/overlays/public/infobar_modal/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("infobar_modal") {
+  sources = [
+    "password_infobar_modal_overlay_request_config.h",
+    "password_infobar_modal_overlay_request_config.mm",
+  ]
+
+  configs += [ "//build/config/compiler:enable_arc" ]
+
+  deps = [
+    "//base",
+    "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/overlays/public/common/infobars",
+    "//ios/chrome/browser/passwords:infobar_delegates",
+  ]
+}
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h b/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h
new file mode 100644
index 0000000..135fa97
--- /dev/null
+++ b/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_REQUEST_CONFIG_H_
+#define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_REQUEST_CONFIG_H_
+
+#include "ios/chrome/browser/overlays/public/overlay_request_config.h"
+
+class InfoBarIOS;
+class IOSChromeSavePasswordInfoBarDelegate;
+
+namespace password_modal {
+// The action to take for a password modal request.
+enum class PasswordAction : short { kSave, kUpdate };
+}  // password_modal
+
+// Configuration object for OverlayRequests for the modal UI for an infobar
+// with a IOSChromeSavePasswordInfoBarDelegate.
+class PasswordInfobarModalOverlayRequestConfig
+    : public OverlayRequestConfig<PasswordInfobarModalOverlayRequestConfig> {
+ public:
+  ~PasswordInfobarModalOverlayRequestConfig() override;
+
+  // The action to take with the password for the requested modal view.
+  password_modal::PasswordAction action() const { return action_; }
+  // The modal's title.
+  NSString* title() const { return title_; }
+  // The username for which passwords are being saved.
+  NSString* username() const { return username_; }
+  // The password being saved.
+  NSString* password() const { return password_; }
+  // The details text.
+  NSString* details_text() const { return details_text_; }
+  // The text to show on the save button.
+  NSString* save_button_text() const { return save_button_text_; }
+  // The text to show on the cancel button.
+  NSString* cancel_button_text() const { return cancel_button_text_; }
+  // The URL string.
+  NSString* url() const { return url_; }
+  // Whether the current password has been saved.
+  bool is_current_password_saved() const { return is_current_password_saved_; }
+
+ private:
+  OVERLAY_USER_DATA_SETUP(PasswordInfobarModalOverlayRequestConfig);
+  explicit PasswordInfobarModalOverlayRequestConfig(InfoBarIOS* infobar);
+
+  // OverlayUserData:
+  void CreateAuxilliaryData(base::SupportsUserData* user_data) override;
+
+  // The InfoBar causing this modal.
+  InfoBarIOS* infobar_ = nullptr;
+  // Configuration data extracted from |infobar_|'s save passwords delegate.
+  password_modal::PasswordAction action_;
+  NSString* title_ = nil;
+  NSString* username_ = nil;
+  NSString* password_ = nil;
+  NSString* details_text_ = nil;
+  NSString* save_button_text_ = nil;
+  NSString* cancel_button_text_ = nil;
+  NSString* url_ = nil;
+  bool is_current_password_saved_ = false;
+};
+
+#endif  // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_INFOBAR_MODAL_PASSWORD_INFOBAR_MODAL_OVERLAY_REQUEST_CONFIG_H_
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.mm b/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.mm
new file mode 100644
index 0000000..318bca3
--- /dev/null
+++ b/ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.mm
@@ -0,0 +1,49 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
+
+#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/infobars/infobar_ios.h"
+#import "ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h"
+#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using password_modal::PasswordAction;
+
+OVERLAY_USER_DATA_SETUP_IMPL(PasswordInfobarModalOverlayRequestConfig);
+
+PasswordInfobarModalOverlayRequestConfig::
+    PasswordInfobarModalOverlayRequestConfig(InfoBarIOS* infobar)
+    : infobar_(infobar) {
+  DCHECK(infobar_);
+  IOSChromeSavePasswordInfoBarDelegate* delegate =
+      IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
+          infobar_->delegate());
+  action_ = delegate->IsPasswordUpdate() ? PasswordAction::kUpdate
+                                         : PasswordAction::kSave;
+  title_ = delegate->GetInfobarModalTitleText();
+  username_ = delegate->GetUserNameText();
+  password_ = delegate->GetPasswordText();
+  details_text_ = delegate->GetDetailsMessageText();
+  save_button_text_ = base::SysUTF16ToNSString(
+      delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK));
+  cancel_button_text_ = base::SysUTF16ToNSString(
+      delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL));
+  url_ = delegate->GetURLHostText();
+  is_current_password_saved_ = delegate->IsCurrentPasswordSaved();
+}
+
+PasswordInfobarModalOverlayRequestConfig::
+    ~PasswordInfobarModalOverlayRequestConfig() = default;
+
+void PasswordInfobarModalOverlayRequestConfig::CreateAuxilliaryData(
+    base::SupportsUserData* user_data) {
+  InfobarOverlayRequestConfig::CreateForUserData(user_data, infobar_,
+                                                 InfobarOverlayType::kModal);
+}
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index bf2dd658..e2c54a03 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -148,9 +148,7 @@
     "//ios/web/common",
     "//ui/base",
   ]
-  public_deps = [
-    "//ios/third_party/material_components_ios",
-  ]
+  public_deps = [ "//ios/third_party/material_components_ios" ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
@@ -159,9 +157,7 @@
     "ntp_home_constant.h",
     "ntp_home_constant.mm",
   ]
-  deps = [
-    "//ios/chrome/common/colors",
-  ]
+  deps = [ "//ios/chrome/common/colors" ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
@@ -328,13 +324,9 @@
   ]
   testonly = true
 
-  sources = [
-    "content_suggestions_app_interface.h",
-  ]
+  sources = [ "content_suggestions_app_interface.h" ]
 
-  deps = [
-    "//ios/third_party/earl_grey2:test_lib",
-  ]
+  deps = [ "//ios/third_party/earl_grey2:test_lib" ]
 }
 
 source_set("eg_app_support+eg2") {
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
index 947de78..31c57c73 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
@@ -69,9 +69,7 @@
     "//ios/chrome/common/ui_util",
     "//ui/base",
   ]
-  public_deps = [
-    "//ios/third_party/material_components_ios",
-  ]
+  public_deps = [ "//ios/third_party/material_components_ios" ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
diff --git a/ios/chrome/browser/ui/content_suggestions/identifier/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/identifier/BUILD.gn
index 494e717..d01df79f 100644
--- a/ios/chrome/browser/ui/content_suggestions/identifier/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/identifier/BUILD.gn
@@ -9,17 +9,13 @@
     "content_suggestions_section_information.h",
     "content_suggestions_section_information.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   configs += [ "//build/config/compiler:enable_arc" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "content_suggestion_identifier_unittest.mm",
-  ]
+  sources = [ "content_suggestion_identifier_unittest.mm" ]
   deps = [
     ":identifier",
     "//testing/gtest",
diff --git a/ios/chrome/browser/ui/overlays/BUILD.gn b/ios/chrome/browser/ui/overlays/BUILD.gn
index 04fa775..097f97c 100644
--- a/ios/chrome/browser/ui/overlays/BUILD.gn
+++ b/ios/chrome/browser/ui/overlays/BUILD.gn
@@ -57,6 +57,7 @@
     "overlay_request_coordinator.h",
     "overlay_request_coordinator.mm",
     "overlay_request_coordinator_delegate.h",
+    "overlay_request_mediator+subclassing.h",
     "overlay_request_mediator.h",
     "overlay_request_mediator.mm",
   ]
@@ -87,5 +88,6 @@
     "//ios/chrome/browser/overlays/test",
     "//ios/chrome/browser/ui/overlays/test",
     "//testing/gtest",
+    "//third_party/ocmock",
   ]
 }
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
index f11c463b..f34c1f3b 100644
--- a/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
+++ b/ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator.mm
@@ -15,6 +15,7 @@
 #include "ios/chrome/browser/overlays/public/overlay_response.h"
 #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_consumer.h"
 #import "ios/chrome/browser/ui/overlays/infobar_banner/infobar_banner_overlay_mediator+consumer_support.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -72,16 +73,6 @@
   // in InfobarBannerOverlayCoordinator.
 }
 
-#pragma mark - Private
-
-// Dispatches |response| through the OverlayRequest, then stops the overlay UI.
-- (void)dispatchResponseAndStopOverlay:
-    (std::unique_ptr<OverlayResponse>)response {
-  if (self.request)
-    self.request->GetCallbackManager()->DispatchResponse(std::move(response));
-  [self.delegate stopOverlayForMediator:self];
-}
-
 @end
 
 @implementation InfobarBannerOverlayMediator (ConsumerSupport)
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h b/ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h
new file mode 100644
index 0000000..2a80a51
--- /dev/null
+++ b/ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_MEDIATOR_SUBCLASSING_H_
+#define IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_MEDIATOR_SUBCLASSING_H_
+
+#import "ios/chrome/browser/ui/overlays/overlay_request_mediator.h"
+
+#include <memory>
+
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+
+// Exposes shared functionality for OverlayRequestMediator subclasses.
+@interface OverlayRequestMediator (Subclassing)
+
+// Dispatches |response| through the mediator's request callback manager, then
+// instructs the delegate to stop the overlay.
+- (void)dispatchResponseAndStopOverlay:
+    (std::unique_ptr<OverlayResponse>)response;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_OVERLAYS_OVERLAY_REQUEST_MEDIATOR_SUBCLASSING_H_
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_mediator.mm b/ios/chrome/browser/ui/overlays/overlay_request_mediator.mm
index e69e03a..4cdd1b26 100644
--- a/ios/chrome/browser/ui/overlays/overlay_request_mediator.mm
+++ b/ios/chrome/browser/ui/overlays/overlay_request_mediator.mm
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #import "ios/chrome/browser/ui/overlays/overlay_request_mediator.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h"
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -51,3 +52,14 @@
 }
 
 @end
+
+@implementation OverlayRequestMediator (Subclassing)
+
+- (void)dispatchResponseAndStopOverlay:
+    (std::unique_ptr<OverlayResponse>)response {
+  if (self.request)
+    self.request->GetCallbackManager()->DispatchResponse(std::move(response));
+  [self.delegate stopOverlayForMediator:self];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm
index 24835f1..0b2a17f 100644
--- a/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm
@@ -3,15 +3,28 @@
 // found in the LICENSE file.
 
 #import "ios/chrome/browser/ui/overlays/overlay_request_mediator.h"
+#import "ios/chrome/browser/ui/overlays/overlay_request_mediator+subclassing.h"
 
+#import "base/bind.h"
+#include "ios/chrome/browser/overlays/public/overlay_callback_manager.h"
 #include "ios/chrome/browser/overlays/public/overlay_request.h"
+#include "ios/chrome/browser/overlays/public/overlay_response.h"
+#include "ios/chrome/browser/overlays/public/overlay_response_support.h"
 #include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h"
+#include "ios/chrome/browser/overlays/test/overlay_test_macros.h"
 #include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// InfoType used to create dispatched respones in test.
+DEFINE_TEST_OVERLAY_RESPONSE_INFO(DispatchInfo);
+}
+
 // Test fixture for OverlayRequestMediator.
 using OverlayRequestMediatorTest = PlatformTest;
 
@@ -25,3 +38,33 @@
   request = nullptr;
   EXPECT_EQ(nullptr, mediator.request);
 }
+
+// Tests that the |-dispatchResponseAndStopOverlay:| correctly dispatches the
+// response and stops the overlay.
+TEST_F(OverlayRequestMediatorTest, DispatchResponseAndStopOverlay) {
+  std::unique_ptr<OverlayRequest> request =
+      OverlayRequest::CreateWithConfig<FakeOverlayUserData>();
+  // Add a dispatch callback that sets |dispatch_callback_executed| to true
+  // upon receiving an OverlayResponse created with DispatchInfo.
+  __block bool dispatch_callback_executed = false;
+  std::unique_ptr<OverlayResponse> dispatched_response =
+      OverlayResponse::CreateWithInfo<DispatchInfo>();
+  OverlayResponse* response_copy = dispatched_response.get();
+  request->GetCallbackManager()->AddDispatchCallback(
+      OverlayDispatchCallback(base::BindRepeating(^(OverlayResponse* response) {
+                                dispatch_callback_executed = true;
+                                EXPECT_EQ(response_copy, response);
+                              }),
+                              DispatchInfo::ResponseSupport()));
+  OverlayRequestMediator* mediator =
+      [[OverlayRequestMediator alloc] initWithRequest:request.get()];
+  id<OverlayRequestMediatorDelegate> delegate =
+      OCMStrictProtocolMock(@protocol(OverlayRequestMediatorDelegate));
+  mediator.delegate = delegate;
+  OCMExpect([delegate stopOverlayForMediator:mediator]);
+
+  [mediator dispatchResponseAndStopOverlay:std::move(dispatched_response)];
+
+  EXPECT_TRUE(dispatch_callback_executed);
+  EXPECT_OCMOCK_VERIFY(delegate);
+}
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
index 1bc5a2c..bafe33ac 100644
--- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -38,9 +38,7 @@
     "//ios/chrome/browser/web_state_list",
     "//ui/base",
   ]
-  public_deps = [
-    "//components/sync_sessions",
-  ]
+  public_deps = [ "//components/sync_sessions" ]
 }
 
 source_set("recent_tabs_ui_constants") {
@@ -95,17 +93,13 @@
     "//ios/chrome/common/favicon",
     "//ui/base",
   ]
-  public_deps = [
-    "//components/sync_sessions",
-  ]
+  public_deps = [ "//components/sync_sessions" ]
 }
 
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "recent_tabs_coordinator_unittest.mm",
-  ]
+  sources = [ "recent_tabs_coordinator_unittest.mm" ]
   deps = [
     ":recent_tabs",
     ":recent_tabs_ui",
@@ -136,9 +130,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "recent_tabs_egtest.mm",
-  ]
+  sources = [ "recent_tabs_egtest.mm" ]
   deps = [
     ":recent_tabs_ui",
     ":recent_tabs_ui_constants",
@@ -173,9 +165,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "recent_tabs_egtest.mm",
-  ]
+  sources = [ "recent_tabs_egtest.mm" ]
   deps = [
     ":recent_tabs_ui_constants",
     "//base/test:test_support",
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn
index 388bb9d3..9273ce9 100644
--- a/ios/chrome/browser/ui/settings/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -38,9 +38,7 @@
     "settings_root_table_constants.h",
     "settings_root_table_constants.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("settings") {
@@ -449,9 +447,7 @@
     "//ios/chrome/test/app:test_support",
     "//third_party/breakpad:client",
   ]
-  public_deps = [
-    "//components/content_settings/core/common",
-  ]
+  public_deps = [ "//components/content_settings/core/common" ]
 }
 
 source_set("eg_test_support+eg2") {
@@ -463,12 +459,8 @@
     "settings_app_interface.h",
     "signin_settings_app_interface.h",
   ]
-  public_deps = [
-    "//components/content_settings/core/common",
-  ]
-  deps = [
-    "//base",
-  ]
+  public_deps = [ "//components/content_settings/core/common" ]
+  deps = [ "//base" ]
 }
 
 source_set("eg2_tests") {
diff --git a/ios/chrome/browser/ui/settings/autofill/BUILD.gn b/ios/chrome/browser/ui/settings/autofill/BUILD.gn
index 5bf747d8..907d658 100644
--- a/ios/chrome/browser/ui/settings/autofill/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/autofill/BUILD.gn
@@ -75,9 +75,7 @@
     "features.h",
     "features.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn
index 42b6cb11..854eea2 100644
--- a/ios/chrome/browser/ui/settings/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -53,9 +53,7 @@
     "//ui/base",
   ]
 
-  public_deps = [
-    ":clear_browsing_data_constants",
-  ]
+  public_deps = [ ":clear_browsing_data_constants" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
index f815356..61899da 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -122,9 +122,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "clear_browsing_data_egtest.mm",
-  ]
+  sources = [ "clear_browsing_data_egtest.mm" ]
   deps = [
     "//base/test:test_support",
     "//ios/chrome/app/strings",
@@ -142,9 +140,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "clear_browsing_data_egtest.mm",
-  ]
+  sources = [ "clear_browsing_data_egtest.mm" ]
   deps = [
     "//base/test:test_support",
     "//ios/chrome/app/strings",
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
index e5102dfc..f80160bf 100644
--- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -162,9 +162,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "google_services_settings_app_interface.h",
-  ]
+  sources = [ "google_services_settings_app_interface.h" ]
 }
 
 source_set("eg2_tests") {
diff --git a/ios/chrome/browser/ui/settings/language/BUILD.gn b/ios/chrome/browser/ui/settings/language/BUILD.gn
index 0073dee..3e72ea5f 100644
--- a/ios/chrome/browser/ui/settings/language/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/language/BUILD.gn
@@ -57,9 +57,7 @@
     "//ios/chrome/common/ui_util",
     "//ui/base",
   ]
-  public_deps = [
-    ":language_ui_constants",
-  ]
+  public_deps = [ ":language_ui_constants" ]
 }
 
 source_set("language_ui_constants") {
@@ -73,9 +71,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "language_settings_mediator_unittest.mm",
-  ]
+  sources = [ "language_settings_mediator_unittest.mm" ]
   deps = [
     ":language_ui",
     "//base/test:test_support",
@@ -152,9 +148,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "language_settings_egtest.mm",
-  ]
+  sources = [ "language_settings_egtest.mm" ]
   deps = [
     ":language_ui_constants",
     "//base/test:test_support",
@@ -174,9 +168,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "language_settings_egtest.mm",
-  ]
+  sources = [ "language_settings_egtest.mm" ]
   deps = [
     ":eg_test_support",
     ":language_ui_constants",
diff --git a/ios/chrome/browser/ui/settings/language/cells/BUILD.gn b/ios/chrome/browser/ui/settings/language/cells/BUILD.gn
index 4df69d83..c22d372 100644
--- a/ios/chrome/browser/ui/settings/language/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/language/cells/BUILD.gn
@@ -8,7 +8,5 @@
     "language_item.h",
     "language_item.mm",
   ]
-  deps = [
-    "//ios/chrome/browser/ui/table_view/cells",
-  ]
+  deps = [ "//ios/chrome/browser/ui/table_view/cells" ]
 }
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn
index d3d77828..bcc0171d 100644
--- a/ios/chrome/browser/ui/settings/password/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -57,9 +57,7 @@
     "passwords_table_view_constants.h",
     "passwords_table_view_constants.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("test_support") {
@@ -70,9 +68,7 @@
     "password_exporter_for_testing.h",
     "reauthentication_module_for_testing.h",
   ]
-  deps = [
-    ":password",
-  ]
+  deps = [ ":password" ]
 }
 
 source_set("unit_tests") {
@@ -145,9 +141,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "passwords_settings_egtest.mm",
-  ]
+  sources = [ "passwords_settings_egtest.mm" ]
   deps = [
     ":eg_test_support",
     ":password_constants",
@@ -213,9 +207,7 @@
   ]
   testonly = true
 
-  sources = [
-    "passwords_settings_app_interface.h",
-  ]
+  sources = [ "passwords_settings_app_interface.h" ]
 }
 
 source_set("eg2_tests") {
@@ -225,9 +217,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "passwords_settings_egtest.mm",
-  ]
+  sources = [ "passwords_settings_egtest.mm" ]
   deps = [
     ":eg_test_support+eg2",
     ":password_constants",
diff --git a/ios/chrome/browser/ui/settings/resources/BUILD.gn b/ios/chrome/browser/ui/settings/resources/BUILD.gn
index 8259221..e1eea040 100644
--- a/ios/chrome/browser/ui/settings/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/resources/BUILD.gn
@@ -5,9 +5,7 @@
 import("//build/config/ios/asset_catalog.gni")
 
 colorset("settings_catalog_example_text") {
-  sources = [
-    "settings_catalog_example_text.colorset/Contents.json",
-  ]
+  sources = [ "settings_catalog_example_text.colorset/Contents.json" ]
 }
 
 imageset("app_icon_placeholder") {
diff --git a/ios/chrome/browser/ui/settings/utils/BUILD.gn b/ios/chrome/browser/ui/settings/utils/BUILD.gn
index e295cac..6aaf2f1 100644
--- a/ios/chrome/browser/ui/settings/utils/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/utils/BUILD.gn
@@ -30,9 +30,7 @@
     "fake_observable_boolean.h",
     "fake_observable_boolean.mm",
   ]
-  deps = [
-    ":utils",
-  ]
+  deps = [ ":utils" ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/webui/BUILD.gn b/ios/chrome/browser/webui/BUILD.gn
index b8ea0123..97496ec7 100644
--- a/ios/chrome/browser/webui/BUILD.gn
+++ b/ios/chrome/browser/webui/BUILD.gn
@@ -20,9 +20,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "net_export_tab_helper_unittest.mm",
-  ]
+  sources = [ "net_export_tab_helper_unittest.mm" ]
   deps = [
     ":webui",
     "//base",
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 973476ff..08df728 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -188,6 +188,7 @@
     "//ios/chrome/browser/infobars:unit_tests",
     "//ios/chrome/browser/infobars/overlays:unit_tests",
     "//ios/chrome/browser/infobars/overlays/browser_agent:unit_tests",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common:unit_tests",
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords:unit_tests",
     "//ios/chrome/browser/itunes_urls:unit_tests",
     "//ios/chrome/browser/json_parser:unit_tests",
diff --git a/ios/third_party/motion_animator_objc/BUILD.gn b/ios/third_party/motion_animator_objc/BUILD.gn
index f48e7eb..791ae104 100644
--- a/ios/third_party/motion_animator_objc/BUILD.gn
+++ b/ios/third_party/motion_animator_objc/BUILD.gn
@@ -65,7 +65,5 @@
     "//build/config/compiler:default_include_dirs",
   ]
 
-  public_deps = [
-    "//ios/third_party/motion_interchange_objc",
-  ]
+  public_deps = [ "//ios/third_party/motion_interchange_objc" ]
 }
diff --git a/media/base/android/media_codec_bridge_impl.cc b/media/base/android/media_codec_bridge_impl.cc
index 48350424..edf707cc 100644
--- a/media/base/android/media_codec_bridge_impl.cc
+++ b/media/base/android/media_codec_bridge_impl.cc
@@ -111,38 +111,7 @@
       break;
     }
     case kCodecAAC: {
-      media::BitReader reader(extra_data, extra_data_size);
-
-      // The following code is copied from aac.cc
-      // TODO(qinmin): refactor the code in aac.cc to make it more reusable.
-      uint8_t profile = 0;
-      uint8_t frequency_index = 0;
-      uint8_t channel_config = 0;
-      RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      RETURN_ON_ERROR(reader.ReadBits(4, &frequency_index));
-
-      if (0xf == frequency_index)
-        RETURN_ON_ERROR(reader.SkipBits(24));
-      RETURN_ON_ERROR(reader.ReadBits(4, &channel_config));
-
-      if (profile == 5 || profile == 29) {
-        // Read extension config.
-        uint8_t ext_frequency_index = 0;
-        RETURN_ON_ERROR(reader.ReadBits(4, &ext_frequency_index));
-        if (ext_frequency_index == 0xf)
-          RETURN_ON_ERROR(reader.SkipBits(24));
-        RETURN_ON_ERROR(reader.ReadBits(5, &profile));
-      }
-
-      if (profile < 1 || profile > 4 || frequency_index == 0xf ||
-          channel_config > 7) {
-        LOG(ERROR) << "Invalid AAC header";
-        return false;
-      }
-
-      output_csd0->push_back(profile << 3 | frequency_index >> 1);
-      output_csd0->push_back((frequency_index & 0x01) << 7 | channel_config
-                                                                 << 3);
+      output_csd0->assign(extra_data, extra_data + extra_data_size);
       *output_frame_has_adts_header = true;
       break;
     }
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn
index e7f90a1..74e46bb 100644
--- a/media/capture/BUILD.gn
+++ b/media/capture/BUILD.gn
@@ -87,9 +87,7 @@
     "video/video_capture_device_factory.h",
   ]
 
-  public_deps = [
-    ":capture_base",
-  ]
+  public_deps = [ ":capture_base" ]
   deps = [
     "//base",
     "//base:i18n",
@@ -364,9 +362,7 @@
     "video_capture_types_unittest.cc",
   ]
 
-  data = [
-    "//media/test/data/bear.mjpeg",
-  ]
+  data = [ "//media/test/data/bear.mjpeg" ]
 
   deps = [
     ":capture",
diff --git a/media/capture/mojom/BUILD.gn b/media/capture/mojom/BUILD.gn
index 87209b9..bfa974c 100644
--- a/media/capture/mojom/BUILD.gn
+++ b/media/capture/mojom/BUILD.gn
@@ -24,9 +24,7 @@
 }
 
 mojom("image_capture") {
-  sources = [
-    "image_capture.mojom",
-  ]
+  sources = [ "image_capture.mojom" ]
 
   # ImageCapture Mojom interfaces are exposed publicly to layout tests which use
   # prepackaged redistributable JS bindings. It is therefore not desirable to
@@ -40,7 +38,5 @@
     "image_capture_types.h",
   ]
 
-  deps = [
-    ":image_capture",
-  ]
+  deps = [ ":image_capture" ]
 }
diff --git a/media/remoting/BUILD.gn b/media/remoting/BUILD.gn
index 07d3724..f0d7b85e 100644
--- a/media/remoting/BUILD.gn
+++ b/media/remoting/BUILD.gn
@@ -8,9 +8,7 @@
 
 proto_library("media_remoting_proto") {
   proto_out_dir = "media/remoting"
-  sources = [
-    "media_remoting_rpc.proto",
-  ]
+  sources = [ "media_remoting_rpc.proto" ]
 }
 
 # This target is separate from "remoting" because this code is shared by the
@@ -30,9 +28,7 @@
     "//media",
   ]
 
-  public_deps = [
-    ":media_remoting_proto",
-  ]
+  public_deps = [ ":media_remoting_proto" ]
 }
 
 source_set("remoting") {
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index 09a10df..e1179bb 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -148,6 +148,9 @@
     // Must precede audio/webm .
     {"video/webm", "webm"},
 
+    // Must precede audio/mp3
+    {"audio/mpeg", "mp3"},
+
     {"application/wasm", "wasm"},
     {"application/x-chrome-extension", "crx"},
     {"application/xhtml+xml", "xhtml,xht,xhtm"},
@@ -196,7 +199,6 @@
     {"application/x-tar", "tar"},
     {"application/x-x509-ca-cert", "cer,crt"},
     {"application/zip", "zip"},
-    {"audio/mpeg", "mp3"},
     // This is the platform mapping on recent versions of Windows 10.
     {"audio/webm", "weba"},
     {"image/bmp", "bmp"},
diff --git a/net/base/net_errors.cc b/net/base/net_errors.cc
index ed6bc4514..7e7ee37ac 100644
--- a/net/base/net_errors.cc
+++ b/net/base/net_errors.cc
@@ -63,8 +63,8 @@
 }
 
 bool IsDnsError(int error) {
-  return (error == ERR_NAME_NOT_RESOLVED ||
-          error == ERR_NAME_RESOLUTION_FAILED);
+  DCHECK_NE(ERR_NAME_RESOLUTION_FAILED, error);
+  return error == ERR_NAME_NOT_RESOLVED;
 }
 
 Error FileErrorToNetError(base::File::Error file_error) {
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc
index 76b9bc6..8aee929 100644
--- a/net/dns/host_resolver.cc
+++ b/net/dns/host_resolver.cc
@@ -242,7 +242,10 @@
 
 // static
 int HostResolver::SquashErrorCode(int error) {
-  if (error == OK || error == ERR_IO_PENDING ||
+  // TODO(crbug.com/1040686): Once InProcessBrowserTests do not use
+  // ERR_NOT_IMPLEMENTED to simulate DNS failures, it should be ok to squash
+  // ERR_NOT_IMPLEMENTED.
+  if (error == OK || error == ERR_IO_PENDING || error == ERR_NOT_IMPLEMENTED ||
       error == ERR_NAME_NOT_RESOLVED) {
     return error;
   } else {
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h
index 092ac6f..264ab583 100644
--- a/net/dns/host_resolver.h
+++ b/net/dns/host_resolver.h
@@ -66,12 +66,9 @@
     // On any other returned value, the request was handled synchronously and
     // |callback| will not be invoked.
     //
-    // Results in ERR_NAME_NOT_RESOLVED if the hostname is invalid, or if it is
-    // an incompatible IP literal (e.g. IPv6 is disabled and it is an IPv6
-    // literal).
-    //
-    // Results in ERR_DNS_CACHE_MISS if only fast local sources are to be
-    // queried and a cache lookup attempt fails.
+    // Results in ERR_NAME_NOT_RESOLVED if the hostname is not resolved. More
+    // detail about the underlying error can be retrieved using
+    // GetResolveErrorInfo().
     //
     // The parent HostResolver must still be alive when Start() is called,  but
     // if it is destroyed before an asynchronous result completes, the request
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc
index 884d3ff..632f5b4 100644
--- a/net/dns/host_resolver_manager.cc
+++ b/net/dns/host_resolver_manager.cc
@@ -650,7 +650,7 @@
     LogFinishRequest(error);
 
     DCHECK(callback_);
-    std::move(callback_).Run(error);
+    std::move(callback_).Run(HostResolver::SquashErrorCode(error));
   }
 
   Job* job() const { return job_; }
@@ -3015,7 +3015,7 @@
                     effective_secure_dns_mode, base::TimeDelta());
     request->set_error_info(results.error(),
                             false /* is_secure_network_error */);
-    return results.error();
+    return HostResolver::SquashErrorCode(results.error());
   }
 
   CreateAndStartJob(effective_query_type, effective_host_resolver_flags,
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc
index 12fe95c0..d4f1d9e 100644
--- a/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -313,7 +313,7 @@
   EXPECT_EQ(test_https_requests_served_, 0u);
 
   EXPECT_TRUE(d.response_completed());
-  EXPECT_EQ(d.request_status(), net::ERR_DNS_MALFORMED_RESPONSE);
+  EXPECT_EQ(d.request_status(), net::ERR_NAME_NOT_RESOLVED);
 
   const auto& resolve_error_info = req->response_info().resolve_error_info;
   EXPECT_TRUE(resolve_error_info.is_secure_network_error);
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn
index 588872c6..32df473 100644
--- a/pdf/BUILD.gn
+++ b/pdf/BUILD.gn
@@ -38,9 +38,7 @@
       "//ui/gfx/range",
     ]
 
-    public_deps = [
-      "//gin",
-    ]
+    public_deps = [ "//gin" ]
 
     public = [
       "pdf.h",
@@ -131,13 +129,9 @@
 
   source_set("features") {
     configs += [ ":pdf_common_config" ]
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
 
-    public = [
-      "pdf_features.h",
-    ]
+    public = [ "pdf_features.h" ]
 
     sources = [
       "pdf_features.cc",
@@ -191,9 +185,7 @@
       "//ui/gfx/range",
     ]
 
-    data = [
-      "test/data/",
-    ]
+    data = [ "test/data/" ]
 
     if (pdf_engine == 0) {
       configs += [ "//v8:external_startup_data" ]
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index e605e18..0a866875 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -74,83 +74,61 @@
 
 fuzzer_test("pdfium_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdfium_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdfium_fuzzer_src" ]
   dict = "dicts/pdf.dict"
   seed_corpus = "//third_party/pdfium/testing/resources"
 }
 
 fuzzer_test("pdf_cmap_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_cmap_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_cmap_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_codec_a85_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_codec_a85_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_codec_a85_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_codec_fax_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_codec_fax_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_codec_fax_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_codec_rle_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_codec_rle_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_codec_rle_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_codec_icc_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_codec_icc_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_codec_icc_fuzzer_src" ]
   dict = "dicts/pdf_codec_icc.dict"
 }
 
 fuzzer_test("pdf_codec_jbig2_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_codec_jbig2_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_codec_jbig2_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_font_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_font_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_font_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_hint_table_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_hint_table_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_hint_table_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_jpx_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_jpx_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_jpx_fuzzer_src" ]
   seed_corpus = "corpora/pdf_jpx"
 }
 
 fuzzer_test("pdf_psengine_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_psengine_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_psengine_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_scanlinecompositor_fuzzer") {
@@ -162,16 +140,12 @@
 
 fuzzer_test("pdf_streamparser_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_streamparser_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_streamparser_fuzzer_src" ]
 }
 
 fuzzer_test("pdf_xml_fuzzer") {
   sources = []
-  deps = [
-    "//third_party/pdfium/testing/fuzzers:pdf_xml_fuzzer_src",
-  ]
+  deps = [ "//third_party/pdfium/testing/fuzzers:pdf_xml_fuzzer_src" ]
   dict = "dicts/pdf_xml.dict"
   seed_corpus = "//third_party/libxml/fuzz/seed_corpus"
 }
@@ -179,9 +153,7 @@
 if (pdf_enable_v8) {
   fuzzer_test("pdf_cjs_util_fuzzer") {
     sources = []
-    deps = [
-      "//third_party/pdfium/testing/fuzzers:pdf_cjs_util_fuzzer_src",
-    ]
+    deps = [ "//third_party/pdfium/testing/fuzzers:pdf_cjs_util_fuzzer_src" ]
   }
 
   fuzzer_test("pdf_fx_date_helpers_fuzzer") {
@@ -195,9 +167,8 @@
     if (pdf_enable_xfa_bmp) {
       fuzzer_test("pdf_codec_bmp_fuzzer") {
         sources = []
-        deps = [
-          "//third_party/pdfium/testing/fuzzers:pdf_codec_bmp_fuzzer_src",
-        ]
+        deps =
+            [ "//third_party/pdfium/testing/fuzzers:pdf_codec_bmp_fuzzer_src" ]
         seed_corpus = "corpora/pdf_codec_bmp"
       }
     }
@@ -205,9 +176,8 @@
     if (pdf_enable_xfa_gif) {
       fuzzer_test("pdf_codec_gif_fuzzer") {
         sources = []
-        deps = [
-          "//third_party/pdfium/testing/fuzzers:pdf_codec_gif_fuzzer_src",
-        ]
+        deps =
+            [ "//third_party/pdfium/testing/fuzzers:pdf_codec_gif_fuzzer_src" ]
         dict = "dicts/pdf_codec_gif.dict"
         seed_corpus = "corpora/pdf_codec_gif"
       }
@@ -215,9 +185,8 @@
 
     fuzzer_test("pdf_codec_jpeg_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_codec_jpeg_fuzzer_src",
-      ]
+      deps =
+          [ "//third_party/pdfium/testing/fuzzers:pdf_codec_jpeg_fuzzer_src" ]
       dict = "dicts/pdf_codec_jpeg.dict"
       seed_corpus = "corpora/pdf_codec_jpeg"
     }
@@ -225,9 +194,8 @@
     if (pdf_enable_xfa_png) {
       fuzzer_test("pdf_codec_png_fuzzer") {
         sources = []
-        deps = [
-          "//third_party/pdfium/testing/fuzzers:pdf_codec_png_fuzzer_src",
-        ]
+        deps =
+            [ "//third_party/pdfium/testing/fuzzers:pdf_codec_png_fuzzer_src" ]
         dict = "dicts/pdf_codec_png.dict"
         seed_corpuses = [
           "corpora/pdf_codec_png",
@@ -241,9 +209,8 @@
     if (pdf_enable_xfa_tiff) {
       fuzzer_test("pdf_codec_tiff_fuzzer") {
         sources = []
-        deps = [
-          "//third_party/pdfium/testing/fuzzers:pdf_codec_tiff_fuzzer_src",
-        ]
+        deps =
+            [ "//third_party/pdfium/testing/fuzzers:pdf_codec_tiff_fuzzer_src" ]
         dict = "dicts/pdf_codec_tiff.dict"
         seed_corpus = "corpora/pdf_codec_tiff"
       }
@@ -251,17 +218,13 @@
 
     fuzzer_test("pdf_css_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_css_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdf_css_fuzzer_src" ]
       dict = "dicts/pdf_css.dict"
     }
 
     fuzzer_test("pdf_fm2js_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_fm2js_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdf_fm2js_fuzzer_src" ]
       dict = "dicts/pdf_formcalc.dict"
     }
 
@@ -275,47 +238,36 @@
 
     fuzzer_test("pdf_formcalc_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_formcalc_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdf_formcalc_fuzzer_src" ]
       dict = "dicts/pdf_formcalc.dict"
     }
 
     if (pdf_enable_xfa_gif) {
       fuzzer_test("pdf_lzw_fuzzer") {
         sources = []
-        deps = [
-          "//third_party/pdfium/testing/fuzzers:pdf_lzw_fuzzer_src",
-        ]
+        deps = [ "//third_party/pdfium/testing/fuzzers:pdf_lzw_fuzzer_src" ]
       }
     }
 
     fuzzer_test("pdf_bidi_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_bidi_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdf_bidi_fuzzer_src" ]
     }
 
     fuzzer_test("pdf_cfx_barcode_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_cfx_barcode_fuzzer_src",
-      ]
+      deps =
+          [ "//third_party/pdfium/testing/fuzzers:pdf_cfx_barcode_fuzzer_src" ]
     }
 
     fuzzer_test("pdf_cfgas_stringformatter_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdf_cfgas_stringformatter_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdf_cfgas_stringformatter_fuzzer_src" ]
     }
 
     fuzzer_test("pdfium_xfa_fuzzer") {
       sources = []
-      deps = [
-        "//third_party/pdfium/testing/fuzzers:pdfium_xfa_fuzzer_src",
-      ]
+      deps = [ "//third_party/pdfium/testing/fuzzers:pdfium_xfa_fuzzer_src" ]
       dict = "dicts/pdf.dict"
       seed_corpus = "corpora/xfa"
     }
@@ -334,9 +286,7 @@
     }
 
     fuzzer_test("pdfium_xfa_lpm_fuzzer") {
-      sources = [
-        "pdfium_xfa_lpm_fuzzer/fuzzer.cc",
-      ]
+      sources = [ "pdfium_xfa_lpm_fuzzer/fuzzer.cc" ]
       deps = [
         ":proto_to_xfa",
         "//base",
@@ -356,9 +306,7 @@
     }
 
     test("pdfium_xfa_lpm_unittest") {
-      sources = [
-        "pdfium_xfa_lpm_fuzzer/simple_xfa_pdf_unittest.cc",
-      ]
+      sources = [ "pdfium_xfa_lpm_fuzzer/simple_xfa_pdf_unittest.cc" ]
 
       deps = [
         ":proto_to_xfa",
@@ -372,14 +320,10 @@
 if (is_clang) {
   fuzzer_test("pdf_nametree_fuzzer") {
     sources = []
-    deps = [
-      "//third_party/pdfium/testing/fuzzers:pdf_nametree_fuzzer_src",
-    ]
+    deps = [ "//third_party/pdfium/testing/fuzzers:pdf_nametree_fuzzer_src" ]
   }
 }
 
 proto_library("xfa_proto") {
-  sources = [
-    "pdfium_xfa_lpm_fuzzer/xfa.proto",
-  ]
+  sources = [ "pdfium_xfa_lpm_fuzzer/xfa.proto" ]
 }
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn
index 65e61ff..ceb99d97 100644
--- a/remoting/BUILD.gn
+++ b/remoting/BUILD.gn
@@ -7,9 +7,7 @@
 group("remoting_all") {
   testonly = true
 
-  deps = [
-    ":remoting_unittests",
-  ]
+  deps = [ ":remoting_unittests" ]
 
   if (is_win) {
     deps += [
@@ -86,9 +84,7 @@
 
     configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-    sources = [
-      "tools/breakpad_tester_win.cc",
-    ]
+    sources = [ "tools/breakpad_tester_win.cc" ]
 
     if (is_win) {
       libs += [
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn
index a2a2cea9..a2b12b6 100644
--- a/remoting/base/BUILD.gn
+++ b/remoting/base/BUILD.gn
@@ -114,9 +114,7 @@
     "//net",
   ]
 
-  deps = [
-    "//remoting/proto/remoting/v1:directory_grpc_library",
-  ]
+  deps = [ "//remoting/proto/remoting/v1:directory_grpc_library" ]
 }
 
 source_set("breakpad") {
@@ -129,9 +127,7 @@
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   if (is_mac) {
     deps += [ "//third_party/breakpad" ]
@@ -151,9 +147,7 @@
     "test_rsa_key_pair.h",
   ]
 
-  deps = [
-    "//remoting/proto",
-  ]
+  deps = [ "//remoting/proto" ]
   public_deps = [
     ":authorization",
     ":base",
diff --git a/remoting/base/grpc_support/BUILD.gn b/remoting/base/grpc_support/BUILD.gn
index 99e57db..c41e21b 100644
--- a/remoting/base/grpc_support/BUILD.gn
+++ b/remoting/base/grpc_support/BUILD.gn
@@ -33,9 +33,7 @@
 }
 
 cc_grpc_library("unit_tests_grpc_library") {
-  sources = [
-    "grpc_support_test_services.proto",
-  ]
+  sources = [ "grpc_support_test_services.proto" ]
 }
 
 source_set("unit_tests") {
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn
index 835723d..ab381ff 100644
--- a/remoting/client/BUILD.gn
+++ b/remoting/client/BUILD.gn
@@ -41,9 +41,7 @@
     "//remoting/build/config:enable_webrtc_remoting_client",
   ]
 
-  public_deps = [
-    "//remoting/base",
-  ]
+  public_deps = [ "//remoting/base" ]
 
   deps = [
     "//mojo/core/embedder",
diff --git a/remoting/client/audio/BUILD.gn b/remoting/client/audio/BUILD.gn
index 684a1b6..4fbc75ba 100644
--- a/remoting/client/audio/BUILD.gn
+++ b/remoting/client/audio/BUILD.gn
@@ -44,9 +44,7 @@
     "fake_async_audio_data_supplier.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/remoting/client/display/BUILD.gn b/remoting/client/display/BUILD.gn
index 1aebe48..925f3da3 100644
--- a/remoting/client/display/BUILD.gn
+++ b/remoting/client/display/BUILD.gn
@@ -30,9 +30,7 @@
     "sys_opengl.h",
   ]
 
-  public_deps = [
-    "//remoting/proto",
-  ]
+  public_deps = [ "//remoting/proto" ]
   deps = [
     "//third_party/libyuv",
     "//third_party/protobuf:protobuf_lite",
diff --git a/remoting/client/ui/BUILD.gn b/remoting/client/ui/BUILD.gn
index 9cbda24..cffd7ca 100644
--- a/remoting/client/ui/BUILD.gn
+++ b/remoting/client/ui/BUILD.gn
@@ -10,9 +10,7 @@
     "fling_tracker.h",
   ]
 
-  deps = [
-    ":ui_manipulation",
-  ]
+  deps = [ ":ui_manipulation" ]
 
   public_deps = [
     "//remoting/proto",
diff --git a/remoting/codec/BUILD.gn b/remoting/codec/BUILD.gn
index 486ed1f..f6ff1ab 100644
--- a/remoting/codec/BUILD.gn
+++ b/remoting/codec/BUILD.gn
@@ -105,9 +105,7 @@
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  public_deps = [
-    "//third_party/libvpx",
-  ]
+  public_deps = [ "//third_party/libvpx" ]
 
   deps = [
     "//base/third_party/dynamic_annotations",
diff --git a/remoting/credits/credits.gni b/remoting/credits/credits.gni
index c75b299..aa4e87c0 100644
--- a/remoting/credits/credits.gni
+++ b/remoting/credits/credits.gni
@@ -23,9 +23,7 @@
       _credits_template,
       _credits_entry_template,
     ]
-    outputs = [
-      _credits_html_file,
-    ]
+    outputs = [ _credits_html_file ]
     args = [
       "credits",
       rebase_path(_credits_html_file, root_build_dir),
@@ -53,11 +51,7 @@
                 "$_credits_source_dir/credits_css.css",
                 "$_credits_source_dir/credits_js.js",
               ] + get_target_outputs(_generate_target)
-    outputs = [
-      "$_credits_gen_dir/{{source_file_part}}",
-    ]
-    deps = [
-      _generate_target,
-    ]
+    outputs = [ "$_credits_gen_dir/{{source_file_part}}" ]
+    deps = [ _generate_target ]
   }
 }
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn
index 03c76167..9fd14a6b 100644
--- a/remoting/host/BUILD.gn
+++ b/remoting/host/BUILD.gn
@@ -8,17 +8,13 @@
 group("all_tests") {
   testonly = true
 
-  deps = [
-    ":unit_tests",
-  ]
+  deps = [ ":unit_tests" ]
 }
 
 group("all") {
   testonly = true
 
-  deps = [
-    ":host",
-  ]
+  deps = [ ":host" ]
   if (enable_me2me_host) {
     deps += [ "//remoting/host:remoting_me2me_host" ]
   }
@@ -39,19 +35,13 @@
 
 process_version("remoting_version") {
   template_file = "//remoting/host/version.h.in"
-  sources = [
-    branding_path,
-  ]
+  sources = [ branding_path ]
   output = "$target_gen_dir/version.h"
 }
 
 source_set("host") {
-  public_deps = [
-    ":common",
-  ]
-  deps = [
-    "//remoting/host/file_transfer",
-  ]
+  public_deps = [ ":common" ]
+  deps = [ "//remoting/host/file_transfer" ]
 }
 
 source_set("base") {
@@ -577,9 +567,7 @@
 
   if (enable_me2me_host) {
     sources += [ "evaluate_capability_unittest.cc" ]
-    data_deps = [
-      "//remoting/test:capability_test_stub",
-    ]
+    data_deps = [ "//remoting/test:capability_test_stub" ]
   }
 }
 
@@ -605,9 +593,7 @@
 
 if (enable_remoting_host) {
   executable("remoting_start_host") {
-    sources = [
-      "setup/start_host_entry_point.cc",
-    ]
+    sources = [ "setup/start_host_entry_point.cc" ]
 
     deps = [
       "//third_party/libjingle_xmpp",
@@ -665,13 +651,9 @@
       "setup/com.google.chrome.remote_desktop.json.jinja2",
     ]
 
-    inputs = [
-      branding_path,
-    ]
+    inputs = [ branding_path ]
 
-    outputs = [
-      "$root_build_dir/remoting/{{source_name_part}}",
-    ]
+    outputs = [ "$root_build_dir/remoting/{{source_name_part}}" ]
 
     args = [
       "--define",
@@ -724,9 +706,7 @@
 
 if (enable_me2me_host) {
   static_library("remoting_me2me_host_static") {
-    sources = [
-      "remoting_me2me_host.cc",
-    ]
+    sources = [ "remoting_me2me_host.cc" ]
     defines = []
 
     configs += [
@@ -773,14 +753,10 @@
 
   if (is_win) {
     group("remoting_me2me_host") {
-      deps = [
-        "//remoting/host/win:remoting_me2me_host",
-      ]
+      deps = [ "//remoting/host/win:remoting_me2me_host" ]
     }
     group("remoting_native_messaging_host") {
-      deps = [
-        "//remoting/host/win:remoting_native_messaging_host",
-      ]
+      deps = [ "//remoting/host/win:remoting_native_messaging_host" ]
     }
   } else {
     source_set("main") {
@@ -795,9 +771,7 @@
     }
     if (is_mac) {
       group("remoting_me2me_host") {
-        deps = [
-          "//remoting/host/mac:remoting_me2me_host",
-        ]
+        deps = [ "//remoting/host/mac:remoting_me2me_host" ]
       }
     } else {
       target("executable", "remoting_me2me_host") {
@@ -820,35 +794,25 @@
 
     if (is_mac) {
       group("remoting_native_messaging_host") {
-        deps = [
-          "//remoting/host/mac:remoting_native_messaging_host",
-        ]
+        deps = [ "//remoting/host/mac:remoting_native_messaging_host" ]
       }
     } else {
       group("remoting_native_messaging_host") {
-        deps = [
-          "//remoting/host/linux:remoting_native_messaging_host",
-        ]
+        deps = [ "//remoting/host/linux:remoting_native_messaging_host" ]
       }
     }
   }
   if (is_chrome_branded && enable_me2me_host && is_linux && !is_chromeos) {
     group("remoting_me2me_host_archive") {
-      deps = [
-        "//remoting/host/installer/linux:remoting_me2me_host_archive",
-      ]
+      deps = [ "//remoting/host/installer/linux:remoting_me2me_host_archive" ]
     }
   } else if (is_win) {
     group("remoting_me2me_host_archive") {
-      deps = [
-        "//remoting/host/installer/win:remoting_me2me_host_archive",
-      ]
+      deps = [ "//remoting/host/installer/win:remoting_me2me_host_archive" ]
     }
   } else if (is_mac) {
     group("remoting_me2me_host_archive") {
-      deps = [
-        "//remoting/host/installer/mac:remoting_me2me_host_archive",
-      ]
+      deps = [ "//remoting/host/installer/mac:remoting_me2me_host_archive" ]
     }
   } else {
     group("remoting_me2me_host_archive") {
diff --git a/remoting/host/file_transfer/BUILD.gn b/remoting/host/file_transfer/BUILD.gn
index 06c1395c..22e913b 100644
--- a/remoting/host/file_transfer/BUILD.gn
+++ b/remoting/host/file_transfer/BUILD.gn
@@ -18,9 +18,7 @@
     "get_desktop_directory_win.cc",
   ]
 
-  public_deps = [
-    ":common",
-  ]
+  public_deps = [ ":common" ]
 
   deps = [
     "//base",
diff --git a/remoting/host/input_monitor/BUILD.gn b/remoting/host/input_monitor/BUILD.gn
index 32d07e0..3fde2d1 100644
--- a/remoting/host/input_monitor/BUILD.gn
+++ b/remoting/host/input_monitor/BUILD.gn
@@ -5,9 +5,7 @@
 import("//remoting/build/config/remoting_build.gni")
 
 source_set("input_monitor") {
-  public = [
-    "local_input_monitor.h",
-  ]
+  public = [ "local_input_monitor.h" ]
 
   sources = [
     "local_hotkey_input_monitor.h",
diff --git a/remoting/host/installer/BUILD.gn b/remoting/host/installer/BUILD.gn
index fc19aa7..d50709e 100644
--- a/remoting/host/installer/BUILD.gn
+++ b/remoting/host/installer/BUILD.gn
@@ -18,9 +18,7 @@
     "credits_entry.tmpl",
   ]
 
-  outputs = [
-    about_credits_file,
-  ]
+  outputs = [ about_credits_file ]
 
   args = [
     "credits",
diff --git a/remoting/host/installer/linux/BUILD.gn b/remoting/host/installer/linux/BUILD.gn
index e27c7ddc9..4db0701 100644
--- a/remoting/host/installer/linux/BUILD.gn
+++ b/remoting/host/installer/linux/BUILD.gn
@@ -31,23 +31,15 @@
   # package handling in other build/signing scripts.
   inputs = packaging_outputs
   output = "$root_build_dir/remoting-me2me-host-linux.zip"
-  deps = [
-    ":remoting_me2me_host_copy",
-  ]
+  deps = [ ":remoting_me2me_host_copy" ]
 }
 
 copy("remoting_me2me_host_copy") {
   # Copy the debian package file, which has version info in it,
   # to a consistewnt filename for use on Chromoting swarming bots.
-  sources = [
-    deb_filename,
-  ]
-  outputs = [
-    "$root_build_dir/remoting-me2me-host.deb",
-  ]
-  public_deps = [
-    ":remoting_me2me_host_deb_installer",
-  ]
+  sources = [ deb_filename ]
+  outputs = [ "$root_build_dir/remoting-me2me-host.deb" ]
+  public_deps = [ ":remoting_me2me_host_deb_installer" ]
 }
 
 action("remoting_me2me_host_deb_installer") {
@@ -65,9 +57,7 @@
     "debian/rules",
   ]
   outputs = packaging_outputs
-  sources = [
-    "build-deb.sh",
-  ]
+  sources = [ "build-deb.sh" ]
   args = [
     "-s",
     rebase_path("//", root_build_dir),
diff --git a/remoting/host/installer/mac/BUILD.gn b/remoting/host/installer/mac/BUILD.gn
index 22d32f3c..d0eced6 100644
--- a/remoting/host/installer/mac/BUILD.gn
+++ b/remoting/host/installer/mac/BUILD.gn
@@ -31,9 +31,7 @@
 
   zip_path = "$root_build_dir/remoting-me2me-host-mac.zip"
 
-  outputs = [
-    "$root_build_dir/remoting-me2me-host-mac.zip",
-  ]
+  outputs = [ "$root_build_dir/remoting-me2me-host-mac.zip" ]
 
   script = "//remoting/host/installer/build-installer-archive.py"
 
@@ -104,15 +102,9 @@
 # remoting_uninstaller-InfoPlist.strings
 foreach(locale, remoting_locales_with_underscores) {
   bundle_data("remoting_uninstaller_strings_${locale}_bundle_data") {
-    sources = [
-      "$root_gen_dir/remoting/host/remoting_uninstaller-InfoPlist.strings/$locale.lproj/InfoPlist.strings",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
-    deps = [
-      "//remoting/host:remoting_infoplist_strings",
-    ]
+    sources = [ "$root_gen_dir/remoting/host/remoting_uninstaller-InfoPlist.strings/$locale.lproj/InfoPlist.strings" ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+    deps = [ "//remoting/host:remoting_infoplist_strings" ]
   }
 }
 
@@ -151,11 +143,7 @@
 }
 
 bundle_data("remoting_host_uninstaller_resources") {
-  sources = [
-    "uninstaller/remoting_uninstaller.icns",
-  ]
+  sources = [ "uninstaller/remoting_uninstaller.icns" ]
 
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 }
diff --git a/remoting/host/installer/win/BUILD.gn b/remoting/host/installer/win/BUILD.gn
index 62d2293..b4eaec9 100644
--- a/remoting/host/installer/win/BUILD.gn
+++ b/remoting/host/installer/win/BUILD.gn
@@ -8,9 +8,7 @@
 action("remoting_me2me_host_archive") {
   script = "//remoting/host/installer/build-installer-archive.py"
 
-  sources = [
-    "//build/android/gyp/util/build_utils.py",
-  ]
+  sources = [ "//build/android/gyp/util/build_utils.py" ]
 
   deps = [
     "//remoting/host:remoting_native_messaging_manifests",
@@ -25,9 +23,7 @@
     "//third_party/icu:icudata",
   ]
 
-  public_deps = [
-    "//remoting/host/security_key:remote_security_key",
-  ]
+  public_deps = [ "//remoting/host/security_key:remote_security_key" ]
 
   if (target_cpu == "x86") {
     _output = "$root_out_dir/remoting-me2me-host-$target_os.zip"
@@ -35,9 +31,7 @@
     _output = "$root_out_dir/remoting-me2me-host-$target_os-unsupported.zip"
   }
 
-  outputs = [
-    _output,
-  ]
+  outputs = [ _output ]
   if (is_chrome_branded) {
     _branding = "Chrome"
   } else {
@@ -137,13 +131,9 @@
   msi_script_arch = "ia32"
 
   action("remoting_host_installation") {
-    deps = [
-      "//remoting/host:remoting_me2me_host_archive",
-    ]
+    deps = [ "//remoting/host:remoting_me2me_host_archive" ]
     script = "//remoting/tools/zip2msi.py"
-    outputs = [
-      "$root_out_dir/chromoting.msi",
-    ]
+    outputs = [ "$root_out_dir/chromoting.msi" ]
     args = [
       "--wix_path",
       rebase_path("//third_party/wix", root_build_dir),
@@ -159,8 +149,6 @@
 } else {
   group("remoting_host_installation") {
     # We still want to build host archive under other configurations.
-    deps = [
-      "//remoting/host:remoting_me2me_host_archive",
-    ]
+    deps = [ "//remoting/host:remoting_me2me_host_archive" ]
   }
 }
diff --git a/remoting/host/it2me/BUILD.gn b/remoting/host/it2me/BUILD.gn
index 9db2751..a63a8a3 100644
--- a/remoting/host/it2me/BUILD.gn
+++ b/remoting/host/it2me/BUILD.gn
@@ -151,39 +151,26 @@
           "//remoting/resources/chromoting128.png",
         ]
 
-        outputs = [
-          "{{bundle_resources_dir}}/{{source_file_part}}",
-        ]
+        outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
       }
 
       # remote_assistance_host-InfoPlist.strings
       foreach(locale, remoting_locales_with_underscores) {
         bundle_data("remote_assistance_host_strings_${locale}_bundle_data") {
-          sources = [
-            "$root_gen_dir/remoting/host/remote_assistance_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings",
-          ]
-          outputs = [
-            "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-          ]
-          deps = [
-            "//remoting/host:remoting_infoplist_strings",
-          ]
+          sources = [ "$root_gen_dir/remoting/host/remote_assistance_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings" ]
+          outputs =
+              [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+          deps = [ "//remoting/host:remoting_infoplist_strings" ]
         }
       }
 
       if (icu_use_data_file) {
         bundle_data("remote_assistance_host_resources") {
-          sources = [
-            "$root_out_dir/icudtl.dat",
-          ]
+          sources = [ "$root_out_dir/icudtl.dat" ]
 
-          outputs = [
-            "{{bundle_resources_dir}}/{{source_file_part}}",
-          ]
+          outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 
-          public_deps = [
-            "//third_party/icu:icudata",
-          ]
+          public_deps = [ "//third_party/icu:icudata" ]
         }
       }
     } else {
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn
index 88803413..31b97a47 100644
--- a/remoting/host/linux/BUILD.gn
+++ b/remoting/host/linux/BUILD.gn
@@ -11,54 +11,32 @@
 
 if (enable_me2me_host) {
   executable("remoting_user_session") {
-    sources = [
-      "remoting_user_session.cc",
-    ]
+    sources = [ "remoting_user_session.cc" ]
 
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
 
     libs = [ "pam" ]
   }
 
   copy("remoting_me2me_host_copy_script") {
-    sources = [
-      "linux_me2me_host.py",
-    ]
-    outputs = [
-      "$root_build_dir/remoting/chrome-remote-desktop",
-    ]
+    sources = [ "linux_me2me_host.py" ]
+    outputs = [ "$root_build_dir/remoting/chrome-remote-desktop" ]
   }
 
   copy("remoting_me2me_host_copy_host_wrapper") {
-    sources = [
-      "remoting_me2me_host_wrapper.sh",
-    ]
-    outputs = [
-      "$root_build_dir/remoting/chrome-remote-desktop-host",
-    ]
+    sources = [ "remoting_me2me_host_wrapper.sh" ]
+    outputs = [ "$root_build_dir/remoting/chrome-remote-desktop-host" ]
   }
 
   copy("remoting_me2me_host_copy_user_session_wrapper") {
-    sources = [
-      "remoting_user_session_wrapper.sh",
-    ]
-    outputs = [
-      "$root_build_dir/remoting/user-session",
-    ]
+    sources = [ "remoting_user_session_wrapper.sh" ]
+    outputs = [ "$root_build_dir/remoting/user-session" ]
   }
 
   copy("remoting_me2me_host_copy_user_session") {
-    sources = [
-      "$root_build_dir/remoting_user_session",
-    ]
-    outputs = [
-      "$root_build_dir/remoting/{{source_file_part}}",
-    ]
-    deps = [
-      ":remoting_user_session",
-    ]
+    sources = [ "$root_build_dir/remoting_user_session" ]
+    outputs = [ "$root_build_dir/remoting/{{source_file_part}}" ]
+    deps = [ ":remoting_user_session" ]
     if (is_component_build) {
       sources += [
         "$root_build_dir/libbase.so",
@@ -120,9 +98,7 @@
       "x_server_clipboard.cc",
       "x_server_clipboard.h",
     ]
-    deps = [
-      "//third_party/webrtc_overrides:webrtc_component",
-    ]
+    deps = [ "//third_party/webrtc_overrides:webrtc_component" ]
   }
 }
 
diff --git a/remoting/host/mac/BUILD.gn b/remoting/host/mac/BUILD.gn
index 971ec123..a8e6129 100644
--- a/remoting/host/mac/BUILD.gn
+++ b/remoting/host/mac/BUILD.gn
@@ -6,17 +6,11 @@
 
 if (icu_use_data_file) {
   bundle_data("icu_data") {
-    sources = [
-      "$root_out_dir/icudtl.dat",
-    ]
+    sources = [ "$root_out_dir/icudtl.dat" ]
 
-    outputs = [
-      "{{bundle_resources_dir}}/{{source_file_part}}",
-    ]
+    outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 
-    public_deps = [
-      "//third_party/icu:icudata",
-    ]
+    public_deps = [ "//third_party/icu:icudata" ]
   }
 }
 
@@ -31,9 +25,7 @@
     "constants_mac.h",
   ]
 
-  deps = [
-    "//remoting/host:remoting_version",
-  ]
+  deps = [ "//remoting/host:remoting_version" ]
 }
 
 source_set("permission_checking") {
@@ -55,9 +47,7 @@
 }
 
 executable("remoting_me2me_host_service") {
-  sources = [
-    "host_service_main.cc",
-  ]
+  sources = [ "host_service_main.cc" ]
   configs += [ "//remoting/build/config:version" ]
   deps = [
     ":constants",
@@ -68,29 +58,17 @@
 }
 
 bundle_data("remoting_me2me_host_service_bundle_data") {
-  sources = [
-    "$root_out_dir/remoting_me2me_host_service",
-  ]
-  outputs = [
-    "{{bundle_executable_dir}}/{{source_file_part}}",
-  ]
-  public_deps = [
-    ":remoting_me2me_host_service",
-  ]
+  sources = [ "$root_out_dir/remoting_me2me_host_service" ]
+  outputs = [ "{{bundle_executable_dir}}/{{source_file_part}}" ]
+  public_deps = [ ":remoting_me2me_host_service" ]
 }
 
 # remoting_me2me_host-InfoPlist.strings
 foreach(locale, remoting_locales_with_underscores) {
   bundle_data("remoting_me2me_host_strings_${locale}_bundle_data") {
-    sources = [
-      "$root_gen_dir/remoting/host/remoting_me2me_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
-    deps = [
-      "//remoting/host:remoting_infoplist_strings",
-    ]
+    sources = [ "$root_gen_dir/remoting/host/remoting_me2me_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings" ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+    deps = [ "//remoting/host:remoting_infoplist_strings" ]
   }
 }
 
@@ -100,13 +78,9 @@
     "remoting_host.icns",
   ]
 
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 
-  public_deps = [
-    "//remoting/host/installer:credits",
-  ]
+  public_deps = [ "//remoting/host/installer:credits" ]
 }
 
 target("mac_app_bundle", "remoting_me2me_host") {
@@ -153,30 +127,18 @@
 
 foreach(locale, remoting_locales_with_underscores) {
   bundle_data("remoting_host_locale_${locale}_bundle_data") {
-    sources = [
-      "$root_build_dir/remoting/resources/$locale.lproj/locale.pak",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
-    deps = [
-      "//remoting/resources:copy_locales",
-    ]
+    sources = [ "$root_build_dir/remoting/resources/$locale.lproj/locale.pak" ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+    deps = [ "//remoting/resources:copy_locales" ]
   }
 }
 
 # native_messaging_host-InfoPlist.strings
 foreach(locale, remoting_locales_with_underscores) {
   bundle_data("native_messaging_host_strings_${locale}_bundle_data") {
-    sources = [
-      "$root_gen_dir/remoting/host/native_messaging_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
-    deps = [
-      "//remoting/host:remoting_infoplist_strings",
-    ]
+    sources = [ "$root_gen_dir/remoting/host/native_messaging_host-InfoPlist.strings/$locale.lproj/InfoPlist.strings" ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+    deps = [ "//remoting/host:remoting_infoplist_strings" ]
   }
 }
 
@@ -192,14 +154,10 @@
     # uses. Also, Authorization Services can't deal with .icns files.
     "//remoting/resources/product_logo_32.png",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
 
   if (icu_use_data_file) {
-    deps = [
-      ":icu_data",
-    ]
+    deps = [ ":icu_data" ]
   }
 }
 
diff --git a/remoting/host/native_messaging/BUILD.gn b/remoting/host/native_messaging/BUILD.gn
index 965eb958..865f995 100644
--- a/remoting/host/native_messaging/BUILD.gn
+++ b/remoting/host/native_messaging/BUILD.gn
@@ -18,7 +18,5 @@
 
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/remoting/host/security_key/BUILD.gn b/remoting/host/security_key/BUILD.gn
index 1a56b42..3575159 100644
--- a/remoting/host/security_key/BUILD.gn
+++ b/remoting/host/security_key/BUILD.gn
@@ -97,9 +97,7 @@
     "security_key_message_writer_impl_unittest.cc",
   ]
 
-  public_deps = [
-    ":test_support",
-  ]
+  public_deps = [ ":test_support" ]
   deps = [
     "//mojo/core/test:test_support",
     "//remoting:test_support",
diff --git a/remoting/host/setup/BUILD.gn b/remoting/host/setup/BUILD.gn
index bf4035d2..e22c8c5 100644
--- a/remoting/host/setup/BUILD.gn
+++ b/remoting/host/setup/BUILD.gn
@@ -3,12 +3,8 @@
 # found in the LICENSE file.
 
 source_set("setup") {
-  public_deps = [
-    ":common",
-  ]
-  deps = [
-    "//remoting/host",
-  ]
+  public_deps = [ ":common" ]
+  deps = [ "//remoting/host" ]
 }
 
 source_set("common") {
diff --git a/remoting/host/win/BUILD.gn b/remoting/host/win/BUILD.gn
index e1e6f2a..633055d 100644
--- a/remoting/host/win/BUILD.gn
+++ b/remoting/host/win/BUILD.gn
@@ -178,12 +178,8 @@
 action("generate_idl") {
   script = "//build/util/version.py"
 
-  inputs = [
-    "chromoting_lib_idl.templ",
-  ]
-  outputs = [
-    "$target_gen_dir/chromoting_lib.idl",
-  ]
+  inputs = [ "chromoting_lib_idl.templ" ]
+  outputs = [ "$target_gen_dir/chromoting_lib.idl" ]
 
   args = [
     "-e",
@@ -196,9 +192,7 @@
 midl("remoting_lib_idl") {
   sources = get_target_outputs(":generate_idl")
   dynamic_guid = rdp_desktop_session_clsid
-  deps = [
-    ":generate_idl",
-  ]
+  deps = [ ":generate_idl" ]
   writes_tlb = true
 }
 
@@ -241,16 +235,12 @@
     "REGISTER_PROXY_DLL",
   ]
 
-  deps = [
-    ":remoting_lib_idl",
-  ]
+  deps = [ ":remoting_lib_idl" ]
 }
 
 # Makes the .mc file from the .mc.jinja file.
 remoting_localize("messages_localizing") {
-  sources = [
-    "host_messages.mc.jinja2",
-  ]
+  sources = [ "host_messages.mc.jinja2" ]
   locales = remoting_locales
   locale_dir = resources_locale_dir
   encoding = "utf-16"
@@ -269,9 +259,7 @@
 message_compiler("messages") {
   compile_generated_code = false
   sources = get_target_outputs(":messages_localizing")
-  deps = [
-    ":messages_localizing",
-  ]
+  deps = [ ":messages_localizing" ]
 }
 
 executable("remoting_console") {
@@ -496,9 +484,7 @@
 }
 
 remoting_localize("remoting_windows_resources") {
-  deps = [
-    "//remoting/resources",
-  ]
+  deps = [ "//remoting/resources" ]
 
   sources = [
     "core.rc.jinja2",
diff --git a/remoting/ios/BUILD.gn b/remoting/ios/BUILD.gn
index 055fdce..a90ddad 100644
--- a/remoting/ios/BUILD.gn
+++ b/remoting/ios/BUILD.gn
@@ -17,9 +17,7 @@
 group("all_test") {
   testonly = true
 
-  deps = [
-    ":ios_core_unit_tests",
-  ]
+  deps = [ ":ios_core_unit_tests" ]
 }
 
 source_set("ios_core") {
@@ -93,14 +91,8 @@
 
 foreach(locale, remoting_locales_with_underscores) {
   bundle_data("unittests_locale_${locale}_bundle_data") {
-    sources = [
-      "$root_out_dir/remoting/resources/$locale.lproj/locale.pak",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
-    public_deps = [
-      "//remoting/resources:copy_locales",
-    ]
+    sources = [ "$root_out_dir/remoting/resources/$locale.lproj/locale.pak" ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
+    public_deps = [ "//remoting/resources:copy_locales" ]
   }
 }
diff --git a/remoting/ios/app/BUILD.gn b/remoting/ios/app/BUILD.gn
index 0a78bfe..a12c799 100644
--- a/remoting/ios/app/BUILD.gn
+++ b/remoting/ios/app/BUILD.gn
@@ -8,9 +8,7 @@
 group("all") {
   testonly = true
 
-  deps = [
-    ":ios_remoting_app",
-  ]
+  deps = [ ":ios_remoting_app" ]
 }
 
 # source set to be used by both external and internal app.
diff --git a/remoting/ios/app/remoting_ios_tmpl.gni b/remoting/ios/app/remoting_ios_tmpl.gni
index 1080e2b..0ff412d 100644
--- a/remoting/ios/app/remoting_ios_tmpl.gni
+++ b/remoting/ios/app/remoting_ios_tmpl.gni
@@ -58,12 +58,8 @@
   _credits_bundle_target_name = "${target_name}_credits_bundle"
   bundle_data(_credits_bundle_target_name) {
     sources = get_target_outputs(":$_credits_resources_target_name")
-    public_deps = [
-      ":$_credits_resources_target_name",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/{{source_file_part}}",
-    ]
+    public_deps = [ ":$_credits_resources_target_name" ]
+    outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
   }
 
   ios_app_bundle(target_name) {
diff --git a/remoting/ios/app/resources/BUILD.gn b/remoting/ios/app/resources/BUILD.gn
index 31e0430..0e1d763b 100644
--- a/remoting/ios/app/resources/BUILD.gn
+++ b/remoting/ios/app/resources/BUILD.gn
@@ -89,9 +89,7 @@
 
 action("infoplist_strings") {
   _source = "InfoPlist.strings.jinja2"
-  sources = [
-    _source,
-  ]
+  sources = [ _source ]
 
   script = "//remoting/tools/build/remoting_localize.py"
   args = [
@@ -124,9 +122,7 @@
       "$root_gen_dir/remoting/ios/app/InfoPlist_Strings/$locale.lproj/InfoPlist.strings",
       "$root_out_dir/remoting/resources/$locale.lproj/locale.pak",
     ]
-    outputs = [
-      "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}",
-    ]
+    outputs = [ "{{bundle_resources_dir}}/$locale.lproj/{{source_file_part}}" ]
     public_deps = [
       ":infoplist_strings",
       "//remoting/resources:copy_locales",
diff --git a/remoting/ios/audio/BUILD.gn b/remoting/ios/audio/BUILD.gn
index fb57d01..d0ad2af 100644
--- a/remoting/ios/audio/BUILD.gn
+++ b/remoting/ios/audio/BUILD.gn
@@ -18,9 +18,7 @@
     "//remoting/client/audio",
   ]
 
-  public_deps = [
-    "//remoting/proto",
-  ]
+  public_deps = [ "//remoting/proto" ]
 
   libs = [ "AudioToolbox.framework" ]
 
@@ -29,9 +27,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "audio_playback_sink_ios_unittest.cc",
-  ]
+  sources = [ "audio_playback_sink_ios_unittest.cc" ]
   deps = [
     ":audio",
     "//remoting/client/audio:test_support",
diff --git a/remoting/ios/display/BUILD.gn b/remoting/ios/display/BUILD.gn
index 9180fd9..2026126 100644
--- a/remoting/ios/display/BUILD.gn
+++ b/remoting/ios/display/BUILD.gn
@@ -5,9 +5,7 @@
 group("all") {
   testonly = true
 
-  deps = [
-    ":display",
-  ]
+  deps = [ ":display" ]
 }
 
 group("all_test") {
diff --git a/remoting/ios/facade/BUILD.gn b/remoting/ios/facade/BUILD.gn
index f7318ab..4a4c0f14 100644
--- a/remoting/ios/facade/BUILD.gn
+++ b/remoting/ios/facade/BUILD.gn
@@ -48,9 +48,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "host_list_service_unittest.mm",
-  ]
+  sources = [ "host_list_service_unittest.mm" ]
   deps = [
     ":facade",
     "//remoting/base/grpc_test_support",
diff --git a/remoting/ios/persistence/BUILD.gn b/remoting/ios/persistence/BUILD.gn
index 1991d46..99796613 100644
--- a/remoting/ios/persistence/BUILD.gn
+++ b/remoting/ios/persistence/BUILD.gn
@@ -35,9 +35,7 @@
     "mock_keychain.h",
   ]
 
-  public_deps = [
-    "//testing/gmock",
-  ]
+  public_deps = [ "//testing/gmock" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/remoting/proto/ftl/v1/BUILD.gn b/remoting/proto/ftl/v1/BUILD.gn
index 7441b62..23ec08ea 100644
--- a/remoting/proto/ftl/v1/BUILD.gn
+++ b/remoting/proto/ftl/v1/BUILD.gn
@@ -13,10 +13,6 @@
 }
 
 cc_grpc_library("ftl_grpc_library") {
-  sources = [
-    "ftl_services.proto",
-  ]
-  deps = [
-    ":ftl_messages",
-  ]
+  sources = [ "ftl_services.proto" ]
+  deps = [ ":ftl_messages" ]
 }
diff --git a/remoting/proto/remoting/v1/BUILD.gn b/remoting/proto/remoting/v1/BUILD.gn
index d5eab716..a329a1b 100644
--- a/remoting/proto/remoting/v1/BUILD.gn
+++ b/remoting/proto/remoting/v1/BUILD.gn
@@ -6,27 +6,17 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("host_info_proto") {
-  sources = [
-    "host_info.proto",
-  ]
+  sources = [ "host_info.proto" ]
 }
 
 proto_library("directory_proto") {
-  sources = [
-    "directory_messages.proto",
-  ]
-  deps = [
-    ":host_info_proto",
-  ]
+  sources = [ "directory_messages.proto" ]
+  deps = [ ":host_info_proto" ]
 }
 
 cc_grpc_library("directory_grpc_library") {
-  sources = [
-    "directory_service.proto",
-  ]
-  deps = [
-    ":directory_proto",
-  ]
+  sources = [ "directory_service.proto" ]
+  deps = [ ":directory_proto" ]
 }
 
 if (is_android) {
@@ -42,18 +32,12 @@
 }
 
 proto_library("network_traversal_proto") {
-  sources = [
-    "network_traversal_messages.proto",
-  ]
+  sources = [ "network_traversal_messages.proto" ]
 }
 
 cc_grpc_library("network_traversal_grpc_library") {
-  sources = [
-    "network_traversal_service.proto",
-  ]
-  deps = [
-    ":network_traversal_proto",
-  ]
+  sources = [ "network_traversal_service.proto" ]
+  deps = [ ":network_traversal_proto" ]
 }
 
 cc_grpc_library("remote_support_host_grpc_library") {
@@ -61,15 +45,11 @@
     "remote_support_host_messages.proto",
     "remote_support_host_service.proto",
   ]
-  deps = [
-    ":host_info_proto",
-  ]
+  deps = [ ":host_info_proto" ]
 }
 
 proto_library("chromoting_event_proto") {
-  sources = [
-    "chromoting_event.proto",
-  ]
+  sources = [ "chromoting_event.proto" ]
 }
 
 proto_library("telemetry_messages") {
@@ -77,16 +57,10 @@
     "generic_log_entry.proto",
     "telemetry_messages.proto",
   ]
-  deps = [
-    ":chromoting_event_proto",
-  ]
+  deps = [ ":chromoting_event_proto" ]
 }
 
 cc_grpc_library("telemetry_grpc_library") {
-  sources = [
-    "telemetry_service.proto",
-  ]
-  deps = [
-    ":telemetry_messages",
-  ]
+  sources = [ "telemetry_service.proto" ]
+  deps = [ ":telemetry_messages" ]
 }
diff --git a/remoting/resources/BUILD.gn b/remoting/resources/BUILD.gn
index 56d2afa2..286a08b 100644
--- a/remoting/resources/BUILD.gn
+++ b/remoting/resources/BUILD.gn
@@ -32,9 +32,7 @@
   inputs = [ "remoting_strings.grd" ] + sources_to_verify
 
   stampfile = "$root_out_dir/remoting_resources_verified_stamp"
-  outputs = [
-    stampfile,
-  ]
+  outputs = [ stampfile ]
 
   args = [
            "-t",
@@ -60,9 +58,7 @@
   # generated file root.
   output_dir = root_gen_dir
 
-  outputs = [
-    "remoting/base/string_resources.h",
-  ]
+  outputs = [ "remoting/base/string_resources.h" ]
 
   # The grd produces a *.pak file and a messages.json file (this one uses
   # underscores instead of hyphens) for each locale.
@@ -86,9 +82,7 @@
     grit_output_dir = "$root_gen_dir/remoting/android/res"
     generated_files =
         rebase_path(android_string_outputs, "remoting/android/res", ".")
-    deps = [
-      ":strings",
-    ]
+    deps = [ ":strings" ]
   }
 }
 
@@ -125,7 +119,5 @@
            rebase_path(root_out_dir, root_build_dir),
          ] + remoting_locales
 
-  deps = [
-    ":strings",
-  ]
+  deps = [ ":strings" ]
 }
diff --git a/remoting/test/BUILD.gn b/remoting/test/BUILD.gn
index b54191a..3d04281 100644
--- a/remoting/test/BUILD.gn
+++ b/remoting/test/BUILD.gn
@@ -132,13 +132,9 @@
     defines = []
     libs = []
 
-    sources = [
-      "it2me_standalone_host_main.cc",
-    ]
+    sources = [ "it2me_standalone_host_main.cc" ]
 
-    deps = [
-      ":it2me_standalone_host",
-    ]
+    deps = [ ":it2me_standalone_host" ]
 
     if (is_desktop_linux) {
       deps += [ "//build/config/linux/gtk" ]
@@ -158,13 +154,9 @@
   # purpose only.
   executable("capability_test_stub") {
     testonly = true
-    sources = [
-      "capability_test_stub_main.cc",
-    ]
+    sources = [ "capability_test_stub_main.cc" ]
 
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
   }
 }
 
diff --git a/remoting/tools/BUILD.gn b/remoting/tools/BUILD.gn
index b0d72be..6d6cf26 100644
--- a/remoting/tools/BUILD.gn
+++ b/remoting/tools/BUILD.gn
@@ -28,8 +28,6 @@
 
     configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-    sources = [
-      "breakpad_tester_win.cc",
-    ]
+    sources = [ "breakpad_tester_win.cc" ]
   }
 }
diff --git a/remoting/tools/build/remoting_localize.gni b/remoting/tools/build/remoting_localize.gni
index 53e80238..a0dbb8cc 100644
--- a/remoting/tools/build/remoting_localize.gni
+++ b/remoting/tools/build/remoting_localize.gni
@@ -43,13 +43,9 @@
     sources = invoker.sources
 
     if (defined(invoker.output)) {
-      outputs = [
-        invoker.output,
-      ]
+      outputs = [ invoker.output ]
     } else {
-      outputs = [
-        "$target_gen_dir/{{source_name_part}}",
-      ]
+      outputs = [ "$target_gen_dir/{{source_name_part}}" ]
     }
 
     args = []
diff --git a/services/identity/BUILD.gn b/services/identity/BUILD.gn
index 09932549..6b4dc56 100644
--- a/services/identity/BUILD.gn
+++ b/services/identity/BUILD.gn
@@ -32,9 +32,7 @@
 source_set("tests") {
   testonly = true
 
-  sources = [
-    "identity_accessor_impl_unittest.cc",
-  ]
+  sources = [ "identity_accessor_impl_unittest.cc" ]
 
   deps = [
     ":lib",
@@ -51,8 +49,6 @@
 
 if (is_android) {
   java_group("java") {
-    deps = [
-      "//components/signin/core/browser/android:java",
-    ]
+    deps = [ "//components/signin/core/browser/android:java" ]
   }
 }
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index dd20ede..b990534 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -19,9 +19,7 @@
 source_set("android_browsertests_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/bfcache.android_browsertests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/bfcache.android_browsertests.filter" ]
 }
 
 source_set("blink_web_tests_filter") {
@@ -35,9 +33,7 @@
 source_set("breakpad_unittests_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/android.asan.breakpad_unittests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/android.asan.breakpad_unittests.filter" ]
 }
 
 source_set("browser_tests_filters") {
@@ -99,9 +95,7 @@
 source_set("content_shell_test_apk_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
-  ]
+  data = [ "//testing/buildbot/filters/bfcache.content_shell_test_apk.filter" ]
 }
 
 source_set("content_unittests_filters") {
@@ -116,9 +110,7 @@
 source_set("e2e_sync_integration_tests_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/e2e.sync_integration_tests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/e2e.sync_integration_tests.filter" ]
 }
 
 source_set("fuchsia_filters") {
@@ -144,27 +136,20 @@
 }
 
 source_set("linux_ozone_views_unittests_filters") {
-  data = [
-    "//testing/buildbot/filters/ozone-linux.x11_views_unittests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/ozone-linux.x11_views_unittests.filter" ]
 }
 
 source_set("linux_trusty_rel_browser_tests_filters") {
-  data = [
-    "//testing/buildbot/filters/linux_trusty_rel.browser_tests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/linux_trusty_rel.browser_tests.filter" ]
 }
 
 source_set("media_unittests_filters") {
-  data = [
-    "//testing/buildbot/filters/android.emulator.media_unittests.filter",
-  ]
+  data =
+      [ "//testing/buildbot/filters/android.emulator.media_unittests.filter" ]
 }
 
 source_set("ozone_unittests_filters") {
-  data = [
-    "//testing/buildbot/filters/chromeos.ozone_unittests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/chromeos.ozone_unittests.filter" ]
 }
 
 source_set("unit_tests_filters") {
@@ -179,23 +164,18 @@
 source_set("viz_unittests_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/android.emulator.viz_unittests.filter",
-  ]
+  data = [ "//testing/buildbot/filters/android.emulator.viz_unittests.filter" ]
 }
 
 source_set("webview_cts_tests_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter",
-  ]
+  data =
+      [ "//testing/buildbot/filters/mojo.fyi.network_webview_CTS_test.filter" ]
 }
 
 source_set("webview_instrumentation_test_apk_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter",
-  ]
+  data = [ "//testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter" ]
 }
diff --git a/testing/buildbot/filters/skia_renderer.content_browsertests.filter b/testing/buildbot/filters/skia_renderer.content_browsertests.filter
index aeb98e870..d2b3edb 100644
--- a/testing/buildbot/filters/skia_renderer.content_browsertests.filter
+++ b/testing/buildbot/filters/skia_renderer.content_browsertests.filter
@@ -1,5 +1,5 @@
-AuraWindowVideoCaptureDeviceBrowserTestP.*
+All/AuraWindowVideoCaptureDeviceBrowserTestP.*
 CaptureScreenshotTest.*
 OOPBrowserTest.Basic
 SnapshotBrowserTest.*
-WebContentsVideoCaptureDeviceBrowserTestP.*
+All/WebContentsVideoCaptureDeviceBrowserTestP.*
diff --git a/testing/buildbot/filters/vulkan.content_browsertests.filter b/testing/buildbot/filters/vulkan.content_browsertests.filter
index d63e38d..125a905 100644
--- a/testing/buildbot/filters/vulkan.content_browsertests.filter
+++ b/testing/buildbot/filters/vulkan.content_browsertests.filter
@@ -1,8 +1,8 @@
 AuraWindowVideoCaptureDeviceBrowserTest.*
 # Some of these tests fallback on software compositing.
-AuraWindowVideoCaptureDeviceBrowserTestP.*
+All/AuraWindowVideoCaptureDeviceBrowserTestP.*
 CaptureScreenshotTest.*
 OOPBrowserTest.Basic
 SnapshotBrowserTest.*
 # Some of these tests fallback on software compositing.
-WebContentsVideoCaptureDeviceBrowserTestP.*
+All/WebContentsVideoCaptureDeviceBrowserTestP.*
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c3f59fd..c14701a 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1594,6 +1594,26 @@
             ]
         }
     ],
+    "ChromeStart": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "params": {
+                        "start_surface_variation": "tasksonly",
+                        "tab_switcher_on_return_time_ms": "3600000"
+                    },
+                    "enable_features": [
+                        "StartSurfaceAndroid",
+                        "TabSwitcherOnReturn"
+                    ]
+                }
+            ]
+        }
+    ],
     "ChromeSuggestionsTuningForceTopSites": [
         {
             "platforms": [
diff --git a/third_party/android_data_chart/BUILD.gn b/third_party/android_data_chart/BUILD.gn
index dc1707b..68c7625 100644
--- a/third_party/android_data_chart/BUILD.gn
+++ b/third_party/android_data_chart/BUILD.gn
@@ -21,7 +21,5 @@
     "java/src/org/chromium/third_party/android/datausagechart/NetworkStats.java",
     "java/src/org/chromium/third_party/android/datausagechart/NetworkStatsHistory.java",
   ]
-  deps = [
-    ":android_data_chart_java_resources",
-  ]
+  deps = [ ":android_data_chart_java_resources" ]
 }
diff --git a/third_party/blink/public/mojom/dom_storage/BUILD.gn b/third_party/blink/public/mojom/dom_storage/BUILD.gn
index a93e337..5d013ad 100644
--- a/third_party/blink/public/mojom/dom_storage/BUILD.gn
+++ b/third_party/blink/public/mojom/dom_storage/BUILD.gn
@@ -14,9 +14,7 @@
     "storage_partition_service.mojom",
   ]
 
-  public_deps = [
-    "//url/mojom:url_mojom_origin",
-  ]
+  public_deps = [ "//url/mojom:url_mojom_origin" ]
 
   # The Blink variant is linked directly into the private platform
   # implementation and so it requires the corresponding export configuration to
diff --git a/third_party/blink/public/web/web_ax_enums.h b/third_party/blink/public/web/web_ax_enums.h
index 42e333c..8da4409 100644
--- a/third_party/blink/public/web/web_ax_enums.h
+++ b/third_party/blink/public/web/web_ax_enums.h
@@ -124,7 +124,6 @@
 // sparse attribute the default value must be the null WebAXObject.
 enum class WebAXObjectAttribute {
   kAriaActiveDescendant,
-  kAriaDetails,
   kAriaErrorMessage,
 };
 
@@ -134,6 +133,7 @@
 // empty vector.
 enum class WebAXObjectVectorAttribute {
   kAriaControls,
+  kAriaDetails,
   kAriaFlowTo,
 };
 
diff --git a/third_party/blink/renderer/build/scripts/scripts.gni b/third_party/blink/renderer/build/scripts/scripts.gni
index 06e2920..7da4412 100644
--- a/third_party/blink/renderer/build/scripts/scripts.gni
+++ b/third_party/blink/renderer/build/scripts/scripts.gni
@@ -93,9 +93,7 @@
 template("blink_python_runner") {
   action(target_name) {
     script = "$_scripts_dir/run_with_pythonpath.py"
-    sources = [
-      invoker.script,
-    ]
+    sources = [ invoker.script ]
     if (defined(invoker.sources)) {
       sources += invoker.sources
     }
diff --git a/third_party/blink/renderer/core/aom/accessible_node.cc b/third_party/blink/renderer/core/aom/accessible_node.cc
index 901ccc59..48f7f3e 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.cc
+++ b/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -66,9 +66,6 @@
     case AOMRelationProperty::kActiveDescendant:
       return html_names::kAriaActivedescendantAttr;
       break;
-    case AOMRelationProperty::kDetails:
-      return html_names::kAriaDetailsAttr;
-      break;
     case AOMRelationProperty::kErrorMessage:
       return html_names::kAriaErrormessageAttr;
       break;
@@ -83,6 +80,9 @@
     case AOMRelationListProperty::kDescribedBy:
       return html_names::kAriaDescribedbyAttr;
       break;
+    case AOMRelationListProperty::kDetails:
+      return html_names::kAriaDetailsAttr;
+      break;
     case AOMRelationListProperty::kControls:
       return html_names::kAriaControlsAttr;
       break;
@@ -655,12 +655,12 @@
   NotifyAttributeChanged(html_names::kAriaDescriptionAttr);
 }
 
-AccessibleNode* AccessibleNode::details() const {
-  return GetProperty(element_, AOMRelationProperty::kDetails);
+AccessibleNodeList* AccessibleNode::details() const {
+  return GetProperty(element_, AOMRelationListProperty::kDetails);
 }
 
-void AccessibleNode::setDetails(AccessibleNode* details) {
-  SetRelationProperty(AOMRelationProperty::kDetails, details);
+void AccessibleNode::setDetails(AccessibleNodeList* details) {
+  SetRelationListProperty(AOMRelationListProperty::kDetails, details);
   NotifyAttributeChanged(html_names::kAriaDetailsAttr);
 }
 
diff --git a/third_party/blink/renderer/core/aom/accessible_node.h b/third_party/blink/renderer/core/aom/accessible_node.h
index 6ef76b7..e2d176b 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.h
+++ b/third_party/blink/renderer/core/aom/accessible_node.h
@@ -70,12 +70,12 @@
 
 enum class AOMRelationProperty {
   kActiveDescendant,
-  kDetails,
   kErrorMessage,
 };
 
 enum class AOMRelationListProperty {
   kDescribedBy,
+  kDetails,
   kControls,
   kFlowTo,
   kLabeledBy,
@@ -234,8 +234,8 @@
   AtomicString description() const;
   void setDescription(const AtomicString&);
 
-  AccessibleNode* details() const;
-  void setDetails(AccessibleNode*);
+  AccessibleNodeList* details() const;
+  void setDetails(AccessibleNodeList*);
 
   bool disabled(bool& is_null) const;
   void setDisabled(bool, bool is_null);
diff --git a/third_party/blink/renderer/core/aom/accessible_node.idl b/third_party/blink/renderer/core/aom/accessible_node.idl
index 38fb58f..b8e78529c4 100644
--- a/third_party/blink/renderer/core/aom/accessible_node.idl
+++ b/third_party/blink/renderer/core/aom/accessible_node.idl
@@ -20,7 +20,7 @@
     attribute AccessibleNodeList? controls;
     attribute DOMString? current;
     attribute AccessibleNodeList? describedBy;
-    attribute AccessibleNode? details;
+    attribute AccessibleNodeList? details;
     attribute boolean? disabled;
     attribute AccessibleNode? errorMessage;
     attribute boolean? expanded;
diff --git a/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl b/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl
index 7a2a504..2229d59 100644
--- a/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl
+++ b/third_party/blink/renderer/core/dom/aria_relationship_attributes.idl
@@ -10,7 +10,7 @@
     [CEReactions, Reflect=aria_activedescendant] attribute Element? ariaActiveDescendantElement;
     [CEReactions, Reflect=aria_controls] attribute FrozenArray<Element>? ariaControlsElements;
     [CEReactions, Reflect=aria_describedby] attribute FrozenArray<Element>? ariaDescribedByElements;
-    [CEReactions, Reflect=aria_details] attribute Element? ariaDetailsElement;
+    [CEReactions, Reflect=aria_details] attribute FrozenArray<Element>? ariaDetailsElements;
     [CEReactions, Reflect=aria_errormessage] attribute Element? ariaErrorMessageElement;
     [CEReactions, Reflect=aria_flowto] attribute FrozenArray<Element>? ariaFlowToElements;
     [CEReactions, Reflect=aria_labelledby] attribute FrozenArray<Element>? ariaLabelledByElements;
diff --git a/third_party/blink/renderer/core/frame/browser_controls.cc b/third_party/blink/renderer/core/frame/browser_controls.cc
index cdb13668..4654b8a 100644
--- a/third_party/blink/renderer/core/frame/browser_controls.cc
+++ b/third_party/blink/renderer/core/frame/browser_controls.cc
@@ -118,8 +118,10 @@
 }
 
 void BrowserControls::SetShownRatio(float top_ratio, float bottom_ratio) {
-  top_ratio = clampTo(top_ratio, 0.f, 1.f);
-  bottom_ratio = clampTo(bottom_ratio, 0.f, 1.f);
+  // The ratios can be > 1 during height change animations, so we shouldn't
+  // clamp the values.
+  top_ratio = std::max(0.f, top_ratio);
+  bottom_ratio = std::max(0.f, bottom_ratio);
 
   if (top_shown_ratio_ == top_ratio && bottom_shown_ratio_ == bottom_ratio)
     return;
diff --git a/third_party/blink/renderer/core/html/parser/BUILD.gn b/third_party/blink/renderer/core/html/parser/BUILD.gn
index 83e917e1..f791662 100644
--- a/third_party/blink/renderer/core/html/parser/BUILD.gn
+++ b/third_party/blink/renderer/core/html/parser/BUILD.gn
@@ -85,9 +85,7 @@
 }
 
 fuzzer_test("blink_html_tokenizer_fuzzer") {
-  sources = [
-    "html_tokenizer_fuzzer.cc",
-  ]
+  sources = [ "html_tokenizer_fuzzer.cc" ]
   deps = [
     "../../:core",
     "../../../platform:blink_fuzzer_test_support",
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
index 1f6d439..b85b4d6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -9,12 +9,14 @@
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_flex_child_iterator.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
@@ -306,6 +308,11 @@
     }
   }
 
+  space_builder.SetNeedsBaseline(
+      ConstraintSpace().NeedsBaseline() ||
+      FlexLayoutAlgorithm::AlignmentForChild(Style(), child_style) ==
+          ItemPosition::kBaseline);
+
   space_builder.SetAvailableSize(content_box_size_);
   space_builder.SetPercentageResolutionSize(child_percentage_size_);
   space_builder.SetTextDirection(child_style.Direction());
@@ -608,15 +615,13 @@
     for (wtf_size_t i = 0; i < line->line_items.size(); ++i) {
       FlexItem& flex_item = line->line_items[i];
 
-      WritingMode child_writing_mode =
-          flex_item.ng_input_node.Style().GetWritingMode();
+      const ComputedStyle& child_style = flex_item.ng_input_node.Style();
       NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
-                                             child_writing_mode,
+                                             child_style.GetWritingMode(),
                                              /* is_new_fc */ true);
       SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item.ng_input_node,
                                               &space_builder);
-      space_builder.SetTextDirection(
-          flex_item.ng_input_node.Style().Direction());
+      space_builder.SetTextDirection(child_style.Direction());
       space_builder.SetIsPaintedAtomically(true);
 
       LogicalSize available_size;
@@ -646,6 +651,11 @@
           space_builder.SetIsFixedBlockSize(true);
       }
 
+      space_builder.SetNeedsBaseline(
+          ConstraintSpace().NeedsBaseline() ||
+          FlexLayoutAlgorithm::AlignmentForChild(Style(), child_style) ==
+              ItemPosition::kBaseline);
+
       space_builder.SetAvailableSize(available_size);
       space_builder.SetPercentageResolutionSize(child_percentage_size_);
 
@@ -694,9 +704,9 @@
 }
 
 void NGFlexLayoutAlgorithm::ApplyStretchAlignmentToChild(FlexItem& flex_item) {
-  WritingMode child_writing_mode =
-      flex_item.ng_input_node.Style().GetWritingMode();
-  NGConstraintSpaceBuilder space_builder(ConstraintSpace(), child_writing_mode,
+  const ComputedStyle& child_style = flex_item.ng_input_node.Style();
+  NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
+                                         child_style.GetWritingMode(),
                                          /* is_new_fc */ true);
   SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item.ng_input_node,
                                           &space_builder);
@@ -712,7 +722,13 @@
       space_builder.SetIsFixedBlockSizeIndefinite(true);
     }
   }
-  space_builder.SetTextDirection(flex_item.ng_input_node.Style().Direction());
+
+  space_builder.SetNeedsBaseline(
+      ConstraintSpace().NeedsBaseline() ||
+      FlexLayoutAlgorithm::AlignmentForChild(Style(), child_style) ==
+          ItemPosition::kBaseline);
+
+  space_builder.SetTextDirection(child_style.Direction());
   space_builder.SetAvailableSize(available_size);
   space_builder.SetPercentageResolutionSize(child_percentage_size_);
   space_builder.SetIsFixedInlineSize(true);
@@ -755,6 +771,8 @@
                                     border_scrollbar_padding_.block_start);
   }
 
+  base::Optional<LayoutUnit> fallback_baseline;
+
   for (FlexLine& line_context : line_contexts) {
     for (wtf_size_t child_number = 0;
          child_number < line_context.line_items.size(); ++child_number) {
@@ -763,6 +781,9 @@
       if (DoesItemStretch(flex_item.ng_input_node))
         ApplyStretchAlignmentToChild(flex_item);
 
+      const auto& physical_fragment = To<NGPhysicalBoxFragment>(
+          flex_item.layout_result->PhysicalFragment());
+
       // flex_item.desired_location stores the main axis offset in X and the
       // cross axis offset in Y. But AddChild wants offset from parent
       // rectangle, so we have to transpose for columns. AddChild takes care of
@@ -770,11 +791,57 @@
       LayoutPoint location = is_column_
                                  ? flex_item.desired_location.TransposedPoint()
                                  : flex_item.desired_location;
-      container_builder_.AddChild(flex_item.layout_result->PhysicalFragment(),
+
+      // Only propagate baselines from children on the first flex-line.
+      if (&line_context == line_contexts.begin()) {
+        PropagateBaselineFromChild(flex_item, physical_fragment, location.Y(),
+                                   &fallback_baseline);
+      }
+
+      container_builder_.AddChild(physical_fragment,
                                   {location.X(), location.Y()});
       flex_item.ng_input_node.StoreMargins(flex_item.physical_margins);
     }
   }
+
+  // Set the baseline to the fallback, if we didn't find any children with
+  // baseline alignment.
+  if (!container_builder_.Baseline() && fallback_baseline)
+    container_builder_.SetBaseline(*fallback_baseline);
+}
+
+void NGFlexLayoutAlgorithm::PropagateBaselineFromChild(
+    const FlexItem& flex_item,
+    const NGPhysicalBoxFragment& physical_fragment,
+    LayoutUnit block_offset,
+    base::Optional<LayoutUnit>* fallback_baseline) {
+  // Check if we've already found an appropriate baseline.
+  if (container_builder_.Baseline())
+    return;
+
+  NGBoxFragment fragment(ConstraintSpace().GetWritingMode(),
+                         ConstraintSpace().Direction(), physical_fragment);
+
+  if (base::Optional<LayoutUnit> baseline = fragment.Baseline()) {
+    LayoutUnit baseline_offset = block_offset + *baseline;
+
+    // We prefer a baseline from a child with baseline alignment, and no
+    // auto-margins in the cross axis.
+    if (FlexLayoutAlgorithm::AlignmentForChild(Style(), flex_item.style) ==
+            ItemPosition::kBaseline &&
+        !flex_item.HasAutoMarginsInCrossAxis()) {
+      container_builder_.SetBaseline(baseline_offset);
+      return;
+    }
+
+    // Set the fallback baseline to this (if not set yet).
+    *fallback_baseline = fallback_baseline->value_or(baseline_offset);
+    return;
+  }
+
+  // Use the block-end border-box edge as the last resort baseline.
+  *fallback_baseline =
+      fallback_baseline->value_or(block_offset + fragment.BlockSize());
 }
 
 base::Optional<MinMaxSize> NGFlexLayoutAlgorithm::ComputeMinMaxSize(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
index 3739c67..167a9d160 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
@@ -60,6 +60,14 @@
   LayoutUnit MainAxisContentExtent(LayoutUnit sum_hypothetical_main_size) const;
 
   void HandleOutOfFlowPositioned(NGBlockNode child);
+
+  // Propagates the baseline from the given flex-item if needed.
+  void PropagateBaselineFromChild(
+      const FlexItem&,
+      const NGPhysicalBoxFragment&,
+      LayoutUnit block_offset,
+      base::Optional<LayoutUnit>* fallback_baseline);
+
   // TODO(dgrogan): This is redundant with FlexLayoutAlgorithm.IsMultiline() but
   // it's needed before the algorithm is instantiated. Figure out how to
   // not reimplement.
diff --git a/third_party/blink/renderer/core/messaging/BUILD.gn b/third_party/blink/renderer/core/messaging/BUILD.gn
index ec799e52..a523a06d 100644
--- a/third_party/blink/renderer/core/messaging/BUILD.gn
+++ b/third_party/blink/renderer/core/messaging/BUILD.gn
@@ -20,7 +20,5 @@
     "message_port.h",
   ]
 
-  public_deps = [
-    "//third_party/blink/public/mojom:mojom_core_blink",
-  ]
+  public_deps = [ "//third_party/blink/public/mojom:mojom_core_blink" ]
 }
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h
index bdb6aa10..a7b0d01e 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.h
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -290,11 +290,12 @@
   FRIEND_TEST_ALL_PREFIXES(FileChooserQueueTest, DerefQueuedChooser);
 };
 
-DEFINE_TYPE_CASTS(ChromeClientImpl,
-                  ChromeClient,
-                  client,
-                  client->IsChromeClientImpl(),
-                  client.IsChromeClientImpl());
+template <>
+struct DowncastTraits<ChromeClientImpl> {
+  static bool AllowFrom(const ChromeClient& client) {
+    return client.IsChromeClientImpl();
+  }
+};
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
index 6534687..0a6b0d0d 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -79,7 +79,7 @@
     web_view_ = helper_.Initialize(nullptr, &web_view_client_);
     main_frame_ = helper_.LocalMainFrame();
     chrome_client_impl_ =
-        ToChromeClientImpl(&web_view_->GetPage()->GetChromeClient());
+        To<ChromeClientImpl>(&web_view_->GetPage()->GetChromeClient());
   }
 
   ViewCreatingClient web_view_client_;
@@ -186,7 +186,7 @@
     web_view_ = helper_.Initialize();
     main_frame_ = helper_.LocalMainFrame();
     chrome_client_impl_ =
-        ToChromeClientImpl(&web_view_->GetPage()->GetChromeClient());
+        To<ChromeClientImpl>(&web_view_->GetPage()->GetChromeClient());
     LocalFrame* frame = helper_.LocalMainFrame()->GetFrame();
     color_chooser_client_ = MakeGarbageCollected<FakeColorChooserClient>(
         frame->GetDocument()->documentElement());
@@ -258,7 +258,7 @@
   void SetUp() override {
     web_view_ = helper_.Initialize();
     chrome_client_impl_ =
-        ToChromeClientImpl(&web_view_->GetPage()->GetChromeClient());
+        To<ChromeClientImpl>(&web_view_->GetPage()->GetChromeClient());
   }
 
   frame_test_helpers::WebViewHelper helper_;
diff --git a/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h b/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
index 27511e1..46e4262 100644
--- a/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
+++ b/third_party/blink/renderer/core/resize_observer/resize_observer_controller.h
@@ -42,13 +42,13 @@
   void Trace(blink::Visitor*);
 
   // For testing only.
-  const HeapHashSet<WeakMember<ResizeObserver>>& Observers() {
+  const HeapLinkedHashSet<WeakMember<ResizeObserver>>& Observers() {
     return observers_;
   }
 
  private:
   // Active observers
-  HeapHashSet<WeakMember<ResizeObserver>> observers_;
+  HeapLinkedHashSet<WeakMember<ResizeObserver>> observers_;
   // True if any observers were changed since last notification.
   bool observers_changed_;
 };
diff --git a/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc b/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
index abc7321..498bc35 100644
--- a/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
+++ b/third_party/blink/renderer/core/resize_observer/resize_observer_test.cc
@@ -102,7 +102,7 @@
 TEST_F(ResizeObserverUnitTest, TestMemoryLeaks) {
   ResizeObserverController& controller =
       GetDocument().EnsureResizeObserverController();
-  const HeapHashSet<WeakMember<ResizeObserver>>& observers =
+  const HeapLinkedHashSet<WeakMember<ResizeObserver>>& observers =
       controller.Observers();
   ASSERT_EQ(observers.size(), 0U);
   v8::HandleScope scope(v8::Isolate::GetCurrent());
diff --git a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
index 509ffe5..719101b 100644
--- a/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
@@ -346,10 +346,10 @@
             sparse_attributes.object_attributes
                 .at(AXObjectAttribute::kAriaActiveDescendant)
                 ->RoleValue());
-  ASSERT_EQ(
-      ax::mojom::Role::kContentInfo,
-      sparse_attributes.object_attributes.at(AXObjectAttribute::kAriaDetails)
-          ->RoleValue());
+  ASSERT_EQ(ax::mojom::Role::kContentInfo,
+            sparse_attributes.object_vector_attributes
+                .at(AXObjectVectorAttribute::kAriaDetails)[0]
+                ->RoleValue());
   ASSERT_EQ(ax::mojom::Role::kArticle,
             sparse_attributes.object_attributes
                 .at(AXObjectAttribute::kAriaErrorMessage)
@@ -359,8 +359,11 @@
   target->accessibleNode()->setRoleDescription("Object");
   target->accessibleNode()->setActiveDescendant(
       GetDocument().getElementById("active2")->accessibleNode());
-  target->accessibleNode()->setDetails(
+  AccessibleNodeList* details_node_list =
+      MakeGarbageCollected<AccessibleNodeList>();
+  details_node_list->add(
       GetDocument().getElementById("details2")->accessibleNode());
+  target->accessibleNode()->setDetails(details_node_list);
   target->accessibleNode()->setErrorMessage(
       GetDocument().getElementById("error2")->accessibleNode());
 
@@ -375,10 +378,10 @@
             sparse_attributes2.object_attributes
                 .at(AXObjectAttribute::kAriaActiveDescendant)
                 ->RoleValue());
-  ASSERT_EQ(
-      ax::mojom::Role::kContentInfo,
-      sparse_attributes2.object_attributes.at(AXObjectAttribute::kAriaDetails)
-          ->RoleValue());
+  ASSERT_EQ(ax::mojom::Role::kContentInfo,
+            sparse_attributes2.object_vector_attributes
+                .at(AXObjectVectorAttribute::kAriaDetails)[0]
+                ->RoleValue());
   ASSERT_EQ(ax::mojom::Role::kArticle,
             sparse_attributes2.object_attributes
                 .at(AXObjectAttribute::kAriaErrorMessage)
diff --git a/third_party/blink/renderer/modules/accessibility/ax_enums.cc b/third_party/blink/renderer/modules/accessibility/ax_enums.cc
index d1a3eeed..0fc39a7 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_enums.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_enums.cc
@@ -33,8 +33,8 @@
                    AXObjectAttribute::kAriaErrorMessage);
 STATIC_ASSERT_ENUM(WebAXObjectVectorAttribute::kAriaControls,
                    AXObjectVectorAttribute::kAriaControls);
-STATIC_ASSERT_ENUM(WebAXObjectAttribute::kAriaDetails,
-                   AXObjectAttribute::kAriaDetails);
+STATIC_ASSERT_ENUM(WebAXObjectVectorAttribute::kAriaDetails,
+                   AXObjectVectorAttribute::kAriaDetails);
 STATIC_ASSERT_ENUM(WebAXObjectVectorAttribute::kAriaFlowTo,
                    AXObjectVectorAttribute::kAriaFlowTo);
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_enums.h b/third_party/blink/renderer/modules/accessibility/ax_enums.h
index 81335f95..8230d0b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_enums.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_enums.h
@@ -63,12 +63,12 @@
 
 enum class AXObjectAttribute {
   kAriaActiveDescendant,
-  kAriaDetails,
   kAriaErrorMessage,
 };
 
 enum class AXObjectVectorAttribute {
   kAriaControls,
+  kAriaDetails,
   kAriaFlowTo,
 };
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc b/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
index 9d9bdfed..1b8a88b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
@@ -67,6 +67,12 @@
   if (!aria_role.IsEmpty())
     return AXObject::AriaRoleToWebCoreRole(aria_role);
 
+  // https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings
+  // <area> tags without an href should be treated as static text.
+  KURL url = Url();
+  if (url.IsNull() || url.IsEmpty())
+    return ax::mojom::Role::kStaticText;
+
   return ax::mojom::Role::kLink;
 }
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index c8e1129a..5a57d55 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -1639,10 +1639,6 @@
   return ax::mojom::Dropeffect::kNone;
 }
 
-bool AXLayoutObject::SupportsARIAFlowTo() const {
-  return !GetAttribute(html_names::kAriaFlowtoAttr).IsEmpty();
-}
-
 bool AXLayoutObject::SupportsARIAOwns() const {
   if (!layout_object_)
     return false;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
index 4021c56..54ede5e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -134,7 +134,6 @@
   ax::mojom::HasPopup HasPopup() const override;
   bool SupportsARIADragging() const override;
   void Dropeffects(Vector<ax::mojom::Dropeffect>& dropeffects) const override;
-  bool SupportsARIAFlowTo() const override;
   bool SupportsARIAOwns() const override;
 
   // ARIA live-region features.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index 0391076..39ba8dfd 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -736,7 +736,6 @@
   bool SupportsARIAExpanded() const;
   virtual bool SupportsARIADragging() const { return false; }
   virtual void Dropeffects(Vector<ax::mojom::Dropeffect>& dropeffects) const {}
-  virtual bool SupportsARIAFlowTo() const { return false; }
   virtual bool SupportsARIAOwns() const { return false; }
   bool SupportsRangeValue() const;
   bool SupportsARIAReadOnly() const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index f25d4cd..74a7ab7b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -419,7 +419,10 @@
 };
 
 // This is the only subclass of AXObjectCache.
-DEFINE_TYPE_CASTS(AXObjectCacheImpl, AXObjectCache, cache, true, true);
+template <>
+struct DowncastTraits<AXObjectCacheImpl> {
+  static bool AllowFrom(const AXObjectCache& cache) { return true; }
+};
 
 // This will let you know if aria-hidden was explicitly set to false.
 bool IsNodeAriaVisible(Node*);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
index 00f23560..bfc50ab1 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.cc
@@ -79,8 +79,6 @@
     switch (attribute_) {
       case AXObjectAttribute::kAriaActiveDescendant:
         return html_names::kAriaActivedescendantAttr;
-      case AXObjectAttribute::kAriaDetails:
-        return html_names::kAriaDetailsAttr;
       case AXObjectAttribute::kAriaErrorMessage:
         return html_names::kAriaErrormessageAttr;
       default:
@@ -120,6 +118,8 @@
     switch (attribute_) {
       case AXObjectVectorAttribute::kAriaControls:
         return html_names::kAriaControlsAttr;
+      case AXObjectVectorAttribute::kAriaDetails:
+        return html_names::kAriaDetailsAttr;
       case AXObjectVectorAttribute::kAriaFlowTo:
         return html_names::kAriaFlowtoAttr;
       default:
@@ -175,7 +175,7 @@
         new ObjectVectorAttributeSetter(AXObjectVectorAttribute::kAriaFlowTo));
     ax_sparse_attribute_setter_map.Set(
         html_names::kAriaDetailsAttr,
-        new ObjectAttributeSetter(AXObjectAttribute::kAriaDetails));
+        new ObjectVectorAttributeSetter(AXObjectVectorAttribute::kAriaDetails));
     ax_sparse_attribute_setter_map.Set(
         html_names::kAriaErrormessageAttr,
         new ObjectAttributeSetter(AXObjectAttribute::kAriaErrorMessage));
@@ -260,9 +260,6 @@
     case AOMRelationProperty::kActiveDescendant:
       attribute = AXObjectAttribute::kAriaActiveDescendant;
       break;
-    case AOMRelationProperty::kDetails:
-      attribute = AXObjectAttribute::kAriaDetails;
-      break;
     case AOMRelationProperty::kErrorMessage:
       attribute = AXObjectAttribute::kAriaErrorMessage;
       break;
@@ -284,6 +281,9 @@
     case AOMRelationListProperty::kControls:
       attribute = AXObjectVectorAttribute::kAriaControls;
       break;
+    case AOMRelationListProperty::kDetails:
+      attribute = AXObjectVectorAttribute::kAriaDetails;
+      break;
     case AOMRelationListProperty::kFlowTo:
       attribute = AXObjectVectorAttribute::kAriaFlowTo;
       break;
diff --git a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
index 349c28b..a0f09b8 100644
--- a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
+++ b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -432,10 +432,6 @@
             CreateProperty(AXPropertyNameEnum::Activedescendant,
                            CreateRelatedNodeListValue(object)));
         break;
-      case AXObjectAttribute::kAriaDetails:
-        properties_.emplace_back(CreateProperty(
-            AXPropertyNameEnum::Details, CreateRelatedNodeListValue(object)));
-        break;
       case AXObjectAttribute::kAriaErrorMessage:
         properties_.emplace_back(
             CreateProperty(AXPropertyNameEnum::Errormessage,
@@ -453,6 +449,11 @@
             AXPropertyNameEnum::Controls, objects,
             html_names::kAriaControlsAttr, *ax_object_));
         break;
+      case AXObjectVectorAttribute::kAriaDetails:
+        properties_.emplace_back(CreateRelatedNodeListProperty(
+            AXPropertyNameEnum::Details, objects, html_names::kAriaDetailsAttr,
+            *ax_object_));
+        break;
       case AXObjectVectorAttribute::kAriaFlowTo:
         properties_.emplace_back(CreateRelatedNodeListProperty(
             AXPropertyNameEnum::Flowto, objects, html_names::kAriaFlowtoAttr,
@@ -533,7 +534,7 @@
   if (!local_frame)
     return Response::Error("Frame is detached.");
   AXContext ax_context(document);
-  AXObjectCacheImpl& cache = ToAXObjectCacheImpl(ax_context.GetAXObjectCache());
+  auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
 
   AXObject* inspected_ax_object = cache.GetOrCreate(dom_node);
   *nodes = std::make_unique<protocol::Array<protocol::Accessibility::AXNode>>();
@@ -722,7 +723,7 @@
     document->UpdateStyleAndLayout();
   *nodes = std::make_unique<protocol::Array<protocol::Accessibility::AXNode>>();
   AXContext ax_context(*document);
-  AXObjectCacheImpl& cache = ToAXObjectCacheImpl(ax_context.GetAXObjectCache());
+  auto& cache = To<AXObjectCacheImpl>(ax_context.GetAXObjectCache());
   Deque<AXID> ids;
   ids.emplace_back(cache.Root()->AXObjectID());
   while (!ids.empty()) {
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
index 088088f..398555c1 100644
--- a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
@@ -25,7 +25,7 @@
 
 AXObjectCacheImpl& AccessibilityTest::GetAXObjectCache() const {
   auto* ax_object_cache =
-      ToAXObjectCacheImpl(GetDocument().ExistingAXObjectCache());
+      To<AXObjectCacheImpl>(GetDocument().ExistingAXObjectCache());
   DCHECK(ax_object_cache);
   return *ax_object_cache;
 }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
index 466ff0c1..afd10b83 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
@@ -338,8 +338,8 @@
   context->rect(10, 10, 40, 40);
   context->addHitRegion(options, exception_state);
 
-  AXObjectCacheImpl* ax_object_cache =
-      ToAXObjectCacheImpl(GetDocument().ExistingAXObjectCache());
+  auto* ax_object_cache =
+      To<AXObjectCacheImpl>(GetDocument().ExistingAXObjectCache());
   AXObject* ax_object = ax_object_cache->GetOrCreate(button_element);
 
   LayoutRect ax_bounds = ax_object->GetBoundsInFrameCoordinates();
@@ -365,8 +365,8 @@
   context->rect(10, 10, 40, 40);
   context->drawFocusIfNeeded(button_element);
 
-  AXObjectCacheImpl* ax_object_cache =
-      ToAXObjectCacheImpl(GetDocument().ExistingAXObjectCache());
+  auto* ax_object_cache =
+      To<AXObjectCacheImpl>(GetDocument().ExistingAXObjectCache());
   AXObject* ax_object = ax_object_cache->GetOrCreate(button_element);
 
   LayoutRect ax_bounds = ax_object->GetBoundsInFrameCoordinates();
diff --git a/third_party/blink/renderer/modules/clipboard/BUILD.gn b/third_party/blink/renderer/modules/clipboard/BUILD.gn
index 0b60478..26666e4 100644
--- a/third_party/blink/renderer/modules/clipboard/BUILD.gn
+++ b/third_party/blink/renderer/modules/clipboard/BUILD.gn
@@ -19,7 +19,5 @@
     "navigator_clipboard.cc",
     "navigator_clipboard.h",
   ]
-  deps = [
-    "//third_party/blink/public:blink_headers",
-  ]
+  deps = [ "//third_party/blink/public:blink_headers" ]
 }
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc
index b97800c56..4d06f1f9 100644
--- a/third_party/blink/renderer/modules/exported/web_ax_object.cc
+++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -1721,7 +1721,7 @@
 WebAXObject WebAXObject::FromWebNode(const WebNode& web_node) {
   WebDocument web_document = web_node.GetDocument();
   const Document* doc = web_document.ConstUnwrap<Document>();
-  AXObjectCacheImpl* cache = ToAXObjectCacheImpl(doc->ExistingAXObjectCache());
+  auto* cache = To<AXObjectCacheImpl>(doc->ExistingAXObjectCache());
   const Node* node = web_node.ConstUnwrap<Node>();
   return cache ? WebAXObject(cache->Get(node)) : WebAXObject();
 }
@@ -1729,8 +1729,7 @@
 // static
 WebAXObject WebAXObject::FromWebDocument(const WebDocument& web_document) {
   const Document* document = web_document.ConstUnwrap<Document>();
-  AXObjectCacheImpl* cache =
-      ToAXObjectCacheImpl(document->ExistingAXObjectCache());
+  auto* cache = To<AXObjectCacheImpl>(document->ExistingAXObjectCache());
   return cache ? WebAXObject(cache->GetOrCreate(document->GetLayoutView()))
                : WebAXObject();
 }
@@ -1739,8 +1738,7 @@
 WebAXObject WebAXObject::FromWebDocumentByID(const WebDocument& web_document,
                                              int ax_id) {
   const Document* document = web_document.ConstUnwrap<Document>();
-  AXObjectCacheImpl* cache =
-      ToAXObjectCacheImpl(document->ExistingAXObjectCache());
+  auto* cache = To<AXObjectCacheImpl>(document->ExistingAXObjectCache());
   return cache ? WebAXObject(cache->ObjectFromAXID(ax_id)) : WebAXObject();
 }
 
@@ -1748,8 +1746,7 @@
 WebAXObject WebAXObject::FromWebDocumentFocused(
     const WebDocument& web_document) {
   const Document* document = web_document.ConstUnwrap<Document>();
-  AXObjectCacheImpl* cache =
-      ToAXObjectCacheImpl(document->ExistingAXObjectCache());
+  auto* cache = To<AXObjectCacheImpl>(document->ExistingAXObjectCache());
   return cache ? WebAXObject(cache->FocusedObject()) : WebAXObject();
 }
 
diff --git a/third_party/blink/renderer/modules/hid/BUILD.gn b/third_party/blink/renderer/modules/hid/BUILD.gn
index 67e6cfec..bd73c19 100644
--- a/third_party/blink/renderer/modules/hid/BUILD.gn
+++ b/third_party/blink/renderer/modules/hid/BUILD.gn
@@ -27,9 +27,7 @@
 
 jumbo_source_set("unit_tests") {
   testonly = true
-  sources = [
-    "hid_report_item_test.cc",
-  ]
+  sources = [ "hid_report_item_test.cc" ]
 
   configs += [
     "//third_party/blink/renderer:config",
diff --git a/third_party/blink/renderer/modules/native_file_system/BUILD.gn b/third_party/blink/renderer/modules/native_file_system/BUILD.gn
index deeeef25..c248e70 100644
--- a/third_party/blink/renderer/modules/native_file_system/BUILD.gn
+++ b/third_party/blink/renderer/modules/native_file_system/BUILD.gn
@@ -26,16 +26,12 @@
     "window_native_file_system.h",
   ]
 
-  deps = [
-    "//third_party/blink/renderer/platform",
-  ]
+  deps = [ "//third_party/blink/renderer/platform" ]
 }
 
 jumbo_source_set("unit_tests") {
   testonly = true
-  sources = [
-    "window_native_file_system_test.cc",
-  ]
+  sources = [ "window_native_file_system_test.cc" ]
 
   configs += [
     "//third_party/blink/renderer:config",
diff --git a/third_party/blink/renderer/modules/payments/BUILD.gn b/third_party/blink/renderer/modules/payments/BUILD.gn
index 7a61f0375..b10aa369 100644
--- a/third_party/blink/renderer/modules/payments/BUILD.gn
+++ b/third_party/blink/renderer/modules/payments/BUILD.gn
@@ -62,7 +62,5 @@
     ]
   }
 
-  deps = [
-    "//components/payments/mojom:mojom_blink",
-  ]
+  deps = [ "//components/payments/mojom:mojom_blink" ]
 }
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index 478d187..7f84b3f 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -232,6 +232,7 @@
     if (supported) {
       resolver_->Resolve();
     } else {
+      DVLOG(2) << __func__ << ": session is unsupported - throwing exception";
       RejectWithDOMException(DOMExceptionCode::kNotSupportedError,
                              kSessionNotSupported, exception_state);
     }
@@ -647,6 +648,9 @@
 
   if (session_mode == device::mojom::blink::XRSessionMode::kImmersiveAr &&
       !RuntimeEnabledFeatures::WebXRARModuleEnabled(doc)) {
+    DVLOG(2) << __func__
+             << ": Immersive AR session is only supported if WebXRARModule "
+                "feature is enabled";
     query->Resolve(false);
     return promise;
   }
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index ee72e69..1f36e0e 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -455,6 +455,9 @@
 virtual/controls-refresh/color-scheme/suggestion-picker/datetimelocal-suggestion-picker-appearance.html [ Failure ]
 virtual/controls-refresh/color-scheme/suggestion-picker/time-suggestion-picker-appearance.html [ Failure ]
 
+# FlexNG depends on LayoutNG.
+crbug.com/845235 virtual/layout_ng_flex_box/* [ Skip ]
+
 # MathML depends on LayoutNG.
 crbug.com/6606 external/wpt/mathml/* [ Skip ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 2944d05..0e84fd0a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1327,7 +1327,6 @@
 crbug.com/845235 virtual/layout_ng_flex_box/css3/flexbox/negative-overflow.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/css3/flexbox/overflow-auto-resizes-correctly.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/css3/flexbox/relpos-with-percentage-top.html [ Failure ]
-crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flexbox_inline.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-004.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-012.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-015.html [ Failure ]
@@ -1336,25 +1335,11 @@
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/percentage-heights-quirks-node.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/quirks-auto-block-size-with-percentage-item.html [ Pass Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/table-as-item-auto-min-width.html [ Failure ]
-crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/css-flexbox/ttwf-reftest-flex-inline.html [ Failure ]
 crbug.com/845235 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003.html [ Failure ]
 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 ]
-crbug.com/1038467 virtual/layout_ng_flex_box/css3/flexbox/flexbox-baseline.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/css3/flexbox/flexbox-baseline-margins.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-003.xhtml [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-align-self-baseline-horiz-001.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-horiz-001a.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-horiz-001b.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-horiz-001.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-horiz-002.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-vert-001.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-line-vert-002.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-single-item-001a.html [ Failure ]
-crbug.com/1038467 virtual/layout_ng_flex_box/external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-single-item-001b.html [ 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/accessibility/aom-relation-list-properties.html b/third_party/blink/web_tests/accessibility/aom-relation-list-properties.html
index 901fc49..a32eaeb 100644
--- a/third_party/blink/web_tests/accessibility/aom-relation-list-properties.html
+++ b/third_party/blink/web_tests/accessibility/aom-relation-list-properties.html
@@ -185,6 +185,47 @@
 }, "AccessibleNode.flowTo");
 </script>
 
+<h1 id="elem1" aria-details="elem2 elem3"></h1>
+
+<div id="elem2">Content 2</div>
+<div id="elem3">Content 3</div>
+<div id="elem4">Content 4</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+test(function(t) {
+    var axElem1 = accessibilityController.accessibleElementById("elem1");
+    var axElem2 = accessibilityController.accessibleElementById("elem2");
+    var axElem3 = accessibilityController.accessibleElementById("elem3");
+    var axElem4 = accessibilityController.accessibleElementById("elem4");
+
+    assert_true(axElem1.ariaDetailsElementAtIndex(0).isEqual(axElem2));
+    assert_true(axElem1.ariaDetailsElementAtIndex(1).isEqual(axElem3));
+
+    var elem1 = document.getElementById("elem1");
+    var elem2 = document.getElementById("elem2");
+    var elem3 = document.getElementById("elem3");
+    var elem4 = document.getElementById("elem4");
+
+    elem1.accessibleNode.details = new AccessibleNodeList();
+    elem1.accessibleNode.details.add(elem4.accessibleNode);
+
+    assert_true(axElem1.ariaDetailsElementAtIndex(0).isEqual(axElem2));
+    assert_true(axElem1.ariaDetailsElementAtIndex(1).isEqual(axElem3));
+
+    elem1.accessibleNode.details.add(elem2.accessibleNode);
+
+    assert_true(axElem1.ariaDetailsElementAtIndex(1).isEqual(axElem3));
+
+    elem1.accessibleNode.details = null;
+
+    assert_true(axElem1.ariaDetailsElementAtIndex(0).isEqual(axElem2));
+    assert_true(axElem1.ariaDetailsElementAtIndex(1).isEqual(axElem3));
+}, "AccessibleNode.details");
+</script>
+
 <div class="container">
     <ul id="list1" role="listbox" aria-owns="listitem3">
         <li role="option">One</li>
diff --git a/third_party/blink/web_tests/accessibility/aom-relation-properties.html b/third_party/blink/web_tests/accessibility/aom-relation-properties.html
index e5a58e36..29f8dc9 100644
--- a/third_party/blink/web_tests/accessibility/aom-relation-properties.html
+++ b/third_party/blink/web_tests/accessibility/aom-relation-properties.html
@@ -44,23 +44,6 @@
 }, "AccessibleNode.activeDescendant");
 </script>
 
-<input id="input1">
-<div id="details">Details</div>
-
-<script>
-test(function(t) {
-    var input1 = document.getElementById("input1");
-    var details = document.getElementById("details");
-    var axInput1 = accessibilityController.accessibleElementById("input1");
-    var axDetails = accessibilityController.accessibleElementById("details");
-    assert_equals(axInput1.ariaDetailsElement(), undefined);
-
-    input1.accessibleNode.details = details.accessibleNode;
-
-    assert_equals(axInput1.ariaDetailsElement(), undefined);
-}, "AccessibleNode.details");
-</script>
-
 <input id="input2">
 <div id="errorMessage">ErrorMessage</div>
 
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/ElementInternals-accessibility.html b/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/ElementInternals-accessibility.html
index c98d771..b07320b 100644
--- a/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/ElementInternals-accessibility.html
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/form-associated/ElementInternals-accessibility.html
@@ -36,7 +36,7 @@
   "ariaControlsElements",
   "ariaCurrent",
   "ariaDescribedByElements",
-  "ariaDetailsElement",
+  "ariaDetailsElements",
   "ariaDisabled",
   "ariaErrorMessageElement",
   "ariaExpanded",
diff --git a/third_party/blink/web_tests/external/wpt/dom/nodes/aria-element-reflection.tentative.html b/third_party/blink/web_tests/external/wpt/dom/nodes/aria-element-reflection.tentative.html
index b4e22f0..9073e520 100644
--- a/third_party/blink/web_tests/external/wpt/dom/nodes/aria-element-reflection.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/dom/nodes/aria-element-reflection.tentative.html
@@ -147,11 +147,11 @@
   <script>
 
   test(function(t) {
-    assert_equals(passwordField.ariaDetailsElement, null);
-    passwordField.ariaDetailsElement = listItem1;
+    assert_equals(passwordField.ariaDetailsElements, null);
+    passwordField.ariaDetailsElements = [ listItem1 ];
     assert_equals(passwordField.getAttribute("aria-details"), "listItem1");
 
-    passwordField.ariaDetailsElement = listItem2;
+    passwordField.ariaDetailsElements = [ listItem2 ];
     assert_equals(passwordField.getAttribute("aria-details"), "listItem2");
   }, "aria-details");
   </script>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wai-aria.idl b/third_party/blink/web_tests/external/wpt/interfaces/wai-aria.idl
index c4fbf11..9cae4025 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/wai-aria.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/wai-aria.idl
@@ -21,7 +21,7 @@
   attribute FrozenArray<Element>? ariaControlsElements;
   attribute DOMString? ariaCurrent;
   attribute FrozenArray<Element>? ariaDescribedByElements;
-  attribute Element? ariaDetailsElement;
+  attribute Element? ariaDetailsElements;
   attribute DOMString? ariaDisabled;
   attribute Element? ariaErrorMessageElement;
   attribute DOMString? ariaExpanded;
diff --git a/third_party/blink/web_tests/fast/files/mp3-mime-type.html b/third_party/blink/web_tests/fast/files/mp3-mime-type.html
new file mode 100644
index 0000000..3b1c196a
--- /dev/null
+++ b/third_party/blink/web_tests/fast/files/mp3-mime-type.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<head>
+  <script src="../../resources/testharness.js"></script>
+  <script src="../../resources/testharnessreport.js"></script>
+</head>
+<body>
+  <iframe id="formiframe" name="formiframe"></iframe>
+  <form target="formiframe" id="myform" action="/forms/resources/return-content-type.php" enctype="multipart/form-data" method="post">
+    <input type="text" name="textinput" value="hello world">
+    <input type="file" name="fileinput" id="fileinput">
+    <input type="submit">
+  </form>
+  <script>
+    window.test(() => {
+      if (!window.eventSender)
+        return;
+      const fileinput = document.getElementById('fileinput');
+      window.eventSender.beginDragWithFiles(['resources/sound_0.mp3']);
+      const centerx = fileinput.offsetLeft + fileinput.offsetWidth / 2;
+      const centery = fileinput.offsetTop + fileinput.offsetHeight / 2;
+      window.eventSender.mouseMoveTo(centerx, centery);
+      window.eventSender.mouseUp();
+      assert_equals(fileinput.files[0].type, 'audio/mpeg');
+    });
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/fast/files/resources/sound_0.mp3 b/third_party/blink/web_tests/fast/files/resources/sound_0.mp3
new file mode 100644
index 0000000..a15d1de
--- /dev/null
+++ b/third_party/blink/web_tests/fast/files/resources/sound_0.mp3
Binary files differ
diff --git a/third_party/blink/web_tests/inspector-protocol/accessibility/accessibility-aria-1.1-expected.txt b/third_party/blink/web_tests/inspector-protocol/accessibility/accessibility-aria-1.1-expected.txt
index 324f42d..88e85c5 100644
--- a/third_party/blink/web_tests/inspector-protocol/accessibility/accessibility-aria-1.1-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/accessibility/accessibility-aria-1.1-expected.txt
@@ -144,7 +144,8 @@
     {
       "name": "details",
       "value": {
-        "type": "idref",
+        "type": "idrefList",
+        "value": "d",
         "relatedNodes": [
           {
             "idref": "d",
diff --git a/third_party/blink/web_tests/resize-observer/notifications-delivered-in-order.html b/third_party/blink/web_tests/resize-observer/notifications-delivered-in-order.html
new file mode 100644
index 0000000..0927a5fe
--- /dev/null
+++ b/third_party/blink/web_tests/resize-observer/notifications-delivered-in-order.html
@@ -0,0 +1,25 @@
+<!doctype HTML>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+
+<style>
+  div {
+    width: 100px;
+    height: 100px;
+  }
+</style>
+<div id="observeme"></div>
+
+<script>
+test(() => {
+  let previousNum = 0;
+  for (let i = 1; i < 50; ++i) {
+    new ResizeObserver(function() {
+      assert_equals(previousNum + 1, i);
+      previousNum = i;
+    }).observe(observeme);
+  }
+  observeme.style.height = "110px";
+}, "ResizeObserver notifications are delivered in order.");
+</script>
+
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
index 6e498b5..ba59d4c 100644
--- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -41,7 +41,7 @@
     property ariaControlsElements
     property ariaCurrent
     property ariaDescribedByElements
-    property ariaDetailsElement
+    property ariaDetailsElements
     property ariaDisabled
     property ariaErrorMessageElement
     property ariaExpanded
@@ -1241,7 +1241,7 @@
     property ariaControlsElements
     property ariaCurrent
     property ariaDescribedByElements
-    property ariaDetailsElement
+    property ariaDetailsElements
     property ariaDisabled
     property ariaErrorMessageElement
     property ariaExpanded
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 366dce3..74c2984e 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
@@ -1998,7 +1998,7 @@
     getter ariaControlsElements
     getter ariaCurrent
     getter ariaDescribedByElements
-    getter ariaDetailsElement
+    getter ariaDetailsElements
     getter ariaDisabled
     getter ariaErrorMessageElement
     getter ariaExpanded
@@ -2141,7 +2141,7 @@
     setter ariaControlsElements
     setter ariaCurrent
     setter ariaDescribedByElements
-    setter ariaDetailsElement
+    setter ariaDetailsElements
     setter ariaDisabled
     setter ariaErrorMessageElement
     setter ariaExpanded
@@ -2208,7 +2208,7 @@
     getter ariaControlsElements
     getter ariaCurrent
     getter ariaDescribedByElements
-    getter ariaDetailsElement
+    getter ariaDetailsElements
     getter ariaDisabled
     getter ariaErrorMessageElement
     getter ariaExpanded
@@ -2264,7 +2264,7 @@
     setter ariaControlsElements
     setter ariaCurrent
     setter ariaDescribedByElements
-    setter ariaDetailsElement
+    setter ariaDetailsElements
     setter ariaDisabled
     setter ariaErrorMessageElement
     setter ariaExpanded
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index 22c70b3..07968149 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -769,8 +769,8 @@
 chrome.automation.AutomationNode.prototype.inPageLinkTarget;
 
 /**
- * A node that provides more details about the current node.
- * @type {(!chrome.automation.AutomationNode|undefined)}
+ * The nodes, if any that provide more details about the current node.
+ * @type {(!Array<!chrome.automation.AutomationNode>|undefined)}
  * @see https://developer.chrome.com/extensions/automation#type-details
  */
 chrome.automation.AutomationNode.prototype.details;
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn
index f937e23a..96c194f 100644
--- a/third_party/grpc/BUILD.gn
+++ b/third_party/grpc/BUILD.gn
@@ -111,9 +111,7 @@
       "//build/config/compiler:no_chromium_code",
     ]
     public_configs = [ ":grpc_config" ]
-    deps = [
-      "//third_party/protobuf:protoc_lib",
-    ]
+    deps = [ "//third_party/protobuf:protoc_lib" ]
   }
 }
 
@@ -506,9 +504,7 @@
     ":nanopb",
     "//third_party/boringssl",
   ]
-  public_deps = [
-    "//third_party/zlib",
-  ]
+  public_deps = [ "//third_party/zlib" ]
 }
 
 static_library("nanopb") {
@@ -570,9 +566,7 @@
 }
 
 fuzzer_test("grpc_alts_credentials_fuzzer") {
-  sources = [
-    "src/test/core/security/alts_credentials_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/security/alts_credentials_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -588,9 +582,7 @@
 }
 
 fuzzer_test("grpc_api_fuzzer") {
-  sources = [
-    "src/test/core/end2end/fuzzers/api_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/end2end/fuzzers/api_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -607,9 +599,7 @@
 }
 
 fuzzer_test("grpc_client_fuzzer") {
-  sources = [
-    "src/test/core/end2end/fuzzers/client_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/end2end/fuzzers/client_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -626,9 +616,7 @@
 }
 
 fuzzer_test("grpc_hpack_parser_fuzzer_test") {
-  sources = [
-    "src/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc",
-  ]
+  sources = [ "src/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -644,9 +632,7 @@
 }
 
 fuzzer_test("grpc_request_fuzzer") {
-  sources = [
-    "src/test/core/http/request_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/http/request_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -662,9 +648,7 @@
 }
 
 fuzzer_test("grpc_response_fuzzer") {
-  sources = [
-    "src/test/core/http/response_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/http/response_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -680,9 +664,7 @@
 }
 
 fuzzer_test("grpc_json_fuzzer") {
-  sources = [
-    "src/test/core/json/fuzzer.cc",
-  ]
+  sources = [ "src/test/core/json/fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -698,9 +680,7 @@
 }
 
 fuzzer_test("grpc_nanopb_fuzzer_response") {
-  sources = [
-    "src/test/core/nanopb/fuzzer_response.cc",
-  ]
+  sources = [ "src/test/core/nanopb/fuzzer_response.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -716,9 +696,7 @@
 }
 
 fuzzer_test("grpc_nanopb_fuzzer_serverlist") {
-  sources = [
-    "src/test/core/nanopb/fuzzer_serverlist.cc",
-  ]
+  sources = [ "src/test/core/nanopb/fuzzer_serverlist.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -734,9 +712,7 @@
 }
 
 fuzzer_test("grpc_percent_decode_fuzzer") {
-  sources = [
-    "src/test/core/slice/percent_decode_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/slice/percent_decode_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -752,9 +728,7 @@
 }
 
 fuzzer_test("grpc_percent_encode_fuzzer") {
-  sources = [
-    "src/test/core/slice/percent_encode_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/slice/percent_encode_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -770,9 +744,7 @@
 }
 
 fuzzer_test("grpc_server_fuzzer") {
-  sources = [
-    "src/test/core/end2end/fuzzers/server_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/end2end/fuzzers/server_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -788,9 +760,7 @@
 }
 
 fuzzer_test("grpc_ssl_server_fuzzer") {
-  sources = [
-    "src/test/core/security/ssl_server_fuzzer.cc",
-  ]
+  sources = [ "src/test/core/security/ssl_server_fuzzer.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
@@ -806,9 +776,7 @@
 }
 
 fuzzer_test("grpc_uri_fuzzer_test") {
-  sources = [
-    "src/test/core/client_channel/uri_fuzzer_test.cc",
-  ]
+  sources = [ "src/test/core/client_channel/uri_fuzzer_test.cc" ]
   deps = [
     ":grpc_core",
     ":grpc_test_util",
diff --git a/third_party/leveldatabase/BUILD.gn b/third_party/leveldatabase/BUILD.gn
index 4f78167..1f2ba34 100644
--- a/third_party/leveldatabase/BUILD.gn
+++ b/third_party/leveldatabase/BUILD.gn
@@ -181,9 +181,7 @@
 
 if (!is_ios && !is_android) {
   test("env_chromium_unittests") {
-    sources = [
-      "env_chromium_unittest.cc",
-    ]
+    sources = [ "env_chromium_unittest.cc" ]
     deps = [
       ":leveldatabase",
       "//base/test:test_support",
@@ -210,42 +208,28 @@
       "//third_party/googletest:gmock",
       "//third_party/googletest:gtest",
     ]
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
   }
 
   test("leveldb_arena_test") {
-    sources = [
-      "src/util/arena_test.cc",
-    ]
+    sources = [ "src/util/arena_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_bloom_test") {
-    sources = [
-      "src/util/bloom_test.cc",
-    ]
+    sources = [ "src/util/bloom_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_cache_test") {
-    sources = [
-      "src/util/cache_test.cc",
-    ]
+    sources = [ "src/util/cache_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
 
     if (is_win) {
       # util\cache_test.cc(167): warning C4018: '<': signed/unsigned mismatch
@@ -255,69 +239,45 @@
   }
 
   test("leveldb_corruption_test") {
-    sources = [
-      "src/db/corruption_test.cc",
-    ]
+    sources = [ "src/db/corruption_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_crc32c_test") {
-    sources = [
-      "src/util/crc32c_test.cc",
-    ]
+    sources = [ "src/util/crc32c_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_db_bench") {
-    sources = [
-      "src/benchmarks/db_bench.cc",
-    ]
+    sources = [ "src/benchmarks/db_bench.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_db_test") {
-    sources = [
-      "src/db/db_test.cc",
-    ]
+    sources = [ "src/db/db_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_dbformat_test") {
-    sources = [
-      "src/db/dbformat_test.cc",
-    ]
+    sources = [ "src/db/dbformat_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_env_test") {
-    sources = [
-      "src/util/env_test.cc",
-    ]
+    sources = [ "src/util/env_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
 
     if (is_win) {
       cflags = [ "/wd4018" ]  # Signed/unsigned mismatch in comparison.
@@ -325,47 +285,31 @@
   }
 
   test("leveldb_filename_test") {
-    sources = [
-      "src/db/filename_test.cc",
-    ]
+    sources = [ "src/db/filename_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_filter_block_test") {
-    sources = [
-      "src/table/filter_block_test.cc",
-    ]
+    sources = [ "src/table/filter_block_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   executable("leveldb_leveldbutil") {
-    sources = [
-      "src/db/leveldbutil.cc",
-    ]
+    sources = [ "src/db/leveldbutil.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_static",
-    ]
+    deps = [ ":leveldb_static" ]
   }
 
   test("leveldb_log_test") {
-    sources = [
-      "src/db/log_test.cc",
-    ]
+    sources = [ "src/db/log_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
 
     if (is_win) {
       # db\log_test.cc(486) triggers two warnings:
@@ -376,47 +320,31 @@
   }
 
   test("leveldb_skiplist_test") {
-    sources = [
-      "src/db/skiplist_test.cc",
-    ]
+    sources = [ "src/db/skiplist_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_table_test") {
-    sources = [
-      "src/table/table_test.cc",
-    ]
+    sources = [ "src/table/table_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_version_edit_test") {
-    sources = [
-      "src/db/version_edit_test.cc",
-    ]
+    sources = [ "src/db/version_edit_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   test("leveldb_write_batch_test") {
-    sources = [
-      "src/db/write_batch_test.cc",
-    ]
+    sources = [ "src/db/write_batch_test.cc" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
-    deps = [
-      ":leveldb_testutil",
-    ]
+    deps = [ ":leveldb_testutil" ]
   }
 
   group("leveldb_test_targets") {
@@ -444,10 +372,6 @@
 }
 
 fuzzer_test("leveldb_put_get_delete_fuzzer") {
-  sources = [
-    "leveldb_put_get_delete_fuzzer.cc",
-  ]
-  deps = [
-    ":leveldatabase",
-  ]
+  sources = [ "leveldb_put_get_delete_fuzzer.cc" ]
+  deps = [ ":leveldatabase" ]
 }
diff --git a/third_party/libaddressinput/BUILD.gn b/third_party/libaddressinput/BUILD.gn
index 8631f982..803c342a 100644
--- a/third_party/libaddressinput/BUILD.gn
+++ b/third_party/libaddressinput/BUILD.gn
@@ -170,13 +170,9 @@
 if (is_ios) {
   bundle_data("countryinfo_test_bundle_data") {
     testonly = true
-    sources = [
-      "//third_party/libaddressinput/src/testdata/countryinfo.txt",
-    ]
-    outputs = [
-      "{{bundle_resources_dir}}/" +
-          "{{source_root_relative_dir}}/{{source_file_part}}",
-    ]
+    sources = [ "//third_party/libaddressinput/src/testdata/countryinfo.txt" ]
+    outputs = [ "{{bundle_resources_dir}}/" +
+                "{{source_root_relative_dir}}/{{source_file_part}}" ]
   }
 }
 
@@ -197,15 +193,11 @@
 
   defines = [ "TEST_DATA_DIR=\"src/third_party/libaddressinput/src/testdata\"" ]
 
-  data = [
-    "//third_party/libaddressinput/src/testdata/",
-  ]
+  data = [ "//third_party/libaddressinput/src/testdata/" ]
 
   include_dirs = [ "src/cpp/src" ]
 
-  deps = [
-    ":libaddressinput",
-  ]
+  deps = [ ":libaddressinput" ]
   if (is_ios) {
     deps += [ ":countryinfo_test_bundle_data" ]
   }
@@ -288,9 +280,7 @@
 }
 
 fuzzer_test("libaddressinput_parse_address_fields_fuzzer") {
-  sources = [
-    "fuzz/parse_address_fields_fuzzer.cc",
-  ]
+  sources = [ "fuzz/parse_address_fields_fuzzer.cc" ]
   deps = [
     ":libaddressinput",
     ":util",
@@ -299,9 +289,7 @@
 }
 
 fuzzer_test("libaddressinput_parse_format_rule_fuzzer") {
-  sources = [
-    "fuzz/parse_format_rule_fuzzer.cc",
-  ]
+  sources = [ "fuzz/parse_format_rule_fuzzer.cc" ]
   deps = [
     ":libaddressinput",
     ":util",
@@ -310,9 +298,7 @@
 }
 
 fuzzer_test("libaddressinput_address_formatter_fuzzer") {
-  sources = [
-    "fuzz/address_formatter_fuzzer.cc",
-  ]
+  sources = [ "fuzz/address_formatter_fuzzer.cc" ]
   deps = [
     ":libaddressinput",
     ":util",
diff --git a/third_party/minigbm/BUILD.gn b/third_party/minigbm/BUILD.gn
index 4060605..8e8c6259 100644
--- a/third_party/minigbm/BUILD.gn
+++ b/third_party/minigbm/BUILD.gn
@@ -94,9 +94,7 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
 
-    deps = [
-      "//build/config/linux/libdrm",
-    ]
+    deps = [ "//build/config/linux/libdrm" ]
     public_configs = [ ":minigbm_config" ]
 
     if (use_exynos_minigbm) {
@@ -111,9 +109,7 @@
   # This target is used for Chromecast build, which expects the resulting lib
   # to have a name <GN target name> + .so
   group("libminigbm") {
-    deps = [
-      ":minigbm",
-    ]
+    deps = [ ":minigbm" ]
   }
 }
 
diff --git a/third_party/qcms/BUILD.gn b/third_party/qcms/BUILD.gn
index 9cb511ce..81963b17 100644
--- a/third_party/qcms/BUILD.gn
+++ b/third_party/qcms/BUILD.gn
@@ -12,9 +12,7 @@
 
 static_library("qcms") {
   if (disable_qcms) {
-    sources = [
-      "src/empty.c",
-    ]
+    sources = [ "src/empty.c" ]
   } else {
     sources = [
       "src/chain.c",
diff --git a/third_party/tlslite/BUILD.gn b/third_party/tlslite/BUILD.gn
index 959b0b2..0b13774 100644
--- a/third_party/tlslite/BUILD.gn
+++ b/third_party/tlslite/BUILD.gn
@@ -6,7 +6,5 @@
 # to run tlslite in the test environment.
 group("tlslite") {
   # For now, depend on the entire directory.
-  data = [
-    "//third_party/tlslite/",
-  ]
+  data = [ "//third_party/tlslite/" ]
 }
diff --git a/third_party/yasm/BUILD.gn b/third_party/yasm/BUILD.gn
index 6e245fe..c6543a530 100644
--- a/third_party/yasm/BUILD.gn
+++ b/third_party/yasm/BUILD.gn
@@ -88,9 +88,7 @@
   }
 
   executable("genmacro") {
-    sources = [
-      "source/patched-yasm/tools/genmacro/genmacro.c",
-    ]
+    sources = [ "source/patched-yasm/tools/genmacro/genmacro.c" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [
       ":yasm_config",
@@ -103,9 +101,7 @@
   }
 
   executable("genmodule") {
-    sources = [
-      "source/patched-yasm/libyasm/genmodule.c",
-    ]
+    sources = [ "source/patched-yasm/libyasm/genmodule.c" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [
       ":yasm_config",
@@ -161,9 +157,7 @@
   }
 
   executable("genstring") {
-    sources = [
-      "source/patched-yasm/genstring.c",
-    ]
+    sources = [ "source/patched-yasm/genstring.c" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [
       ":yasm_config",
@@ -176,9 +170,7 @@
   }
 
   executable("genversion") {
-    sources = [
-      "source/patched-yasm/modules/preprocs/nasm/genversion.c",
-    ]
+    sources = [ "source/patched-yasm/modules/preprocs/nasm/genversion.c" ]
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [
       ":yasm_config",
@@ -391,9 +383,7 @@
       "source/patched-yasm/modules/arch/x86/x86regtmod.gperf",
     ]
 
-    outputs = [
-      "$target_gen_dir/{{source_name_part}}.c",
-    ]
+    outputs = [ "$target_gen_dir/{{source_name_part}}.c" ]
     args = [
       "{{source}}",
       rebase_path(target_gen_dir, root_build_dir) + "/{{source_name_part}}.c",
@@ -414,9 +404,7 @@
       "source/patched-yasm/x86insn_nasm.gperf",
     ]
 
-    outputs = [
-      "$yasm_gen_include_dir/{{source_name_part}}.c",
-    ]
+    outputs = [ "$yasm_gen_include_dir/{{source_name_part}}.c" ]
     args = [
       "{{source}}",
       rebase_path(yasm_gen_include_dir, root_build_dir) +
@@ -445,49 +433,31 @@
   compile_macro("compile_nasm_macros") {
     # Output #included by
     #   source/patched-yasm/modules/preprocs/nasm/nasm-parser.c
-    sources = [
-      "source/patched-yasm/modules/parsers/nasm/nasm-std.mac",
-    ]
-    outputs = [
-      "$yasm_gen_include_dir/nasm-macros.c",
-    ]
+    sources = [ "source/patched-yasm/modules/parsers/nasm/nasm-std.mac" ]
+    outputs = [ "$yasm_gen_include_dir/nasm-macros.c" ]
     macro_varname = "nasm_standard_mac"
   }
 
   compile_macro("compile_nasm_version") {
     # Output #included by
     #   source/patched-yasm/modules/preprocs/nasm/nasm-preproc.c
-    sources = [
-      "$target_gen_dir/$version_file",
-    ]
-    outputs = [
-      "$yasm_gen_include_dir/nasm-version.c",
-    ]
+    sources = [ "$target_gen_dir/$version_file" ]
+    outputs = [ "$yasm_gen_include_dir/nasm-version.c" ]
     macro_varname = "nasm_version_mac"
-    deps = [
-      ":generate_version",
-    ]
+    deps = [ ":generate_version" ]
   }
 
   compile_macro("compile_win64_gas") {
     # Output #included by source/patched-yasm/frontends/yasm/yasm.c.
-    sources = [
-      "source/patched-yasm/modules/objfmts/coff/win64-gas.mac",
-    ]
-    outputs = [
-      "$yasm_gen_include_dir/win64-gas.c",
-    ]
+    sources = [ "source/patched-yasm/modules/objfmts/coff/win64-gas.mac" ]
+    outputs = [ "$yasm_gen_include_dir/win64-gas.c" ]
     macro_varname = "win64_gas_stdmac"
   }
 
   compile_macro("compile_win64_nasm") {
     # Output #included by source/patched-yasm/frontends/yasm/yasm.c.
-    sources = [
-      "source/patched-yasm/modules/objfmts/coff/win64-nasm.mac",
-    ]
-    outputs = [
-      "$yasm_gen_include_dir/win64-nasm.c",
-    ]
+    sources = [ "source/patched-yasm/modules/objfmts/coff/win64-nasm.mac" ]
+    outputs = [ "$yasm_gen_include_dir/win64-nasm.c" ]
     macro_varname = "win64_nasm_stdmac"
   }
 
@@ -497,9 +467,7 @@
       "source/patched-yasm/modules/parsers/gas/gas-token.re",
       "source/patched-yasm/modules/parsers/nasm/nasm-token.re",
     ]
-    outputs = [
-      "$target_gen_dir/{{source_name_part}}.c",
-    ]
+    outputs = [ "$target_gen_dir/{{source_name_part}}.c" ]
     args = [
       "-b",
       "-o",
@@ -511,12 +479,8 @@
   # This call doesn't fit into the re2c template above.
   compiled_action("compile_re2c_lc3b") {
     tool = ":re2c"
-    inputs = [
-      "source/patched-yasm/modules/arch/lc3b/lc3bid.re",
-    ]
-    outputs = [
-      "$target_gen_dir/lc3bid.c",
-    ]
+    inputs = [ "source/patched-yasm/modules/arch/lc3b/lc3bid.re" ]
+    outputs = [ "$target_gen_dir/lc3bid.c" ]
     args = [
       "-s",
       "-o",
@@ -529,12 +493,8 @@
     tool = ":genstring"
 
     # Output #included by source/patched-yasm/frontends/yasm/yasm.c.
-    inputs = [
-      "source/patched-yasm/COPYING",
-    ]
-    outputs = [
-      "$yasm_gen_include_dir/license.c",
-    ]
+    inputs = [ "source/patched-yasm/COPYING" ]
+    outputs = [ "$yasm_gen_include_dir/license.c" ]
     args = [
       "license_msg",
       rebase_path(outputs[0], root_build_dir),
@@ -548,9 +508,7 @@
       "source/patched-yasm/libyasm/module.in",
       config_makefile,
     ]
-    outputs = [
-      "$target_gen_dir/module.c",
-    ]
+    outputs = [ "$target_gen_dir/module.c" ]
     args = [
       rebase_path(inputs[0], root_build_dir),
       rebase_path(config_makefile, root_build_dir),
@@ -560,9 +518,7 @@
 
   compiled_action("generate_version") {
     tool = ":genversion"
-    outputs = [
-      "$target_gen_dir/$version_file",
-    ]
+    outputs = [ "$target_gen_dir/$version_file" ]
     args = [ rebase_path(outputs[0], root_build_dir) ]
   }
 }
diff --git a/third_party/yasm/yasm_assemble.gni b/third_party/yasm/yasm_assemble.gni
index f94fa6b..9deddd0 100644
--- a/third_party/yasm/yasm_assemble.gni
+++ b/third_party/yasm/yasm_assemble.gni
@@ -123,9 +123,7 @@
                          root_build_dir) ]
 
     # Deps.
-    deps = [
-      yasm_label,
-    ]
+    deps = [ yasm_label ]
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
@@ -165,9 +163,7 @@
     }
 
     # Output file.
-    outputs = [
-      "$target_out_dir/$source_set_name/{{source_name_part}}.o",
-    ]
+    outputs = [ "$target_out_dir/$source_set_name/{{source_name_part}}.o" ]
     args += [
       "-o",
       rebase_path(outputs[0], root_build_dir),
@@ -192,8 +188,6 @@
     # Do not publicize any header to remove build dependency.
     public = []
 
-    deps = [
-      ":$action_name",
-    ]
+    deps = [ ":$action_name" ]
   }
 }
diff --git a/tools/binary_size/BUILD.gn b/tools/binary_size/BUILD.gn
index a9629c2..ad3019e 100644
--- a/tools/binary_size/BUILD.gn
+++ b/tools/binary_size/BUILD.gn
@@ -18,15 +18,11 @@
 python_library("sizes_py") {
   testonly = true
   pydeps_file = "sizes.pydeps"
-  data_deps = [
-    "//third_party/catapult/tracing:convert_chart_json",
-  ]
+  data_deps = [ "//third_party/catapult/tracing:convert_chart_json" ]
 }
 
 if (is_linux) {
   group("caspian") {
-    deps = [
-      "//tools/binary_size/libsupersize/caspian:cli($host_toolchain)",
-    ]
+    deps = [ "//tools/binary_size/libsupersize/caspian:cli($host_toolchain)" ]
   }
 }
diff --git a/tools/binary_size/libsupersize/caspian/BUILD.gn b/tools/binary_size/libsupersize/caspian/BUILD.gn
index dc48257..ebc0bcf 100644
--- a/tools/binary_size/libsupersize/caspian/BUILD.gn
+++ b/tools/binary_size/libsupersize/caspian/BUILD.gn
@@ -33,9 +33,7 @@
     "//third_party/zlib:zlib",
     "//third_party/zlib/google:compression_utils_portable",
   ]
-  public_deps = [
-    "//third_party/jsoncpp:jsoncpp",
-  ]
+  public_deps = [ "//third_party/jsoncpp:jsoncpp" ]
   configs -= [ "//build/config/compiler:default_optimization" ]
   configs += [ "//build/config/compiler:optimize_speed" ]
 }
@@ -57,20 +55,14 @@
 }
 
 executable("cli") {
-  sources = [
-    "cli.cc",
-  ]
-  deps = [
-    ":caspian-lib",
-  ]
+  sources = [ "cli.cc" ]
+  deps = [ ":caspian-lib" ]
   cflags = [ "-Wall" ]
 }
 
 if (is_wasm) {
   executable("caspian_web") {
-    sources = [
-      "caspian_web.cc",
-    ]
+    sources = [ "caspian_web.cc" ]
     deps = [
       ":caspian-lib",
       "//third_party/re2:re2",
diff --git a/tools/binary_size/sizes.gni b/tools/binary_size/sizes.gni
index c7213fc..83085dc 100644
--- a/tools/binary_size/sizes.gni
+++ b/tools/binary_size/sizes.gni
@@ -14,9 +14,7 @@
     executable = "//tools/binary_size/sizes.py"
     wrapper_script = "$root_out_dir/bin/run_${target_name}"
 
-    data_deps = [
-      "//tools/binary_size:sizes_py",
-    ]
+    data_deps = [ "//tools/binary_size:sizes_py" ]
     if (defined(invoker.data_deps)) {
       data_deps += invoker.data_deps
     }
diff --git a/tools/gritsettings/BUILD.gn b/tools/gritsettings/BUILD.gn
index 5d38372..ea3f2b6 100644
--- a/tools/gritsettings/BUILD.gn
+++ b/tools/gritsettings/BUILD.gn
@@ -7,15 +7,9 @@
 
 action("default_resource_ids") {
   script = "//tools/grit/grit.py"
-  inputs = [
-    "resource_ids.spec",
-  ]
-  outputs = [
-    grit_resource_id_file,
-  ]
-  deps = [
-    "//tools/grit:grit_sources",
-  ]
+  inputs = [ "resource_ids.spec" ]
+  outputs = [ grit_resource_id_file ]
+  deps = [ "//tools/grit:grit_sources" ]
   depfile = "$target_gen_dir/$target_name.d"
   _rebased_input = rebase_path(inputs[0], root_build_dir)
   args = [
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 1b82a685..9818660 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -16,11 +16,13 @@
     'chrome': {
       'chromeos-arm-generic-cfi-thin-lto-chrome': 'cros_chrome_sdk_cfi_thin_lto',
       'chromeos-betty-cfi-thin-lto-chrome': 'cros_chrome_sdk_cfi_thin_lto',
-      'chromeos-betty-chrome': 'cros_chrome_sdk',
-      'chromeos-betty-pi-arc-chrome': 'cros_chrome_sdk',
-      'chromeos-eve-chrome': 'cros_chrome_sdk',
-      'chromeos-kevin-chrome': 'cros_chrome_sdk',
-      'linux-chromeos-chrome': 'official_goma_chromeos_minimal_symbols',
+      'chromeos-betty-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-betty-pi-arc-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-eve-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-kevin-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'linux-chromeos-chrome': 'official_goma_chromeos_minimal_symbols_include_unwind_tables',
+      # Don't include unwind tables for the remaining three builders since
+      # they monitor binary size growth, which may be affected by the tables.
       'linux-chrome': 'official_goma',
       'mac-chrome': 'official_goma',
       'win-chrome': 'official_goma_x86',
@@ -747,14 +749,14 @@
     'tryserver.chrome': {
       'chromeos-arm-generic-cfi-thin-lto-chrome': 'cros_chrome_sdk_cfi_thin_lto',
       'chromeos-betty-cfi-thin-lto-chrome': 'cros_chrome_sdk_cfi_thin_lto',
-      'chromeos-betty-chrome': 'cros_chrome_sdk',
-      'chromeos-betty-pi-arc-chrome': 'cros_chrome_sdk',
-      'chromeos-eve-chrome': 'cros_chrome_sdk',
-      'chromeos-eve-compile-chrome': 'cros_chrome_sdk',
-      'chromeos-kevin-chrome': 'cros_chrome_sdk',
-      'chromeos-kevin-compile-chrome': 'cros_chrome_sdk',
+      'chromeos-betty-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-betty-pi-arc-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-eve-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-eve-compile-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-kevin-chrome': 'cros_chrome_sdk_include_unwind_tables',
+      'chromeos-kevin-compile-chrome': 'cros_chrome_sdk_include_unwind_tables',
       'linux-chrome': 'official_goma',
-      'linux-chromeos-chrome': 'official_goma_chromeos_minimal_symbols',
+      'linux-chromeos-chrome': 'official_goma_chromeos_minimal_symbols_include_unwind_tables',
       'win_chrome_official': 'official_goma_x86',
       'win-celab-try-rel': 'official_celab_release_bot',
     },
@@ -1511,6 +1513,10 @@
       'cros_chrome_sdk', 'cfi_full', 'thin_lto',
     ],
 
+    'cros_chrome_sdk_include_unwind_tables': [
+      'cros_chrome_sdk', 'include_unwind_tables',
+    ],
+
     'dawn_tests_release_trybot': [
       'dawn_tests', 'release_trybot',
     ],
@@ -1850,8 +1856,9 @@
       'official', 'goma', 'no_gnome_keyring',
     ],
 
-    'official_goma_chromeos_minimal_symbols': [
+    'official_goma_chromeos_minimal_symbols_include_unwind_tables': [
       'official', 'goma', 'chromeos', 'minimal_symbols',
+      'include_unwind_tables',
     ],
 
     'official_goma_minimal_symbols_android': [
@@ -2317,6 +2324,10 @@
       'mixins': ['disable_nacl'],
     },
 
+    'include_unwind_tables': {
+      'gn_args': 'exclude_unwind_tables=false',
+    },
+
     'incremental': {
       'gn_args': 'incremental_install=true',
     },
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 69ef8e3..d0d5f91 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -159709,6 +159709,9 @@
 
 <histogram name="UMA.Debug.EnableCrashUpload.DeferredStartUpAsyncTaskDuration"
     units="ms" expires_after="M77">
+  <obsolete>
+    No longer useful or monitored, removed 2020-01-06.
+  </obsolete>
   <owner>wnwen@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -159719,6 +159722,9 @@
 
 <histogram name="UMA.Debug.EnableCrashUpload.DeferredStartUpCompleteTime"
     units="ms" expires_after="M77">
+  <obsolete>
+    No longer useful or monitored, removed 2020-01-06.
+  </obsolete>
   <owner>wnwen@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -159729,6 +159735,9 @@
 
 <histogram name="UMA.Debug.EnableCrashUpload.DeferredStartUpDuration"
     units="ms" expires_after="M77">
+  <obsolete>
+    No longer useful or monitored, removed 2020-01-06.
+  </obsolete>
   <owner>wnwen@chromium.org</owner>
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
@@ -159754,6 +159763,9 @@
 
 <histogram name="UMA.Debug.EnableCrashUpload.DeferredStartUpMaxTaskDuration"
     units="ms" expires_after="2020-02-16">
+  <obsolete>
+    No longer useful or monitored, removed 2020-01-06.
+  </obsolete>
   <owner>wnwen@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -177432,7 +177444,10 @@
       label="From app list query context menu."/>
   <suffix name="FromAppListRecommendation"
       label="From app list recommendation."/>
+  <suffix name="FromChromeInternal" label="From Chrome Internal."/>
   <suffix name="FromFileManager" label="From FileManager."/>
+  <suffix name="FromLink" label="From Link."/>
+  <suffix name="FromOmnibox" label="From Omnibox."/>
   <suffix name="FromShelf" label="From shelf."/>
   <affected-histogram name="Apps.DefaultAppLaunch"/>
 </histogram_suffixes>
diff --git a/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py b/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
index 5a18103..8824e00 100644
--- a/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
+++ b/tools/perf/contrib/cluster_telemetry/ad_tagging_ct.py
@@ -23,10 +23,16 @@
   @classmethod
   def AddBenchmarkCommandLineArgs(cls, parser):
     ct_benchmarks_util.AddBenchmarkCommandLineArgs(parser)
+    parser.add_option(
+        '--verbose-cpu-metrics-for-adtagging',
+        action='store_true',
+        help='Enables non-UMA CPU metrics for the ad_tagging.cluster_telemetry '
+        'benchmark.')
 
   @classmethod
   def ProcessCommandLineArgs(cls, parser, args):
     ct_benchmarks_util.ValidateCommandLineArgs(parser, args)
+    cls.enable_limited_cpu_time_metric = args.verbose_cpu_metrics_for_adtagging
 
   def GetExtraOutDirectories(self):
     # The indexed filter list does not end up in a build directory on cluster
@@ -52,7 +58,11 @@
     for histogram in uma_histograms:
       tbm_options.config.chrome_trace_config.EnableUMAHistograms(histogram)
 
-    tbm_options.SetTimelineBasedMetrics(['umaMetric', 'cpuTimeMetric'])
+    timeline_based_metrics = ['umaMetric']
+    if self.enable_limited_cpu_time_metric:
+      timeline_based_metrics.append('limitedCpuTimeMetric')
+
+    tbm_options.SetTimelineBasedMetrics(timeline_based_metrics)
     return tbm_options
 
   def CreateStorySet(self, options):
diff --git a/tools/perf/core/minidump_unittest.py b/tools/perf/core/minidump_unittest.py
index 5bb282d..c374b92c 100644
--- a/tools/perf/core/minidump_unittest.py
+++ b/tools/perf/core/minidump_unittest.py
@@ -19,7 +19,7 @@
   # Minidump symbolization doesn't work in ChromeOS local mode if the rootfs is
   # still read-only, so skip the test in that case.
   # TODO(crbug.com/1038043): Test is failing on chromeos-betty-chrome.
-  @decorators.Disabled('chromeos-local', 'chromeos')
+  @decorators.Disabled('chromeos-local', 'chromeos-board-betty')
   def testSymbolizeMinidump(self):
     # Wait for the browser to restart fully before crashing
     self._LoadPageThenWait('var sam = "car";', 'sam')
@@ -60,7 +60,7 @@
   # Minidump symbolization doesn't work in ChromeOS local mode if the rootfs is
   # still read-only, so skip the test in that case.
   # TODO(crbug.com/1038043): Test is failing on chromeos-betty-chrome.
-  @decorators.Disabled('chromeos-local', 'chromeos')
+  @decorators.Disabled('chromeos-local', 'chromeos-board-betty')
   def testMultipleCrashMinidumps(self):
     # Wait for the browser to restart fully before crashing
     self._LoadPageThenWait('var cat = "dog";', 'cat')
diff --git a/tools/traffic_annotation/auditor/BUILD.gn b/tools/traffic_annotation/auditor/BUILD.gn
index bee4e1a8..93b312d 100644
--- a/tools/traffic_annotation/auditor/BUILD.gn
+++ b/tools/traffic_annotation/auditor/BUILD.gn
@@ -31,15 +31,11 @@
 }
 
 proto_library("traffic_annotation") {
-  sources = [
-    "../traffic_annotation.proto",
-  ]
+  sources = [ "../traffic_annotation.proto" ]
 
   import_dirs = [ "$root_gen_dir" + "/components/policy/proto" ]
 
-  deps = [
-    ":chrome_settings_full_runtime",
-  ]
+  deps = [ ":chrome_settings_full_runtime" ]
 
   use_protobuf_full = true
 }
@@ -78,18 +74,12 @@
 }
 
 executable("traffic_annotation_auditor") {
-  sources = [
-    "traffic_annotation_auditor_ui.cc",
-  ]
-  deps = [
-    ":auditor_sources",
-  ]
+  sources = [ "traffic_annotation_auditor_ui.cc" ]
+  deps = [ ":auditor_sources" ]
 }
 
 test("traffic_annotation_auditor_unittests") {
-  sources = [
-    "traffic_annotation_auditor_unittest.cc",
-  ]
+  sources = [ "traffic_annotation_auditor_unittest.cc" ]
   data = [
     "../summary/annotations.xml",
     "tests/annotations_diff12.txt",
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index 617b6265..be52001 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -1577,8 +1577,6 @@
       return "descriptionFrom";
     case ax::mojom::IntAttribute::kActivedescendantId:
       return "activedescendantId";
-    case ax::mojom::IntAttribute::kDetailsId:
-      return "detailsId";
     case ax::mojom::IntAttribute::kErrormessageId:
       return "errormessageId";
     case ax::mojom::IntAttribute::kInPageLinkTargetId:
@@ -1705,8 +1703,6 @@
     return ax::mojom::IntAttribute::kDescriptionFrom;
   if (0 == strcmp(int_attribute, "activedescendantId"))
     return ax::mojom::IntAttribute::kActivedescendantId;
-  if (0 == strcmp(int_attribute, "detailsId"))
-    return ax::mojom::IntAttribute::kDetailsId;
   if (0 == strcmp(int_attribute, "errormessageId"))
     return ax::mojom::IntAttribute::kErrormessageId;
   if (0 == strcmp(int_attribute, "inPageLinkTargetId"))
@@ -1894,6 +1890,8 @@
       return "indirectChildIds";
     case ax::mojom::IntListAttribute::kControlsIds:
       return "controlsIds";
+    case ax::mojom::IntListAttribute::kDetailsIds:
+      return "detailsIds";
     case ax::mojom::IntListAttribute::kDescribedbyIds:
       return "describedbyIds";
     case ax::mojom::IntListAttribute::kFlowtoIds:
@@ -1931,6 +1929,8 @@
     return ax::mojom::IntListAttribute::kIndirectChildIds;
   if (0 == strcmp(int_list_attribute, "controlsIds"))
     return ax::mojom::IntListAttribute::kControlsIds;
+  if (0 == strcmp(int_list_attribute, "detailsIds"))
+    return ax::mojom::IntListAttribute::kDetailsIds;
   if (0 == strcmp(int_list_attribute, "describedbyIds"))
     return ax::mojom::IntListAttribute::kDescribedbyIds;
   if (0 == strcmp(int_list_attribute, "flowtoIds"))
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 65499001..3a4b82f4 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -580,7 +580,6 @@
 
   // Relationships between this element and other elements.
   kActivedescendantId,
-  kDetailsId,
   kErrormessageId,
   kInPageLinkTargetId,
   kMemberOfId,
@@ -751,6 +750,7 @@
 
   // Relationships between this element and other elements.
   kControlsIds,
+  kDetailsIds,
   kDescribedbyIds,
   kFlowtoIds,
   kLabelledbyIds,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index e082d812..d1cf41a 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -97,7 +97,6 @@
 bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr) {
   switch (attr) {
     case ax::mojom::IntAttribute::kActivedescendantId:
-    case ax::mojom::IntAttribute::kDetailsId:
     case ax::mojom::IntAttribute::kErrormessageId:
     case ax::mojom::IntAttribute::kInPageLinkTargetId:
     case ax::mojom::IntAttribute::kMemberOfId:
@@ -175,6 +174,7 @@
 bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr) {
   switch (attr) {
     case ax::mojom::IntListAttribute::kControlsIds:
+    case ax::mojom::IntListAttribute::kDetailsIds:
     case ax::mojom::IntListAttribute::kDescribedbyIds:
     case ax::mojom::IntListAttribute::kFlowtoIds:
     case ax::mojom::IntListAttribute::kIndirectChildIds:
@@ -1104,9 +1104,6 @@
       case ax::mojom::IntAttribute::kActivedescendantId:
         result += " activedescendant=" + value;
         break;
-      case ax::mojom::IntAttribute::kDetailsId:
-        result += " details=" + value;
-        break;
       case ax::mojom::IntAttribute::kErrormessageId:
         result += " errormessage=" + value;
         break;
@@ -1534,6 +1531,9 @@
       case ax::mojom::IntListAttribute::kDescribedbyIds:
         result += " describedby_ids=" + IntVectorToString(values);
         break;
+      case ax::mojom::IntListAttribute::kDetailsIds:
+        result += " details_ids=" + IntVectorToString(values);
+        break;
       case ax::mojom::IntListAttribute::kFlowtoIds:
         result += " flowto_ids=" + IntVectorToString(values);
         break;
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index f383e1c7..a3b5738 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -2873,8 +2873,6 @@
     {ax::mojom::IntAttribute::kPopupForId, ATK_RELATION_POPUP_FOR,
      base::nullopt},
 #if defined(ATK_226)
-    {ax::mojom::IntAttribute::kDetailsId, ATK_RELATION_DETAILS,
-     ATK_RELATION_DETAILS_FOR},
     {ax::mojom::IntAttribute::kErrormessageId, ATK_RELATION_ERROR_MESSAGE,
      ATK_RELATION_ERROR_FOR},
 #endif
@@ -2889,6 +2887,8 @@
 static AtkIntListRelation kIntListRelations[] = {
     {ax::mojom::IntListAttribute::kControlsIds, ATK_RELATION_CONTROLLER_FOR,
      ATK_RELATION_CONTROLLED_BY},
+    {ax::mojom::IntListAttribute::kDetailsIds, ATK_RELATION_DETAILS,
+     ATK_RELATION_DETAILS_FOR},
     {ax::mojom::IntListAttribute::kDescribedbyIds, ATK_RELATION_DESCRIBED_BY,
      ATK_RELATION_DESCRIPTION_FOR},
     {ax::mojom::IntListAttribute::kFlowtoIds, ATK_RELATION_FLOWS_TO,
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc b/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
index f17dbed..1d665dcf 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
@@ -2009,7 +2009,7 @@
   AXNodeData root;
   root.id = 1;
   root.role = ax::mojom::Role::kRootWebArea;
-  root.AddIntAttribute(ax::mojom::IntAttribute::kDetailsId, 2);
+  root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2});
 
   AXNodeData child1;
   child1.id = 2;
@@ -2029,7 +2029,7 @@
   AXNodeData child3;
   child3.id = 4;
   child3.role = ax::mojom::Role::kStaticText;
-  child3.AddIntAttribute(ax::mojom::IntAttribute::kDetailsId, 2);
+  child3.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2});
   child3.AddIntAttribute(ax::mojom::IntAttribute::kMemberOfId, 1);
 
   root.child_ids.push_back(4);
@@ -2139,8 +2139,8 @@
     test_relation(setter, expected_relation, expected_reverse_relation);
   };
 
-  test_int_relation(ax::mojom::IntAttribute::kDetailsId, ATK_RELATION_DETAILS,
-                    ATK_RELATION_DETAILS_FOR);
+  test_int_list_relation(ax::mojom::IntListAttribute::kDetailsIds,
+                         ATK_RELATION_DETAILS, ATK_RELATION_DETAILS_FOR);
   test_int_relation(ax::mojom::IntAttribute::kErrormessageId,
                     ATK_RELATION_ERROR_MESSAGE, ATK_RELATION_ERROR_FOR);
   test_int_list_relation(ax::mojom::IntListAttribute::kControlsIds,
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 12de7a9..5913dd9c 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -1920,7 +1920,7 @@
   AXNodeData root;
   root.id = 1;
   root.role = ax::mojom::Role::kRootWebArea;
-  root.AddIntAttribute(ax::mojom::IntAttribute::kDetailsId, 2);
+  root.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2});
 
   AXNodeData child1;
   child1.id = 2;
@@ -1940,7 +1940,7 @@
   AXNodeData child3;
   child3.id = 4;
   child3.role = ax::mojom::Role::kStaticText;
-  child3.AddIntAttribute(ax::mojom::IntAttribute::kDetailsId, 2);
+  child3.AddIntListAttribute(ax::mojom::IntListAttribute::kDetailsIds, {2});
 
   root.child_ids.push_back(4);
 
diff --git a/ui/accessibility/platform/ax_platform_relation_win.cc b/ui/accessibility/platform/ax_platform_relation_win.cc
index 75a9535c..5f03ec8 100644
--- a/ui/accessibility/platform/ax_platform_relation_win.cc
+++ b/ui/accessibility/platform/ax_platform_relation_win.cc
@@ -39,8 +39,6 @@
 
 base::string16 GetIA2RelationFromIntAttr(ax::mojom::IntAttribute attribute) {
   switch (attribute) {
-    case ax::mojom::IntAttribute::kDetailsId:
-      return IA2_RELATION_DETAILS;
     case ax::mojom::IntAttribute::kMemberOfId:
       return IA2_RELATION_MEMBER_OF;
     case ax::mojom::IntAttribute::kErrormessageId:
@@ -58,6 +56,8 @@
       return IA2_RELATION_CONTROLLER_FOR;
     case ax::mojom::IntListAttribute::kDescribedbyIds:
       return IA2_RELATION_DESCRIBED_BY;
+    case ax::mojom::IntListAttribute::kDetailsIds:
+      return IA2_RELATION_DETAILS;
     case ax::mojom::IntListAttribute::kFlowtoIds:
       return IA2_RELATION_FLOWS_TO;
     case ax::mojom::IntListAttribute::kLabelledbyIds:
@@ -71,8 +71,6 @@
 base::string16 GetIA2ReverseRelationFromIntAttr(
     ax::mojom::IntAttribute attribute) {
   switch (attribute) {
-    case ax::mojom::IntAttribute::kDetailsId:
-      return IA2_RELATION_DETAILS_FOR;
     case ax::mojom::IntAttribute::kErrormessageId:
       return IA2_RELATION_ERROR_FOR;
     default:
@@ -88,6 +86,8 @@
       return IA2_RELATION_CONTROLLED_BY;
     case ax::mojom::IntListAttribute::kDescribedbyIds:
       return IA2_RELATION_DESCRIPTION_FOR;
+    case ax::mojom::IntListAttribute::kDetailsIds:
+      return IA2_RELATION_DETAILS_FOR;
     case ax::mojom::IntListAttribute::kFlowtoIds:
       return IA2_RELATION_FLOWS_FROM;
     case ax::mojom::IntListAttribute::kLabelledbyIds:
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc
index 21cd0e1..4d5e45c4 100644
--- a/ui/android/view_android.cc
+++ b/ui/android/view_android.cc
@@ -447,6 +447,15 @@
   return Java_ViewAndroidDelegate_getViewportInsetBottom(env, delegate);
 }
 
+void ViewAndroid::OnBrowserControlsHeightChanged() {
+  if (event_handler_)
+    event_handler_->OnBrowserControlsHeightChanged();
+  for (auto* child : children_) {
+    if (child->match_parent())
+      child->OnBrowserControlsHeightChanged();
+  }
+}
+
 void ViewAndroid::OnSizeChanged(int width, int height) {
   // Match-parent view must not receive size events.
   DCHECK(!match_parent());
diff --git a/ui/android/view_android.h b/ui/android/view_android.h
index c8eefde..95488d7 100644
--- a/ui/android/view_android.h
+++ b/ui/android/view_android.h
@@ -162,6 +162,7 @@
                             float top_content_offset);
   void OnBottomControlsChanged(float bottom_controls_offset,
                                float bottom_content_offset);
+  void OnBrowserControlsHeightChanged();
 
   // Gets the Visual Viewport inset to apply in physical pixels.
   int GetViewportInsetBottom();
diff --git a/ui/base/ime/fuchsia/BUILD.gn b/ui/base/ime/fuchsia/BUILD.gn
index 60935a1..378de2b 100644
--- a/ui/base/ime/fuchsia/BUILD.gn
+++ b/ui/base/ime/fuchsia/BUILD.gn
@@ -25,7 +25,5 @@
     "//ui/events",
   ]
 
-  deps = [
-    "//ui/events:dom_keycode_converter",
-  ]
+  deps = [ "//ui/events:dom_keycode_converter" ]
 }
diff --git a/ui/color/BUILD.gn b/ui/color/BUILD.gn
index 12d0512..8413ed17 100644
--- a/ui/color/BUILD.gn
+++ b/ui/color/BUILD.gn
@@ -20,9 +20,7 @@
     "color_provider.h",
   ]
 
-  public_deps = [
-    ":color_buildflags",
-  ]
+  public_deps = [ ":color_buildflags" ]
 
   if (use_color_pipeline) {
     sources += [
@@ -99,9 +97,7 @@
       "//ui/gfx:color_utils",
     ]
 
-    public_deps = [
-      "//base",
-    ]
+    public_deps = [ "//base" ]
 
     if (is_chromeos) {
       sources += [ "cros/native_color_mixer.cc" ]
diff --git a/ui/display/util/BUILD.gn b/ui/display/util/BUILD.gn
index cbaa00b..782be6f8 100644
--- a/ui/display/util/BUILD.gn
+++ b/ui/display/util/BUILD.gn
@@ -37,9 +37,7 @@
 }
 
 fuzzer_test("edid_parser_fuzzer") {
-  sources = [
-    "edid_parser_fuzzer.cc",
-  ]
+  sources = [ "edid_parser_fuzzer.cc" ]
   deps = [
     ":util",
     "//base",
diff --git a/ui/events/android/event_handler_android.cc b/ui/events/android/event_handler_android.cc
index 58779938..4f06903 100644
--- a/ui/events/android/event_handler_android.cc
+++ b/ui/events/android/event_handler_android.cc
@@ -51,4 +51,6 @@
 
 void EventHandlerAndroid::OnPhysicalBackingSizeChanged() {}
 
+void EventHandlerAndroid::OnBrowserControlsHeightChanged() {}
+
 }  // namespace ui
diff --git a/ui/events/android/event_handler_android.h b/ui/events/android/event_handler_android.h
index ee48a004..1cafd595 100644
--- a/ui/events/android/event_handler_android.h
+++ b/ui/events/android/event_handler_android.h
@@ -29,6 +29,7 @@
   virtual bool OnGestureEvent(const GestureEventAndroid& event);
   virtual void OnSizeChanged();
   virtual void OnPhysicalBackingSizeChanged();
+  virtual void OnBrowserControlsHeightChanged();
 
   virtual bool OnGenericMotionEvent(const MotionEventAndroid& event);
   virtual bool OnKeyUp(const KeyEventAndroid& event);
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index 9ca2f4b..0cfd9571 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -32,9 +32,7 @@
     "//url",
   ]
 
-  public_deps = [
-    "//ui/message_center/public/cpp",
-  ]
+  public_deps = [ "//ui/message_center/public/cpp" ]
 
   defines = [ "MESSAGE_CENTER_IMPLEMENTATION" ]
 
@@ -131,9 +129,7 @@
     }
   } else {
     # Notification service disabled.
-    sources = [
-      "dummy_message_center.cc",
-    ]
+    sources = [ "dummy_message_center.cc" ]
   }
 }
 
diff --git a/ui/ozone/platform/drm/host/drm_device_connector.cc b/ui/ozone/platform/drm/host/drm_device_connector.cc
index 47ee622e..0b3cf4a8 100644
--- a/ui/ozone/platform/drm/host/drm_device_connector.cc
+++ b/ui/ozone/platform/drm/host/drm_device_connector.cc
@@ -41,11 +41,6 @@
     scoped_refptr<base::SingleThreadTaskRunner> io_runner,
     GpuHostBindInterfaceCallback binder,
     GpuHostTerminateCallback terminate_callback) {
-  // We can get into this state if a new instance of GpuProcessHost is created
-  // before the old one is destroyed.
-  if (host_drm_device_->IsConnected())
-    host_drm_device_->OnGpuServiceLost();
-
   // We need to preserve |binder| to let us bind interfaces later.
   binder_callback_ = std::move(binder);
   host_id_ = host_id;
diff --git a/ui/ozone/platform/drm/host/host_drm_device.cc b/ui/ozone/platform/drm/host/host_drm_device.cc
index 58f9008..1381921 100644
--- a/ui/ozone/platform/drm/host/host_drm_device.cc
+++ b/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -325,6 +325,11 @@
     mojo::PendingRemote<ui::ozone::mojom::DrmDevice> drm_device) {
   DCHECK_CALLED_ON_VALID_THREAD(on_ui_thread_);
 
+  // We can get into this state if a new instance of GpuProcessHost is created
+  // before the old one is destroyed.
+  if (IsConnected())
+    OnGpuServiceLost();
+
   drm_device_.Bind(std::move(drm_device));
 
   // Create two DeviceCursor connections: one for the UI thread and one for the
diff --git a/ui/views/controls/webview/BUILD.gn b/ui/views/controls/webview/BUILD.gn
index 7316d518..dbf92b4 100644
--- a/ui/views/controls/webview/BUILD.gn
+++ b/ui/views/controls/webview/BUILD.gn
@@ -71,9 +71,7 @@
     "../../test/webview_test_helper.h",
   ]
 
-  public_deps = [
-    ":webview",
-  ]
+  public_deps = [ ":webview" ]
   deps = [
     "//base",
     "//content",
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index a4f9ce8f..69e1615 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -111,9 +111,7 @@
 executable("views_examples_exe") {
   testonly = true
 
-  sources = [
-    "examples_main.cc",
-  ]
+  sources = [ "examples_main.cc" ]
 
   deps = [
     ":views_examples_lib",
@@ -174,9 +172,7 @@
 executable("views_examples_with_content_exe") {
   testonly = true
 
-  sources = [
-    "examples_with_content_main_exe.cc",
-  ]
+  sources = [ "examples_with_content_main_exe.cc" ]
 
   defines = [ "VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION" ]
 
@@ -198,13 +194,7 @@
 }
 
 copy("copy_content_resources") {
-  deps = [
-    "//content:resources",
-  ]
-  sources = [
-    "$root_gen_dir/content/content_resources.pak",
-  ]
-  outputs = [
-    "$root_out_dir/content_resources.pak",
-  ]
+  deps = [ "//content:resources" ]
+  sources = [ "$root_gen_dir/content/content_resources.pak" ]
+  outputs = [ "$root_out_dir/content_resources.pak" ]
 }
diff --git a/ui/views/layout/animating_layout_manager_unittest.cc b/ui/views/layout/animating_layout_manager_unittest.cc
index 716b093f..92bfa7d3 100644
--- a/ui/views/layout/animating_layout_manager_unittest.cc
+++ b/ui/views/layout/animating_layout_manager_unittest.cc
@@ -1640,6 +1640,85 @@
   EXPECT_LT(child(2)->x(), old_child2_bounds.x());
 }
 
+// Regression test for issue crbug.com/1040173 (1/2):
+// PostOrQueueAction does not delay an action after FadeIn is called.
+TEST_F(AnimatingLayoutManagerTest,
+       FlexLayout_PostDelayedActionAfterFadeIn_AnimateNewViewIn) {
+  child(0)->SetVisible(false);
+  layout()->SetShouldAnimateBounds(true);
+  layout()->SetOrientation(LayoutOrientation::kHorizontal);
+  auto* const flex_layout =
+      layout()->SetTargetLayoutManager(std::make_unique<FlexLayout>());
+  flex_layout->SetOrientation(LayoutOrientation::kHorizontal);
+  flex_layout->SetCollapseMargins(true);
+  flex_layout->SetCrossAxisAlignment(LayoutAlignment::kStart);
+  flex_layout->SetDefault(kFlexBehaviorKey, kDropOut);
+
+  layout()->ResetLayout();
+  SizeAndLayout();
+
+  bool action_run = false;
+
+  layout()->FadeIn(child(0));
+  layout()->PostOrQueueAction(
+      base::BindOnce([](bool* var) { *var = true; }, &action_run));
+  // No tasks should be posted, we're still animating.
+  EXPECT_TRUE(layout()->is_animating());
+  RunCurrentTasks();
+  EXPECT_FALSE(action_run);
+
+  // Advance the animation to the end.
+  animation_api()->IncrementTime(base::TimeDelta::FromMilliseconds(1000));
+  SizeAndLayout();
+  // We should be done and tasks will post.
+  EXPECT_FALSE(layout()->is_animating());
+  RunCurrentTasks();
+  EXPECT_TRUE(action_run);
+  EXPECT_TRUE(child(0)->GetVisible());
+  EXPECT_TRUE(child(1)->GetVisible());
+  EXPECT_TRUE(child(2)->GetVisible());
+}
+
+// Regression test for issue crbug.com/1040173 (2/2):
+// PostOrQueueAction does not delay an action after FadeIn is called.
+TEST_F(AnimatingLayoutManagerTest,
+       FlexLayout_PostDelayedActionAfterFadeIn_SwapTwoViews) {
+  child(0)->SetVisible(false);
+  layout()->SetShouldAnimateBounds(false);
+  layout()->SetOrientation(LayoutOrientation::kHorizontal);
+  auto* const flex_layout =
+      layout()->SetTargetLayoutManager(std::make_unique<FlexLayout>());
+  flex_layout->SetOrientation(LayoutOrientation::kHorizontal);
+  flex_layout->SetCollapseMargins(true);
+  flex_layout->SetCrossAxisAlignment(LayoutAlignment::kStart);
+  flex_layout->SetDefault(kFlexBehaviorKey, kDropOut);
+
+  view()->SetSize({20, 10});
+  layout()->ResetLayout();
+  view()->Layout();
+
+  bool action_run = false;
+
+  layout()->FadeIn(child(0));
+  layout()->PostOrQueueAction(
+      base::BindOnce([](bool* var) { *var = true; }, &action_run));
+  // No tasks should be posted, we're still animating.
+  EXPECT_TRUE(layout()->is_animating());
+  RunCurrentTasks();
+  EXPECT_FALSE(action_run);
+
+  // Advance the animation to the end.
+  animation_api()->IncrementTime(base::TimeDelta::FromMilliseconds(1000));
+  view()->Layout();
+  // We should be done and tasks will post.
+  EXPECT_FALSE(layout()->is_animating());
+  RunCurrentTasks();
+  EXPECT_TRUE(action_run);
+  EXPECT_TRUE(child(0)->GetVisible());
+  EXPECT_TRUE(child(1)->GetVisible());
+  EXPECT_FALSE(child(2)->GetVisible());
+}
+
 TEST_F(AnimatingLayoutManagerTest, FlexLayout_FadeInOnAdded) {
   constexpr gfx::Insets kChildMargins(5);
   layout()->SetShouldAnimateBounds(false);
diff --git a/ui/views/resources/BUILD.gn b/ui/views/resources/BUILD.gn
index 226a664b..d30acd9e 100644
--- a/ui/views/resources/BUILD.gn
+++ b/ui/views/resources/BUILD.gn
@@ -6,9 +6,7 @@
 import("//tools/grit/repack.gni")
 
 group("resources") {
-  public_deps = [
-    ":resources_grd",
-  ]
+  public_deps = [ ":resources_grd" ]
 }
 
 grit("resources_grd") {
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
index dadfd89..d075a8d1 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/BUILD.gn
@@ -20,24 +20,18 @@
 }
 
 js_library("button_bar") {
-  deps = [
-    "//ui/webui/resources/js:i18n_behavior",
-  ]
+  deps = [ "//ui/webui/resources/js:i18n_behavior" ]
 }
 
 js_library("base_page") {
 }
 
 js_library("sim_detect_page") {
-  deps = [
-    ":base_page",
-  ]
+  deps = [ ":base_page" ]
 }
 
 js_library("webview_post_util") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
   externs_list = [
     "$externs_path/chrome_extensions.js",
     "$externs_path/webview_tag.js",
@@ -56,9 +50,7 @@
 }
 
 js_library("final_page") {
-  deps = [
-    ":base_page",
-  ]
+  deps = [ ":base_page" ]
 }
 
 js_library("cellular_setup") {
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
index 6f2aa215..de6c651e 100644
--- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -53,15 +53,11 @@
 }
 
 js_library("multidevice_setup_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("multidevice_setup_delegate") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("password_page") {
diff --git a/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn b/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn
index fc1a7d5..88e62568 100644
--- a/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/BUILD.gn
@@ -27,9 +27,7 @@
 }
 
 js_library("smb_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-  ]
+  deps = [ "//ui/webui/resources/js:cr" ]
 }
 
 js_library("add_smb_share_dialog") {
@@ -47,9 +45,7 @@
 }
 
 js_library("add_smb_share_dialog.m") {
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.m.js",
-  ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.m.js" ]
   deps = [
     ":smb_browser_proxy.m",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
@@ -70,12 +66,8 @@
 }
 
 js_library("smb_browser_proxy.m") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
-  sources = [
-    "$root_gen_dir/ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.m.js",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
+  sources = [ "$root_gen_dir/ui/webui/resources/cr_components/chromeos/smb_shares/smb_browser_proxy.m.js" ]
   extra_deps = [ ":smb_browser_proxy_module" ]
 }
 
diff --git a/ui/webui/resources/cr_elements/cr_slider/BUILD.gn b/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
index ad5d8f6..bbcf09a 100644
--- a/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
+++ b/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":cr_slider",
-  ]
+  deps = [ ":cr_slider" ]
 }
 
 js_library("cr_slider") {
diff --git a/weblayer/public/java/BUILD.gn b/weblayer/public/java/BUILD.gn
index a0c6af6..88105fdd 100644
--- a/weblayer/public/java/BUILD.gn
+++ b/weblayer/public/java/BUILD.gn
@@ -99,7 +99,5 @@
   template_file =
       "org/chromium/weblayer/WebLayerClientVersionConstants.java.version"
   output = _version_constants_java_file
-  sources = [
-    "//chrome/VERSION",
-  ]
+  sources = [ "//chrome/VERSION" ]
 }
diff --git a/weblayer/public/javatests/BUILD.gn b/weblayer/public/javatests/BUILD.gn
index a8096ad..41767c05 100644
--- a/weblayer/public/javatests/BUILD.gn
+++ b/weblayer/public/javatests/BUILD.gn
@@ -7,9 +7,7 @@
 
 android_library("weblayer_public_javatests") {
   testonly = true
-  sources = [
-    "org/chromium/weblayer/ObserverListTest.java",
-  ]
+  sources = [ "org/chromium/weblayer/ObserverListTest.java" ]
   deps = [
     "//base:base_java_test_support",
     "//third_party/junit:junit",
diff --git a/weblayer/public/javatestutil/BUILD.gn b/weblayer/public/javatestutil/BUILD.gn
index 4917ee9..48b69a71 100644
--- a/weblayer/public/javatestutil/BUILD.gn
+++ b/weblayer/public/javatestutil/BUILD.gn
@@ -7,9 +7,7 @@
 
 android_library("test_java") {
   testonly = true
-  sources = [
-    "org/chromium/weblayer/TestWebLayer.java",
-  ]
+  sources = [ "org/chromium/weblayer/TestWebLayer.java" ]
 
   deps = [
     "//base:base_java_test_support",