diff --git a/BUILD.gn b/BUILD.gn
index 35715fbb..f928c3d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -985,9 +985,7 @@
   # third_party/blink/tools/run_web_tests.py
   group("run_web_tests") {
     testonly = true
-    deps = [
-      ":blink_web_tests",
-    ]
+    deps = [ ":blink_web_tests" ]
   }
 
   if (!is_chromeos && !is_ios && !is_fuchsia && !is_android) {
@@ -1018,23 +1016,15 @@
         "//chrome:chrome",
         "//chrome/test/chromedriver",
       ]
-      deps = [
-        "//third_party/blink/tools:wpt_tests_isolate",
-      ]
+      deps = [ "//third_party/blink/tools:wpt_tests_isolate" ]
     }
   }
 
   group("devtools_web_tests") {
     testonly = true
-    deps = [
-      ":blink_web_tests",
-    ]
-    data_deps = [
-      ":blink_web_tests",
-    ]
-    data = [
-      "//third_party/devtools-frontend/src/test/webtests/",
-    ]
+    deps = [ ":blink_web_tests" ]
+    data_deps = [ ":blink_web_tests" ]
+    data = [ "//third_party/devtools-frontend/src/test/webtests/" ]
   }
 
   # https://www.chromium.org/developers/testing/webkit-layout-tests
@@ -1149,33 +1139,24 @@
   copy("layout_test_data_mojo_bindings") {
     testonly = true
 
-    sources = [
-      "$root_gen_dir/mojo/public/js/mojo_bindings.js",
-    ]
+    sources = [ "$root_gen_dir/mojo/public/js/mojo_bindings.js" ]
 
-    outputs = [
-      "$root_gen_dir/layout_test_data/mojo/public/js/mojo_bindings.js",
-    ]
+    outputs =
+        [ "$root_gen_dir/layout_test_data/mojo/public/js/mojo_bindings.js" ]
 
-    deps = [
-      "//mojo/public/js:bindings",
-    ]
+    deps = [ "//mojo/public/js:bindings" ]
   }
 
   copy("layout_test_data_mojo_bindings_lite") {
     testonly = true
 
-    sources = [
-      "$root_gen_dir/mojo/public/js/mojo_bindings_lite.js",
-    ]
+    sources = [ "$root_gen_dir/mojo/public/js/mojo_bindings_lite.js" ]
 
     outputs = [
       "$root_gen_dir/layout_test_data/mojo/public/js/mojo_bindings_lite.js",
     ]
 
-    deps = [
-      "//mojo/public/js:bindings_lite",
-    ]
+    deps = [ "//mojo/public/js:bindings_lite" ]
   }
 
   group("blink_python_tests") {
diff --git a/DEPS b/DEPS
index 51943c7..bd72661 100644
--- a/DEPS
+++ b/DEPS
@@ -181,7 +181,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'f6d60d32a7d47ad383db14190f97bf4d9b3da42a',
+  'skia_revision': 'bfb72113a7a84fde3189254fefb93ac7c6500a32',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -252,7 +252,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '151993a023223545a9be549ecb797a069a327899',
+  'devtools_frontend_revision': '3cd66dcf894a99faceb1c8809393ad33c78440b2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 7a5e1ea4..d760d4b0 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1503,9 +1503,7 @@
     "//url",
   ]
 
-  data_deps = [
-    ":dbus_service_files",
-  ]
+  data_deps = [ ":dbus_service_files" ]
 
   assert_no_deps = [
     # Ash should not depend upon cryptohome_client or components that depend
@@ -1640,9 +1638,7 @@
     "//ui/views/examples:views_examples_with_content_lib",
     "//ui/wm",
   ]
-  public_deps = [
-    ":ash_shell_lib",
-  ]
+  public_deps = [ ":ash_shell_lib" ]
   data_deps = [
     "//ash/resources:ash_test_resources_200_percent",
     "//ash/resources:ash_test_resources_with_content_100_percent",
@@ -1658,9 +1654,7 @@
     "dbus/org.chromium.UrlHandlerService.conf",
   ]
   output_conf_file = "$root_out_dir/dbus/ash_dbus_services.conf"
-  outputs = [
-    output_conf_file,
-  ]
+  outputs = [ output_conf_file ]
 
   script = "//chromeos/tools/concat_dbus_conf_files.py"
   args = [ rebase_path(output_conf_file, root_build_dir) ]
@@ -2132,9 +2126,7 @@
     "//url",
   ]
 
-  data_deps = [
-    "//ash/resources:ash_test_resources_100_percent",
-  ]
+  data_deps = [ "//ash/resources:ash_test_resources_100_percent" ]
 
   data = [
     # See DisplayColorManagerTest.
@@ -2204,9 +2196,7 @@
 
 executable("ash_shell_with_content") {
   testonly = true
-  sources = [
-    "shell/content/shell_with_content_main.cc",
-  ]
+  sources = [ "shell/content/shell_with_content_main.cc" ]
 
   deps = [
     ":ash_shell_lib_with_content",
diff --git a/ash/components/fast_ink/BUILD.gn b/ash/components/fast_ink/BUILD.gn
index 7a4345fd..8b4e8781 100644
--- a/ash/components/fast_ink/BUILD.gn
+++ b/ash/components/fast_ink/BUILD.gn
@@ -30,9 +30,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "fast_ink_points_unittest.cc",
-  ]
+  sources = [ "fast_ink_points_unittest.cc" ]
 
   deps = [
     ":fast_ink",
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc
index 05c8875..e591ee1 100644
--- a/ash/focus_cycler_unittest.cc
+++ b/ash/focus_cycler_unittest.cc
@@ -46,10 +46,11 @@
     std::copy(accessible_panes_.begin(), accessible_panes_.end(),
               std::back_inserter(*panes));
   }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   views::Widget* widget_;
   std::vector<views::View*> accessible_panes_;
 };
diff --git a/ash/lock_screen_action/test_lock_screen_action_background_controller.cc b/ash/lock_screen_action/test_lock_screen_action_background_controller.cc
index dffa0a13..26917717 100644
--- a/ash/lock_screen_action/test_lock_screen_action_background_controller.cc
+++ b/ash/lock_screen_action/test_lock_screen_action_background_controller.cc
@@ -21,14 +21,15 @@
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   bool CanActivate() const override { return false; }
   bool CanResize() const override { return true; }
   bool CanMaximize() const override { return true; }
   bool ShouldAdvanceFocusToTopLevelWidget() const override { return true; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   views::Widget* widget_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
diff --git a/ash/login/ui/login_test_base.cc b/ash/login/ui/login_test_base.cc
index a54d0ec..ab6e9bf 100644
--- a/ash/login/ui/login_test_base.cc
+++ b/ash/login/ui/login_test_base.cc
@@ -29,12 +29,13 @@
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
   views::View* GetInitiallyFocusedView() override { return content_; }
-  views::Widget* GetWidget() override { return content_->GetWidget(); }
-  const views::Widget* GetWidget() const override {
+
+ private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override {
     return content_->GetWidget();
   }
 
- private:
   views::View* content_;
 
   DISALLOW_COPY_AND_ASSIGN(WidgetDelegate);
diff --git a/ash/public/cpp/lock_screen_widget_factory.cc b/ash/public/cpp/lock_screen_widget_factory.cc
index f8420532..b4e9682 100644
--- a/ash/public/cpp/lock_screen_widget_factory.cc
+++ b/ash/public/cpp/lock_screen_widget_factory.cc
@@ -22,11 +22,12 @@
   views::View* GetInitiallyFocusedView() override {
     return widget_->GetContentsView();
   }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   void DeleteDelegate() override { delete this; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   views::Widget* widget_;
 
   DISALLOW_COPY_AND_ASSIGN(LockScreenWidgetDelegate);
diff --git a/ash/shelf/shelf_navigation_widget.cc b/ash/shelf/shelf_navigation_widget.cc
index 312b2d05..1b9fab9 100644
--- a/ash/shelf/shelf_navigation_widget.cc
+++ b/ash/shelf/shelf_navigation_widget.cc
@@ -90,8 +90,6 @@
 
   // views::WidgetDelegate:
   bool CanActivate() const override;
-  views::Widget* GetWidget() override { return View::GetWidget(); }
-  const views::Widget* GetWidget() const override { return View::GetWidget(); }
 
   BackButton* back_button() const { return back_button_; }
   HomeButton* home_button() const { return home_button_; }
diff --git a/ash/shelf/shelf_unittest.cc b/ash/shelf/shelf_unittest.cc
index ea3de76d..bbbf889 100644
--- a/ash/shelf/shelf_unittest.cc
+++ b/ash/shelf/shelf_unittest.cc
@@ -21,7 +21,6 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "components/session_manager/session_manager_types.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 
 namespace ash {
 namespace {
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 8458e96..3b35172 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -111,8 +111,6 @@
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return View::GetWidget(); }
-  const views::Widget* GetWidget() const override { return View::GetWidget(); }
 
   bool CanActivate() const override;
   void ReorderChildLayers(ui::Layer* parent_layer) override;
diff --git a/ash/shell_test_api.cc b/ash/shell_test_api.cc
index c615fde..2bd6a0fe 100644
--- a/ash/shell_test_api.cc
+++ b/ash/shell_test_api.cc
@@ -25,7 +25,6 @@
 #include "ash/wm/workspace_controller.h"
 #include "base/run_loop.h"
 #include "components/prefs/testing_pref_service.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc
index 7de4c6e..8c1b7134 100644
--- a/ash/system/status_area_widget_delegate.cc
+++ b/ash/system/status_area_widget_delegate.cc
@@ -135,14 +135,6 @@
   return "ash/StatusAreaWidgetDelegate";
 }
 
-views::Widget* StatusAreaWidgetDelegate::GetWidget() {
-  return View::GetWidget();
-}
-
-const views::Widget* StatusAreaWidgetDelegate::GetWidget() const {
-  return View::GetWidget();
-}
-
 void StatusAreaWidgetDelegate::OnGestureEvent(ui::GestureEvent* event) {
   views::Widget* target_widget =
       static_cast<views::View*>(event->target())->GetWidget();
diff --git a/ash/system/status_area_widget_delegate.h b/ash/system/status_area_widget_delegate.h
index 53a3e31..13cca06 100644
--- a/ash/system/status_area_widget_delegate.h
+++ b/ash/system/status_area_widget_delegate.h
@@ -44,8 +44,6 @@
   // views::AccessiblePaneView:
   View* GetDefaultFocusableChild() override;
   const char* GetClassName() const override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
 
   // ui::EventHandler:
   void OnGestureEvent(ui::GestureEvent* event) override;
diff --git a/ash/wm/lock_action_handler_layout_manager_unittest.cc b/ash/wm/lock_action_handler_layout_manager_unittest.cc
index 196649a..a22b353 100644
--- a/ash/wm/lock_action_handler_layout_manager_unittest.cc
+++ b/ash/wm/lock_action_handler_layout_manager_unittest.cc
@@ -53,8 +53,6 @@
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   bool CanActivate() const override { return true; }
   bool CanResize() const override { return true; }
   bool CanMaximize() const override { return true; }
@@ -63,6 +61,9 @@
   void set_widget(views::Widget* widget) { widget_ = widget; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   views::Widget* widget_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc
index fd15d51..ef6281c 100644
--- a/ash/wm/lock_layout_manager_unittest.cc
+++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -35,12 +35,13 @@
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   bool CanActivate() const override { return true; }
   bool ShouldAdvanceFocusToTopLevelWidget() const override { return true; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   views::Widget* widget_;
 
   DISALLOW_COPY_AND_ASSIGN(LoginTestWidgetDelegate);
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index 54b2d54..516d85ca 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -4511,8 +4511,6 @@
 
   // views::WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   bool CanActivate() const override { return true; }
   bool CanResize() const override { return can_resize_; }
   bool CanMaximize() const override { return true; }
@@ -4521,6 +4519,9 @@
   void set_widget(views::Widget* widget) { widget_ = widget; }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   bool can_resize_;
   views::Widget* widget_ = nullptr;
 
diff --git a/base/util/memory_pressure/BUILD.gn b/base/util/memory_pressure/BUILD.gn
index 8314643..9143193 100644
--- a/base/util/memory_pressure/BUILD.gn
+++ b/base/util/memory_pressure/BUILD.gn
@@ -39,9 +39,7 @@
     ]
   }
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unittests") {
diff --git a/build/android/buildhooks/BUILD.gn b/build/android/buildhooks/BUILD.gn
index a47e662..74e2f1b6 100644
--- a/build/android/buildhooks/BUILD.gn
+++ b/build/android/buildhooks/BUILD.gn
@@ -7,25 +7,19 @@
 
 java_library("build_hooks_java") {
   jacoco_never_instrument = true
-  sources = [
-    "java/org/chromium/build/BuildHooks.java",
-  ]
+  sources = [ "java/org/chromium/build/BuildHooks.java" ]
 
   # Make all targets pull in the try-with-resources support files.
   # If an apk ends up not using any such statements, ProGuard will remove
   # them.
-  deps = [
-    "//third_party/bazel/desugar:desugar_runtime_java",
-  ]
+  deps = [ "//third_party/bazel/desugar:desugar_runtime_java" ]
   srcjar_deps = [ ":base_build_hooks_config" ]
   no_build_hooks = true
   supports_android = true
 }
 
 java_cpp_template("base_build_hooks_config") {
-  sources = [
-    "java/templates/BuildHooksConfig.template",
-  ]
+  sources = [ "java/templates/BuildHooksConfig.template" ]
   package_path = "org/chromium/build"
 
   defines = []
@@ -52,11 +46,7 @@
 # specify a different implementation via build_hooks_android_impl_deps.
 android_library("build_hooks_android_impl_java") {
   jacoco_never_instrument = true
-  sources = [
-    build_hooks_android_impl,
-  ]
-  deps = [
-    ":build_hooks_android_java",
-  ]
+  sources = [ build_hooks_android_impl ]
+  deps = [ ":build_hooks_android_java" ]
   no_build_hooks = true
 }
diff --git a/build/android/pylib/device/commands/BUILD.gn b/build/android/pylib/device/commands/BUILD.gn
index d63f551..a3ee646 100644
--- a/build/android/pylib/device/commands/BUILD.gn
+++ b/build/android/pylib/device/commands/BUILD.gn
@@ -5,21 +5,13 @@
 import("//build/config/android/rules.gni")
 
 group("commands") {
-  data_deps = [
-    ":chromium_commands_java",
-  ]
+  data_deps = [ ":chromium_commands_java" ]
 }
 
 android_library("chromium_commands_java") {
   jacoco_never_instrument = true
-  sources = [
-    "java/src/org/chromium/android/commands/unzip/Unzip.java",
-  ]
+  sources = [ "java/src/org/chromium/android/commands/unzip/Unzip.java" ]
   dex_path = "$root_build_dir/lib.java/chromium_commands.dex.jar"
-  deps = [
-    "//base:base_java",
-  ]
-  data = [
-    dex_path,
-  ]
+  deps = [ "//base:base_java" ]
+  data = [ dex_path ]
 }
diff --git a/build/config/freetype/BUILD.gn b/build/config/freetype/BUILD.gn
index 0ba90271..76cb025 100644
--- a/build/config/freetype/BUILD.gn
+++ b/build/config/freetype/BUILD.gn
@@ -9,8 +9,6 @@
   if (use_system_freetype) {
     public_configs = [ "//build/linux:freetype_from_pkgconfig" ]
   } else {
-    public_deps = [
-      "//third_party:freetype_harfbuzz",
-    ]
+    public_deps = [ "//third_party:freetype_harfbuzz" ]
   }
 }
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc
index b603eb8..f523285d 100644
--- a/cc/paint/discardable_image_map.cc
+++ b/cc/paint/discardable_image_map.cc
@@ -24,26 +24,6 @@
 namespace {
 const int kMaxRectsSize = 256;
 
-SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
-  SkRect dst;
-  matrix.mapRect(&dst, src);
-  return dst;
-}
-
-bool ComputePaintBounds(const SkRect& rect,
-                        const SkPaint* current_paint,
-                        SkRect* paint_bounds) {
-  *paint_bounds = rect;
-  if (current_paint) {
-    if (!current_paint->canComputeFastBounds())
-      return false;
-    *paint_bounds =
-        current_paint->computeFastBounds(*paint_bounds, paint_bounds);
-  }
-
-  return true;
-}
-
 class DiscardableImageGenerator {
  public:
   DiscardableImageGenerator(int width,
@@ -148,7 +128,10 @@
       if (top_level_op_rect) {
         op_rect = *top_level_op_rect;
       } else {
-        local_op_rect = ComputePaintRect(op, canvas);
+        const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds());
+        const SkMatrix& ctm = canvas->getTotalMatrix();
+
+        local_op_rect = PaintOp::ComputePaintRect(op, clip_rect, ctm);
         if (local_op_rect.value().IsEmpty())
           continue;
 
@@ -184,58 +167,6 @@
     }
   }
 
-  // Given the |op_rect|, which is the rect for the draw op, returns the
-  // transformed rect accounting for the current transform, clip and paint
-  // state on |canvas_|.
-  gfx::Rect ComputePaintRect(const PaintOp* op, SkNoDrawCanvas* canvas) {
-    const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds());
-    const SkMatrix& ctm = canvas->getTotalMatrix();
-
-    gfx::Rect transformed_rect;
-    SkRect op_rect;
-    if (!op->IsDrawOp() || !PaintOp::GetBounds(op, &op_rect)) {
-      // If we can't provide a conservative bounding rect for the op, assume it
-      // covers the complete current clip.
-      // TODO(khushalsagar): See if we can do something better for non-draw ops.
-      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(clip_rect));
-    } else {
-      const PaintFlags* flags =
-          op->IsPaintOpWithFlags()
-              ? &static_cast<const PaintOpWithFlags*>(op)->flags
-              : nullptr;
-      SkPaint paint;
-      if (flags)
-        paint = flags->ToSkPaint();
-
-      SkRect paint_rect = MapRect(ctm, op_rect);
-      bool computed_paint_bounds =
-          ComputePaintBounds(paint_rect, &paint, &paint_rect);
-      if (!computed_paint_bounds) {
-        // TODO(vmpstr): UMA this case.
-        paint_rect = clip_rect;
-      }
-
-      // Clamp the image rect by the current clip rect.
-      if (!paint_rect.intersect(clip_rect))
-        return gfx::Rect();
-
-      transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect));
-    }
-
-    // During raster, we use the device clip bounds on the canvas, which outsets
-    // the actual clip by 1 due to the possibility of antialiasing. Account for
-    // this here by outsetting the image rect by 1. Note that this only affects
-    // queries into the rtree, which will now return images that only touch the
-    // bounds of the query rect.
-    //
-    // Note that it's not sufficient for us to inset the device clip bounds at
-    // raster time, since we might be sending a larger-than-one-item display
-    // item to skia, which means that skia will internally determine whether to
-    // raster the picture (using device clip bounds that are outset).
-    transformed_rect.Inset(-1, -1);
-    return transformed_rect;
-  }
-
   void AddImageFromFlags(const gfx::Rect& op_rect,
                          const PaintFlags& flags,
                          const SkMatrix& ctm) {
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index 97a18290..69d3c09 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -18,6 +18,7 @@
 #include "third_party/skia/include/core/SkSerialProcs.h"
 #include "third_party/skia/include/docs/SkPDFDocument.h"
 #include "third_party/skia/include/gpu/GrContext.h"
+#include "ui/gfx/skia_util.h"
 
 namespace cc {
 namespace {
@@ -46,6 +47,12 @@
                           original.width() * x_scale,
                           original.height() * y_scale);
 }
+
+SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
+  SkRect dst;
+  matrix.mapRect(&dst, src);
+  return dst;
+}
 }  // namespace
 
 #define TYPES(M)      \
@@ -2047,6 +2054,50 @@
 }
 
 // static
+gfx::Rect PaintOp::ComputePaintRect(const PaintOp* op,
+                                    const SkRect& clip_rect,
+                                    const SkMatrix& ctm) {
+  gfx::Rect transformed_rect;
+  SkRect op_rect;
+  if (!op->IsDrawOp() || !PaintOp::GetBounds(op, &op_rect)) {
+    // If we can't provide a conservative bounding rect for the op, assume it
+    // covers the complete current clip.
+    // TODO(khushalsagar): See if we can do something better for non-draw ops.
+    transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(clip_rect));
+  } else {
+    const PaintFlags* flags =
+        op->IsPaintOpWithFlags()
+            ? &static_cast<const PaintOpWithFlags*>(op)->flags
+            : nullptr;
+    SkRect paint_rect = MapRect(ctm, op_rect);
+    if (flags) {
+      SkPaint paint = flags->ToSkPaint();
+      paint_rect = paint.canComputeFastBounds()
+                       ? paint.computeFastBounds(paint_rect, &paint_rect)
+                       : clip_rect;
+    }
+    // Clamp the image rect by the current clip rect.
+    if (!paint_rect.intersect(clip_rect))
+      return gfx::Rect();
+
+    transformed_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect));
+  }
+
+  // During raster, we use the device clip bounds on the canvas, which outsets
+  // the actual clip by 1 due to the possibility of antialiasing. Account for
+  // this here by outsetting the image rect by 1. Note that this only affects
+  // queries into the rtree, which will now return images that only touch the
+  // bounds of the query rect.
+  //
+  // Note that it's not sufficient for us to inset the device clip bounds at
+  // raster time, since we might be sending a larger-than-one-item display
+  // item to skia, which means that skia will internally determine whether to
+  // raster the picture (using device clip bounds that are outset).
+  transformed_rect.Inset(-1, -1);
+  return transformed_rect;
+}
+
+// static
 bool PaintOp::QuickRejectDraw(const PaintOp* op, const SkCanvas* canvas) {
   if (!op->IsDrawOp())
     return false;
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 7388e06f..7943996 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -227,6 +227,13 @@
   // for the op.
   static bool GetBounds(const PaintOp* op, SkRect* rect);
 
+  // Returns the minimum conservative bounding rect that |op| draws to on a
+  // canvas. |clip_rect| and |ctm| are the current clip rect and transform on
+  // this canvas.
+  static gfx::Rect ComputePaintRect(const PaintOp* op,
+                                    const SkRect& clip_rect,
+                                    const SkMatrix& ctm);
+
   // Returns true if the op lies outside the current clip and should be skipped.
   // Should only be used with draw ops.
   static bool QuickRejectDraw(const PaintOp* op, const SkCanvas* canvas);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 63fb6cc..20231bef 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2852,7 +2852,6 @@
     "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfInfoBar.java",
     "java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfModelObserverBridge.java",
     "java/src/org/chromium/chrome/browser/send_tab_to_self/TargetDeviceInfo.java",
-    "java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java",
     "java/src/org/chromium/chrome/browser/settings/LocationSettings.java",
     "java/src/org/chromium/chrome/browser/settings/NfcSystemLevelSetting.java",
     "java/src/org/chromium/chrome/browser/settings/about/AboutSettingsBridge.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 7ec83ac..c01512d 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1369,7 +1369,6 @@
   "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundTask.java",
   "java/src/org/chromium/chrome/browser/services/gcm/GcmUma.java",
   "java/src/org/chromium/chrome/browser/services/gcm/InvalidationGcmUpstreamSender.java",
-  "java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java",
   "java/src/org/chromium/chrome/browser/settings/ExpandablePreferenceGroup.java",
   "java/src/org/chromium/chrome/browser/settings/HyperlinkPreference.java",
   "java/src/org/chromium/chrome/browser/settings/LearnMorePreference.java",
diff --git a/chrome/android/features/dev_ui/public/BUILD.gn b/chrome/android/features/dev_ui/public/BUILD.gn
index cd4d486..779293e 100644
--- a/chrome/android/features/dev_ui/public/BUILD.gn
+++ b/chrome/android/features/dev_ui/public/BUILD.gn
@@ -10,9 +10,7 @@
     "//components/module_installer/android:module_installer_java",
     "//components/module_installer/android:module_interface_java",
   ]
-  sources = [
-    "java/src/org/chromium/chrome/features/dev_ui/DevUi.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/features/dev_ui/DevUi.java" ]
 
   # Need this to generate DevUiModule.java.
   annotation_processor_deps =
diff --git a/chrome/android/features/keyboard_accessory/factory/BUILD.gn b/chrome/android/features/keyboard_accessory/factory/BUILD.gn
index a99df797..c1d9b09 100644
--- a/chrome/android/features/keyboard_accessory/factory/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/factory/BUILD.gn
@@ -8,15 +8,12 @@
 _factory_sources = [ "java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponentFactory.java" ]
 
 android_library_factory("public_java") {
-  deps = [
-    "//chrome/android/features/keyboard_accessory/public:public_java",
-  ]
+  deps = [ "//chrome/android/features/keyboard_accessory/public:public_java" ]
   sources = _factory_sources
 }
 
 android_library("internal_java") {
-  deps = [
-    "//chrome/android/features/keyboard_accessory/internal:internal_java",
-  ]
+  deps =
+      [ "//chrome/android/features/keyboard_accessory/internal:internal_java" ]
   sources = _factory_sources
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java b/chrome/android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java
index 2006dc4..6cbb8e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java
@@ -4,13 +4,12 @@
 
 package org.chromium.chrome.browser.rlz;
 
-import android.content.SharedPreferences;
-
-import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.AppHooks;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.tab.Tab;
 
 /**
@@ -18,7 +17,6 @@
  */
 @JNINamespace("chrome::android")
 public class RevenueStats {
-    private static final String PREF_RLZ_NOTIFIED = "rlz_first_search_notified";
 
     private static RevenueStats sInstance;
 
@@ -43,8 +41,8 @@
      * Returns whether the RLZ provider has been notified that the first search has occurred.
      */
     protected static boolean getRlzNotified() {
-        return ContextUtils.getAppSharedPreferences().getBoolean(
-                PREF_RLZ_NOTIFIED, false);
+        return SharedPreferencesManager.getInstance().readBoolean(
+                ChromePreferenceKeys.RLZ_NOTIFIED, false);
     }
 
     /**
@@ -52,10 +50,16 @@
      * shared preference.
      */
     protected static void setRlzNotified(boolean notified) {
-        SharedPreferences.Editor sharedPreferencesEditor =
-                ContextUtils.getAppSharedPreferences().edit();
-        sharedPreferencesEditor.putBoolean(PREF_RLZ_NOTIFIED, notified);
-        sharedPreferencesEditor.apply();
+        SharedPreferencesManager.getInstance().writeBoolean(
+                ChromePreferenceKeys.RLZ_NOTIFIED, notified);
+    }
+
+    /**
+     * Stores that the RLZ provider has been notified that the first search has occurred.
+     */
+    protected static void markRlzNotified() {
+        SharedPreferencesManager.getInstance().writeBoolean(
+                ChromePreferenceKeys.RLZ_NOTIFIED, true);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java
deleted file mode 100644
index 6b52522..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/sessions/SessionTabHelper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.sessions;
-
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.content_public.browser.WebContents;
-
-/**
- * The SessionTabHelper Java wrapper to allow communicating with the native SessionTabHelper
- * object.
- */
-public class SessionTabHelper {
-    /**
-     * If WebContents has a SessionTabHelper (probably because it was used as the contents of a
-     * tab), returns a session tab id. Returns -1 if the WebContents has no SessionTabHelper. See
-     * SessionTabHelper::IdForTab() in session_tab_helper.h
-     *
-     * @param tab The WebContents to get the tab id for.
-     */
-    public static int sessionIdForTab(WebContents webContents) {
-        return SessionTabHelperJni.get().idForTab(webContents);
-    }
-
-    @NativeMethods
-    interface Natives {
-        int idForTab(WebContents webContents);
-    }
-}
diff --git a/chrome/android/modules/chime/internal/BUILD.gn b/chrome/android/modules/chime/internal/BUILD.gn
index ec7fae0..46a4bda 100644
--- a/chrome/android/modules/chime/internal/BUILD.gn
+++ b/chrome/android/modules/chime/internal/BUILD.gn
@@ -7,9 +7,8 @@
 # Upstream chime DFM implementation which does nothing, the actual
 # implementation lives in downstream repo.
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/modules/chime/ChimeModuleEntryImpl.java",
-  ]
+  sources =
+      [ "java/src/org/chromium/chrome/modules/chime/ChimeModuleEntryImpl.java" ]
 
   deps = [
     "//base:base_java",
diff --git a/chrome/android/modules/stack_unwinder/internal/BUILD.gn b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
index 43fd990..27a75fa 100644
--- a/chrome/android/modules/stack_unwinder/internal/BUILD.gn
+++ b/chrome/android/modules/stack_unwinder/internal/BUILD.gn
@@ -6,9 +6,7 @@
 import("//chrome/android/modules/buildflags.gni")
 
 android_library("java") {
-  sources = [
-    "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderProviderImpl.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/modules/stack_unwinder/StackUnwinderProviderImpl.java" ]
   deps = [
     "//base:base_java",
     "//chrome/android/features/stack_unwinder/internal:java",
@@ -22,15 +20,11 @@
 # component target must be named according to the feature, so that the component
 # build's .cr.co library is named properly (ie. libstack_unwinder.cr.so).
 group("native") {
-  deps = [
-    ":stack_unwinder",
-  ]
+  deps = [ ":stack_unwinder" ]
 }
 
 component("stack_unwinder") {
-  sources = [
-    "entrypoints.cc",
-  ]
+  sources = [ "entrypoints.cc" ]
   deps = [
     ":jni_registration",
     "//base",
diff --git a/chrome/android/third_party/compositor_animator/BUILD.gn b/chrome/android/third_party/compositor_animator/BUILD.gn
index a0efda7..d1b467310 100644
--- a/chrome/android/third_party/compositor_animator/BUILD.gn
+++ b/chrome/android/third_party/compositor_animator/BUILD.gn
@@ -6,7 +6,5 @@
 import("//build/config/android/rules.gni")
 
 android_library("compositor_animator_java") {
-  sources = [
-    "java/src/org/chromium/chrome/browser/compositor/animation/FloatProperty.java",
-  ]
+  sources = [ "java/src/org/chromium/chrome/browser/compositor/animation/FloatProperty.java" ]
 }
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn
index e600a817..473f75a 100644
--- a/chrome/android/webapk/libs/runtime_library/BUILD.gn
+++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -16,9 +16,7 @@
 android_aidl("webapk_service_aidl") {
   import_include = [ "src/org/chromium/webapk/lib/runtime_library" ]
   interface_file = "src/org/chromium/webapk/lib/runtime_library/common.aidl"
-  sources = [
-    "src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl",
-  ]
+  sources = [ "src/org/chromium/webapk/lib/runtime_library/IWebApkApi.aidl" ]
 }
 
 # A standalone jar for the aidl's generated java files so that multiple places
@@ -31,20 +29,17 @@
 # library because the dx tool expects files ending in .dex.jar
 android_library("runtime_library_for_assets_java") {
   jacoco_never_instrument = true
-  sources = [
-    "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java",
-  ]
+  sources =
+      [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   srcjar_deps = [ ":webapk_service_aidl" ]
-  deps = [
-    "//third_party/android_deps:com_android_support_support_compat_java",
-  ]
+  deps =
+      [ "//third_party/android_deps:com_android_support_support_compat_java" ]
 }
 
 # The subset of runtime_library_from_assets_java needed for tests.
 android_library("runtime_library_for_tests_java") {
-  sources = [
-    "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java",
-  ]
+  sources =
+      [ "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java" ]
   deps = [
     ":webapk_service_aidl_java",
     "//third_party/android_deps:com_android_support_support_compat_java",
@@ -52,9 +47,7 @@
 }
 
 proguarded_dist_dex("webapk_runtime_library") {
-  deps = [
-    ":runtime_library_for_assets_java",
-  ]
+  deps = [ ":runtime_library_for_assets_java" ]
   proguard_configs = [
     "runtime_library.proguard.flags",
     "//base/android/proguard/chromium_code.flags",
@@ -71,16 +64,12 @@
     "$target_out_dir/$runtime_library_dex_asset_name",
   ]
 
-  deps = [
-    ":webapk_runtime_library",
-  ]
+  deps = [ ":webapk_runtime_library" ]
 }
 
 android_library("runtime_library_javatests") {
   testonly = true
-  sources = [
-    "javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java",
-  ]
+  sources = [ "javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java" ]
   deps = [
     ":runtime_library_for_tests_java",
     ":webapk_service_aidl_java",
diff --git a/chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service/BUILD.gn b/chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service/BUILD.gn
index 3241619..85f81dd 100644
--- a/chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service/BUILD.gn
+++ b/chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service/BUILD.gn
@@ -15,9 +15,7 @@
 
   android_manifest = "AndroidManifest.xml"
   apk_name = "ApkWithWebApkService"
-  sources = [
-    "src/org/chromium/webapk/lib/runtime_library/test/TestWebApkServiceImplWrapper.java",
-  ]
+  sources = [ "src/org/chromium/webapk/lib/runtime_library/test/TestWebApkServiceImplWrapper.java" ]
   deps = [
     "//chrome/android/webapk/libs/runtime_library:runtime_library_for_tests_java",
     "//chrome/android/webapk/libs/runtime_library:webapk_service_aidl_java",
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 76e6c688..9c099eae 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3183,10 +3183,10 @@
   <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_DISABLED" desc="Sub label for the Google Assistant button when Assistant is disabled.">
     Disabled
   </message>
-  <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ON" desc="Row label in Google Assistant settings." meaning="Google Assistant is off.">
+  <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ON" desc="Row label in Google Assistant settings." meaning="Google Assistant is on.">
     On
   </message>
-  <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_OFF" desc="Row label in Google Assistant settings." meaning="Google Assistant is on.">
+  <message name="IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_OFF" desc="Row label in Google Assistant settings." meaning="Google Assistant is off.">
     Off
   </message>
 </if>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7230721..7e499872 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2635,7 +2635,6 @@
       "android/send_tab_to_self/send_tab_to_self_model_observer_bridge.h",
       "android/service_tab_launcher.cc",
       "android/service_tab_launcher.h",
-      "android/sessions/session_tab_helper_android.cc",
       "android/shortcut_helper.cc",
       "android/shortcut_helper.h",
       "android/shortcut_info.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 5667b68..72885fe6 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1353,7 +1353,8 @@
         {QuietNotificationPermissionUiConfig::kEnableAdaptiveActivation,
          "true"},
         {QuietNotificationPermissionUiConfig::kEnableCrowdDenyTriggering,
-         "true"}};
+         "true"},
+        {QuietNotificationPermissionUiConfig::kCrowdDenyHoldBackChance, "0"}};
 
 // The default "Enabled" option has the semantics of showing the quiet UI
 // (animated location bar indicator on Desktop, and mini-infobars on Android),
diff --git a/chrome/browser/android/sessions/session_tab_helper_android.cc b/chrome/browser/android/sessions/session_tab_helper_android.cc
deleted file mode 100644
index 8edf06c..0000000
--- a/chrome/browser/android/sessions/session_tab_helper_android.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/android/jni_android.h"
-#include "chrome/android/chrome_jni_headers/SessionTabHelper_jni.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
-#include "content/public/browser/web_contents.h"
-
-using base::android::JavaParamRef;
-
-// static
-jint JNI_SessionTabHelper_IdForTab(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& java_web_contents) {
-  content::WebContents* web_contents =
-      content::WebContents::FromJavaWebContents(java_web_contents);
-  CHECK(web_contents);
-  return SessionTabHelper::IdForTab(web_contents).id();
-}
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn
index 74ef15a..6bd1ee92 100644
--- a/chrome/browser/android/vr/BUILD.gn
+++ b/chrome/browser/android/vr/BUILD.gn
@@ -127,9 +127,7 @@
     deps += [ ":ar_jni_headers" ]
   }
 
-  public_deps = [
-    "//device/vr/public/mojom",
-  ]
+  public_deps = [ "//device/vr/public/mojom" ]
 
   libs = [ "android" ]
 
@@ -145,12 +143,8 @@
 
 # The VR UI module factory interface.
 source_set("ui_factory") {
-  sources = [
-    "ui_factory.h",
-  ]
-  deps = [
-    "//chrome/browser/vr:vr_base",
-  ]
+  sources = [ "ui_factory.h" ]
+  deps = [ "//chrome/browser/vr:vr_base" ]
 }
 
 # The default UI factory implementation, which simply instantiates an object.
@@ -188,13 +182,9 @@
 # vr_android_with_factory).
 group("module_factory") {
   if (use_native_partitions) {
-    deps = [
-      ":ui_module_factory",
-    ]
+    deps = [ ":ui_module_factory" ]
   } else {
-    deps = [
-      ":ui_default_factory",
-    ]
+    deps = [ ":ui_default_factory" ]
   }
 }
 
@@ -205,9 +195,7 @@
     "//third_party/arcore-android-sdk-client:com_google_ar_core_java",
   ]
 
-  sources = [
-    "//chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java",
-  ]
+  sources = [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java" ]
 }
 
 if (enable_arcore) {
@@ -229,9 +217,7 @@
 }
 
 group("test_support") {
-  public_deps = [
-    ":ui_default_factory",
-  ]
+  public_deps = [ ":ui_default_factory" ]
 }
 
 test("vr_android_unittests") {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 99ea5da..7389669 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -120,7 +120,6 @@
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "chrome/browser/safe_browsing/url_checker_delegate_impl.h"
 #include "chrome/browser/search/search.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/sharing/sms/sms_remote_fetcher.h"
 #include "chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h"
 #include "chrome/browser/signin/chrome_signin_url_loader_throttle.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f82e63c..46c5bc0 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -319,9 +319,7 @@
     "//ui/wm/public",
     "//url",
   ]
-  data_deps = [
-    ":dbus_service_files",
-  ]
+  data_deps = [ ":dbus_service_files" ]
 
   allow_circular_includes_from = [
     "//chrome/browser/extensions",
@@ -2461,9 +2459,7 @@
     "dbus/org.chromium.VmApplicationsService.conf",
   ]
   output_conf_file = "$root_out_dir/dbus/chrome_dbus_services.conf"
-  outputs = [
-    output_conf_file,
-  ]
+  outputs = [ output_conf_file ]
 
   script = "//chromeos/tools/concat_dbus_conf_files.py"
   args = [ rebase_path(output_conf_file, root_build_dir) ]
@@ -3076,9 +3072,7 @@
     ]
   }
 
-  public_deps = [
-    ":chromeos",
-  ]
+  public_deps = [ ":chromeos" ]
   deps = [
     ":arc_test_support",
     ":attestation_proto",
@@ -3191,53 +3185,37 @@
     "//ui/events/devices:test_support",
     "//ui/shell_dialogs",
   ]
-  data = [
-    "//chromeos/test/data/",
-  ]
+  data = [ "//chromeos/test/data/" ]
 }
 
 proto_library("attestation_proto") {
-  sources = [
-    "attestation/attestation_key_payload.proto",
-  ]
+  sources = [ "attestation/attestation_key_payload.proto" ]
 }
 
 proto_library("screen_brightness_event_proto") {
-  sources = [
-    "power/ml/screen_brightness_event.proto",
-  ]
+  sources = [ "power/ml/screen_brightness_event.proto" ]
 }
 
 proto_library("user_charging_event_proto") {
-  sources = [
-    "power/smart_charging/user_charging_event.proto",
-  ]
+  sources = [ "power/smart_charging/user_charging_event.proto" ]
 }
 
 proto_library("user_activity_event_proto") {
-  sources = [
-    "power/ml/user_activity_event.proto",
-  ]
+  sources = [ "power/ml/user_activity_event.proto" ]
 }
 
 proto_library("backdrop_wallpaper_proto") {
-  sources = [
-    "backdrop_wallpaper_handlers/backdrop_wallpaper.proto",
-  ]
+  sources = [ "backdrop_wallpaper_handlers/backdrop_wallpaper.proto" ]
   generate_python = false
 }
 
 proto_library("device_configuration_proto") {
-  sources = [
-    "login/screens/recommend_apps/device_configuration.proto",
-  ]
+  sources = [ "login/screens/recommend_apps/device_configuration.proto" ]
   generate_python = false
 }
 
 proto_library("print_job_info_proto") {
-  sources = [
-    "printing/history/print_job_info.proto",
-  ]
+  sources = [ "printing/history/print_job_info.proto" ]
 }
 
 device_policy_remover_path = "$target_gen_dir/device_policy_remover.cc"
@@ -3263,9 +3241,7 @@
     chrome_device_policy_pb2_path,
   ]
 
-  outputs = [
-    device_policy_remover_path,
-  ]
+  outputs = [ device_policy_remover_path ]
 
   args = [
     # generated file name
@@ -3284,13 +3260,9 @@
 }
 
 static_library("device_policy_remover_generated") {
-  sources = [
-    device_policy_remover_path,
-  ]
+  sources = [ device_policy_remover_path ]
 
-  public_deps = [
-    ":device_policy_remover_generate",
-  ]
+  public_deps = [ ":device_policy_remover_generate" ]
 }
 
 fuzzer_test("smb_url_fuzzer") {
@@ -3314,9 +3286,7 @@
 }
 
 fuzzer_test("zeroconf_printer_detector_fuzzer") {
-  sources = [
-    "printing/zeroconf_printer_detector_fuzzer.cc",
-  ]
+  sources = [ "printing/zeroconf_printer_detector_fuzzer.cc" ]
   deps = [
     "//base/test:test_support",
     "//chrome/browser",
@@ -3326,9 +3296,7 @@
 
 if (use_libfuzzer) {
   fuzzer_test("policy_fuzzer") {
-    sources = [
-      "policy/fuzzer/policy_fuzzer.cc",
-    ]
+    sources = [ "policy/fuzzer/policy_fuzzer.cc" ]
 
     deps = [
       ":policy_fuzzer_proto",
@@ -3340,9 +3308,7 @@
   }
 
   fuzzable_proto_library("policy_fuzzer_proto") {
-    sources = [
-      "policy/fuzzer/policy_fuzzer.proto",
-    ]
+    sources = [ "policy/fuzzer/policy_fuzzer.proto" ]
 
     import_dirs = [ "//components/policy/proto" ]
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.cc b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
index d4bc7328..2a16d85 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_panel.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_panel.cc
@@ -82,14 +82,6 @@
   widget_->Close();
 }
 
-const views::Widget* AccessibilityPanel::GetWidget() const {
-  return widget_;
-}
-
-views::Widget* AccessibilityPanel::GetWidget() {
-  return widget_;
-}
-
 content::WebContents* AccessibilityPanel::GetWebContents() {
   return web_contents_;
 }
@@ -102,6 +94,10 @@
   return web_view_;
 }
 
+const views::Widget* AccessibilityPanel::GetWidgetImpl() const {
+  return widget_;
+}
+
 bool AccessibilityPanel::HandleContextMenu(
     content::RenderFrameHost* render_frame_host,
     const content::ContextMenuParams& params) {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_panel.h b/chrome/browser/chromeos/accessibility/accessibility_panel.h
index 1e68396..5cfa4311 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_panel.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_panel.h
@@ -38,8 +38,6 @@
   void Close();
 
   // WidgetDelegate:
-  const views::Widget* GetWidget() const override;
-  views::Widget* GetWidget() override;
   void DeleteDelegate() override;
   views::View* GetContentsView() override;
 
@@ -50,6 +48,9 @@
  private:
   class AccessibilityPanelWebContentsObserver;
 
+  // WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // content::WebContentsDelegate:
   bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
                          const content::ContextMenuParams& params) override;
diff --git a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.h b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.h
index 8c92710..8003fd00 100644
--- a/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.h
+++ b/chrome/browser/chromeos/arc/enterprise/arc_enterprise_reporting_service.h
@@ -12,7 +12,6 @@
 #include "base/threading/thread_checker.h"
 #include "components/arc/mojom/enterprise_reporting.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace content {
 class BrowserContext;
diff --git a/chrome/browser/chromeos/external_protocol_dialog.cc b/chrome/browser/chromeos/external_protocol_dialog.cc
index ab813b92..ed234e4 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.cc
+++ b/chrome/browser/chromeos/external_protocol_dialog.cc
@@ -111,10 +111,6 @@
   return message_box_view_;
 }
 
-const views::Widget* ExternalProtocolDialog::GetWidget() const {
-  return message_box_view_->GetWidget();
-}
-
-views::Widget* ExternalProtocolDialog::GetWidget() {
+const views::Widget* ExternalProtocolDialog::GetWidgetImpl() const {
   return message_box_view_->GetWidget();
 }
diff --git a/chrome/browser/chromeos/external_protocol_dialog.h b/chrome/browser/chromeos/external_protocol_dialog.h
index 08a4cc9..f9e83e5 100644
--- a/chrome/browser/chromeos/external_protocol_dialog.h
+++ b/chrome/browser/chromeos/external_protocol_dialog.h
@@ -35,10 +35,11 @@
   base::string16 GetWindowTitle() const override;
   void DeleteDelegate() override;
   views::View* GetContentsView() override;
-  const views::Widget* GetWidget() const override;
-  views::Widget* GetWidget() override;
 
  private:
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // The message box view whose commands we handle.
   views::MessageBoxView* message_box_view_;
 
diff --git a/chrome/browser/extensions/default_extensions/BUILD.gn b/chrome/browser/extensions/default_extensions/BUILD.gn
index 77a0554..4cf3f01 100644
--- a/chrome/browser/extensions/default_extensions/BUILD.gn
+++ b/chrome/browser/extensions/default_extensions/BUILD.gn
@@ -4,12 +4,8 @@
 
 if (is_win) {
   copy("default_extensions") {
-    sources = [
-      "external_extensions.json",
-    ]
-    outputs = [
-      "$root_out_dir/extensions/{{source_file_part}}",
-    ]
+    sources = [ "external_extensions.json" ]
+    outputs = [ "$root_out_dir/extensions/{{source_file_part}}" ]
   }
 } else {
   # No-op on non-Windows.
diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc
index fc115a5..9d72f75f 100644
--- a/chrome/browser/extensions/process_management_browsertest.cc
+++ b/chrome/browser/extensions/process_management_browsertest.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
index 7818205..a124624 100644
--- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
+++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
@@ -19,7 +19,6 @@
 #include "chrome/browser/native_file_system/native_file_system_permission_request_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/common/chrome_paths.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/notifications/scheduler/BUILD.gn b/chrome/browser/notifications/scheduler/BUILD.gn
index 02f3321..b500b3d 100644
--- a/chrome/browser/notifications/scheduler/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/BUILD.gn
@@ -3,13 +3,9 @@
 # found in the LICENSE file.
 
 group("scheduler") {
-  deps = [
-    ":factory",
-  ]
+  deps = [ ":factory" ]
 
-  public_deps = [
-    "//chrome/browser/notifications/scheduler/public",
-  ]
+  public_deps = [ "//chrome/browser/notifications/scheduler/public" ]
 }
 
 # The embedder can depend on this target to get the internal library.
diff --git a/chrome/browser/notifications/scheduler/public/BUILD.gn b/chrome/browser/notifications/scheduler/public/BUILD.gn
index 020c9a7b..8165e53 100644
--- a/chrome/browser/notifications/scheduler/public/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/public/BUILD.gn
@@ -46,17 +46,13 @@
 
 if (is_android) {
   java_cpp_enum("jni_enums") {
-    sources = [
-      "notification_scheduler_types.h",
-    ]
+    sources = [ "notification_scheduler_types.h" ]
   }
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "schedule_service_utils_unittest.cc",
-  ]
+  sources = [ "schedule_service_utils_unittest.cc" ]
 
   deps = [
     "//chrome/browser/notifications/scheduler/public",
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
index 8877191..421e0b82 100644
--- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -876,6 +876,10 @@
           optimization_metadata->performance_hints_metadata =
               optimization.performance_hints_metadata();
           break;
+        case optimization_guide::proto::Optimization::kPublicImageMetadata:
+          optimization_metadata->public_image_metadata =
+              optimization.public_image_metadata();
+          break;
         default:
           NOTREACHED();
           break;
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
index ba9562d..6ab06494 100644
--- a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
@@ -1482,6 +1482,44 @@
             optimization_type_decision);
 }
 
+TEST_F(OptimizationGuideHintsManagerTest,
+       CanApplyOptimizationAndPopulatesPublicImageMetadata) {
+  optimization_guide::proto::Configuration config;
+  optimization_guide::proto::Hint* hint = config.add_hints();
+  hint->set_key("somedomain.org");
+  hint->set_key_representation(optimization_guide::proto::HOST_SUFFIX);
+  hint->set_version("someversion");
+  optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
+  page_hint->set_page_pattern("/news/");
+  optimization_guide::proto::Optimization* opt =
+      page_hint->add_whitelisted_optimizations();
+  opt->set_optimization_type(optimization_guide::proto::COMPRESS_PUBLIC_IMAGES);
+  opt->mutable_public_image_metadata()->add_url("someimage");
+
+  ProcessHints(config, "1.0.0.0");
+
+  std::unique_ptr<content::MockNavigationHandle> navigation_handle =
+      CreateMockNavigationHandleWithOptimizationGuideWebContentsObserver(
+          url_with_hints());
+  base::RunLoop run_loop;
+  hints_manager()->OnNavigationStartOrRedirect(navigation_handle.get(),
+                                               run_loop.QuitClosure());
+  run_loop.Run();
+
+  optimization_guide::OptimizationMetadata optimization_metadata;
+  optimization_guide::OptimizationTypeDecision optimization_type_decision =
+      hints_manager()->CanApplyOptimization(
+          navigation_handle.get(),
+          optimization_guide::proto::COMPRESS_PUBLIC_IMAGES,
+          &optimization_metadata);
+  // Make sure public images metadata is populated.
+  EXPECT_EQ(1, optimization_metadata.public_image_metadata.url_size());
+
+  // Make sure decisions are logged correctly.
+  EXPECT_EQ(optimization_guide::OptimizationTypeDecision::kAllowedByHint,
+            optimization_type_decision);
+}
+
 TEST_F(OptimizationGuideHintsManagerTest, IsGoogleURL) {
   const struct {
     const char* url;
diff --git a/chrome/browser/permissions/contextual_notification_permission_ui_selector.cc b/chrome/browser/permissions/contextual_notification_permission_ui_selector.cc
index 9534605..71e3881 100644
--- a/chrome/browser/permissions/contextual_notification_permission_ui_selector.cc
+++ b/chrome/browser/permissions/contextual_notification_permission_ui_selector.cc
@@ -10,6 +10,7 @@
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/rand_util.h"
 #include "base/task/post_task.h"
 #include "base/time/default_clock.h"
 #include "chrome/browser/browser_process.h"
@@ -80,6 +81,20 @@
   return UiToUse::kNormalUi;
 }
 
+// Roll the dice to decide whether to use the normal UI even when the crowd data
+// suggests that a site is sending unsolicited prompts. This creates a control
+// group of normal UI prompt impressions, which facilitates comparing acceptance
+// rates, better calibrating server-side logic, and detecting when the
+// notification experience on the site has improved.
+bool ShouldHoldBackQuietUI() {
+  const double chance =
+      QuietNotificationPermissionUiConfig::GetCrowdDenyHoldBackChance();
+  // Avoid rolling a dice if the chance is 0.
+  const bool result = chance && base::RandDouble() < chance;
+  base::UmaHistogramBoolean("Permissions.CrowdDeny.DidHoldbackQuietUi", result);
+  return result;
+}
+
 }  // namespace
 
 ContextualNotificationPermissionUiSelector::
@@ -149,7 +164,7 @@
 
 void ContextualNotificationPermissionUiSelector::OnCrowdDenyTriggerEvaluated(
     UiToUse ui_to_use) {
-  if (ui_to_use == UiToUse::kQuietUi) {
+  if (ui_to_use == UiToUse::kQuietUi && !ShouldHoldBackQuietUI()) {
     Notify(UiToUse::kQuietUi, QuietUiReason::kTriggeredByCrowdDeny);
     return;
   }
@@ -170,3 +185,5 @@
   DCHECK_EQ(ui_to_use == UiToUse::kQuietUi, !!quiet_ui_reason);
   std::move(callback_).Run(ui_to_use, quiet_ui_reason);
 }
+
+// static
diff --git a/chrome/browser/permissions/crowd_deny_preload_data.h b/chrome/browser/permissions/crowd_deny_preload_data.h
index aed131f9..08c1a89 100644
--- a/chrome/browser/permissions/crowd_deny_preload_data.h
+++ b/chrome/browser/permissions/crowd_deny_preload_data.h
@@ -12,15 +12,12 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/permissions/crowd_deny.pb.h"
+#include "url/origin.h"
 
 namespace base {
 class SequencedTaskRunner;
 }
 
-namespace url {
-class Origin;
-}
-
 namespace base {
 class FilePath;
 }
@@ -54,6 +51,16 @@
   // in binary wire format from the file at |preload_data_path|.
   void LoadFromDisk(const base::FilePath& preload_data_path);
 
+  // Sets the notification UX for a particular origin. Only used for testing.
+  void set_origin_notification_user_experience_for_testing(
+      const url::Origin& origin,
+      chrome_browser_crowd_deny::
+          SiteReputation_NotificationUserExperienceQuality quality) {
+    domain_to_reputation_map_[origin.host()] = SiteReputation();
+    domain_to_reputation_map_[origin.host()].set_notification_ux_quality(
+        quality);
+  }
+
  private:
   void set_site_reputations(DomainToReputationMap map) {
     domain_to_reputation_map_ = std::move(map);
diff --git a/chrome/browser/permissions/permission_request_manager_unittest.cc b/chrome/browser/permissions/permission_request_manager_unittest.cc
index 6e70557..1db8b72 100644
--- a/chrome/browser/permissions/permission_request_manager_unittest.cc
+++ b/chrome/browser/permissions/permission_request_manager_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <stddef.h>
+#include <string>
 
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -16,6 +17,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/permissions/adaptive_quiet_notification_permission_ui_enabler.h"
+#include "chrome/browser/permissions/crowd_deny_preload_data.h"
 #include "chrome/browser/permissions/mock_permission_request.h"
 #include "chrome/browser/permissions/notification_permission_ui_selector.h"
 #include "chrome/browser/permissions/permission_request.h"
@@ -966,3 +968,56 @@
   EXPECT_TRUE(request->granted());
 }
 #endif  // defined(OS_CHROMEOS)
+
+TEST_F(PermissionRequestManagerTest, TestCrowdDenyHoldbackChance) {
+  const struct {
+    std::string holdback_chance;
+    bool enabled_in_prefs;
+    bool expect_quiet_ui;
+    bool expect_histogram_bucket;
+  } kTestCases[] = {
+      // 100% chance to holdback, the UI used should be the normal UI.
+      {"1.0", false, false, true},
+      // 0% chance to holdback, the UI used should be the quiet UI.
+      {"0.0", false, true, false},
+      // 100% chance to holdback but the quiet UI is enabled by the user in
+      // prefs, the UI used should be the quiet UI.
+      {"1.0", true, true, true},
+  };
+
+  GURL url("https://spammy.com");
+  CrowdDenyPreloadData::GetInstance()
+      ->set_origin_notification_user_experience_for_testing(
+          url::Origin::Create(url),
+          CrowdDenyPreloadData::SiteReputation::UNSOLICITED_PROMPTS);
+
+  for (const auto& test : kTestCases) {
+    base::HistogramTester histograms;
+
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeatureWithParameters(
+        features::kQuietNotificationPrompts,
+        {{QuietNotificationPermissionUiConfig::kEnableAdaptiveActivation,
+          "true"},
+         {QuietNotificationPermissionUiConfig::kEnableCrowdDenyTriggering,
+          "true"},
+         {QuietNotificationPermissionUiConfig::kCrowdDenyHoldBackChance,
+          test.holdback_chance}});
+
+    if (test.enabled_in_prefs)
+      QuietNotificationPermissionUiState::EnableQuietUiInPrefs(profile());
+
+    MockPermissionRequest request(
+        "request", PermissionRequestType::PERMISSION_NOTIFICATIONS, url);
+
+    manager_->AddRequest(&request);
+    WaitForBubbleToBeShown();
+    EXPECT_EQ(test.expect_quiet_ui, manager_->ShouldCurrentRequestUseQuietUI());
+    Closing();
+
+    histograms.ExpectBucketCount(
+        "Permissions.CrowdDeny.DidHoldbackQuietUi",
+        static_cast<base::HistogramBase::Sample>(test.expect_histogram_bucket),
+        1);
+  }
+}
diff --git a/chrome/browser/permissions/quiet_notification_permission_ui_config.cc b/chrome/browser/permissions/quiet_notification_permission_ui_config.cc
index 1b825ca..92e8b4b 100644
--- a/chrome/browser/permissions/quiet_notification_permission_ui_config.cc
+++ b/chrome/browser/permissions/quiet_notification_permission_ui_config.cc
@@ -16,6 +16,10 @@
     "enable_crowd_deny_triggering";
 
 // static
+const char QuietNotificationPermissionUiConfig::kCrowdDenyHoldBackChance[] =
+    "crowd_deny_hold_back_chance";
+
+// static
 bool QuietNotificationPermissionUiConfig::IsAdaptiveActivationEnabled() {
   if (!base::FeatureList::IsEnabled(features::kQuietNotificationPrompts))
     return false;
@@ -34,3 +38,9 @@
       features::kQuietNotificationPrompts, kEnableCrowdDenyTriggering,
       false /* default */);
 }
+
+// static
+double QuietNotificationPermissionUiConfig::GetCrowdDenyHoldBackChance() {
+  return base::GetFieldTrialParamByFeatureAsDouble(
+      features::kQuietNotificationPrompts, kCrowdDenyHoldBackChance, 0);
+}
diff --git a/chrome/browser/permissions/quiet_notification_permission_ui_config.h b/chrome/browser/permissions/quiet_notification_permission_ui_config.h
index 70473cf..f847c1b 100644
--- a/chrome/browser/permissions/quiet_notification_permission_ui_config.h
+++ b/chrome/browser/permissions/quiet_notification_permission_ui_config.h
@@ -21,6 +21,14 @@
   // rate.
   static const char kEnableCrowdDenyTriggering[];
 
+  // Name of the variation parameter that represents the chance that a
+  // quiet notifications permission prompt UI triggered by crowd deny will be
+  // replaced by the normal UI. This ensures that a small percentage of
+  // permission requests still use the normal UI and allows sites to recover
+  // from a bad reputation score. Represented as a number in the [0,1] interval.
+  // If the quiet UI is enabled in preferences, the quiet UI is always used.
+  static const char kCrowdDenyHoldBackChance[];
+
   // Whether or not adaptive activation is enabled. Adaptive activation means
   // that quiet notifications permission prompts will be turned on after three
   // consecutive prompt denies.
@@ -30,6 +38,11 @@
   // sites with a low notification permission grant rate, the quiet UI will be
   // shown as a one-off, even when it is not turned on for all sites in prefs.
   static bool IsCrowdDenyTriggeringEnabled();
+
+  // The chance that a quiet notifications permission prompt UI triggered by
+  // crowd deny will be replaced by the normal UI. This is per individual
+  // permission prompt.
+  static double GetCrowdDenyHoldBackChance();
 };
 
 #endif  // CHROME_BROWSER_PERMISSIONS_QUIET_NOTIFICATION_PERMISSION_UI_CONFIG_H_
diff --git a/chrome/browser/plugins/plugin_info_host_impl.h b/chrome/browser/plugins/plugin_info_host_impl.h
index cd0de67..fe765f7 100644
--- a/chrome/browser/plugins/plugin_info_host_impl.h
+++ b/chrome/browser/plugins/plugin_info_host_impl.h
@@ -24,7 +24,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/buildflags/buildflags.h"
 #include "media/media_buildflags.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 
 class GURL;
 class HostContentSettingsMap;
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index d739854..ba8df24 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -440,6 +440,8 @@
      */
     public static final String REACHED_CODE_PROFILER_GROUP = "reached_code_profiler_group";
 
+    public static final String RLZ_NOTIFIED = "rlz_first_search_notified";
+
     /**
      * Generic signin and sync promo preferences.
      */
@@ -707,6 +709,7 @@
                 PRIVACY_NETWORK_PREDICTIONS,
                 PROMOS_SKIPPED_ON_FIRST_START,
                 REACHED_CODE_PROFILER_GROUP,
+                RLZ_NOTIFIED,
                 SIGNIN_AND_SYNC_PROMO_SHOW_COUNT,
                 SIGNIN_PROMO_IMPRESSIONS_COUNT_BOOKMARKS,
                 SIGNIN_PROMO_IMPRESSIONS_COUNT_SETTINGS,
diff --git a/chrome/browser/reputation/BUILD.gn b/chrome/browser/reputation/BUILD.gn
index bbcd9b1..74fe53b 100644
--- a/chrome/browser/reputation/BUILD.gn
+++ b/chrome/browser/reputation/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "safety_tips.proto",
-  ]
+  sources = [ "safety_tips.proto" ]
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
index 159786c..942fc77 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -2010,7 +2010,8 @@
       });
 });
 
-TEST_F('ChromeVoxBackgroundTest', 'PopUpButtonSetSize', function() {
+// See https://crbug.com/997688
+TEST_F('ChromeVoxBackgroundTest', 'DISABLED_PopUpButtonSetSize', function() {
   var mockFeedback = this.createMockFeedback();
   this.runWithLoadedTree(
       `
diff --git a/chrome/browser/resources/explore_sites_internals/BUILD.gn b/chrome/browser/resources/explore_sites_internals/BUILD.gn
index a308c70d..2b09c61 100644
--- a/chrome/browser/resources/explore_sites_internals/BUILD.gn
+++ b/chrome/browser/resources/explore_sites_internals/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_type_check("closure_compile") {
-  deps = [
-    ":explore_sites_internals",
-  ]
+  deps = [ ":explore_sites_internals" ]
 }
 
 js_library("explore_sites_internals") {
diff --git a/chrome/browser/resources/offline_pages/BUILD.gn b/chrome/browser/resources/offline_pages/BUILD.gn
index c008bad..4465cf5 100644
--- a/chrome/browser/resources/offline_pages/BUILD.gn
+++ b/chrome/browser/resources/offline_pages/BUILD.gn
@@ -21,7 +21,5 @@
 }
 
 js_library("offline_internals_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
 }
diff --git a/chrome/browser/resources/safe_browsing/BUILD.gn b/chrome/browser/resources/safe_browsing/BUILD.gn
index 89a3efd..d4ea993 100644
--- a/chrome/browser/resources/safe_browsing/BUILD.gn
+++ b/chrome/browser/resources/safe_browsing/BUILD.gn
@@ -34,18 +34,14 @@
     target_arch = "unknown_target_arch"
   }
 
-  inputs = [
-    input_filename,
-  ]
+  inputs = [ input_filename ]
 
   deps = [
     "//chrome/common/safe_browsing:proto",
     "//third_party/protobuf:py_proto",
   ]
 
-  outputs = [
-    "$output_dir/$output_basename",
-  ]
+  outputs = [ "$output_dir/$output_basename" ]
 
   args = [
     "-w",
@@ -75,9 +71,7 @@
   python_path_root = "$root_build_dir/pyproto"
   python_path_safe_browsing = "$python_path_root/chrome/common/safe_browsing"
 
-  inputs = [
-    input_filename,
-  ]
+  inputs = [ input_filename ]
 
   deps = [
     "//chrome/common/safe_browsing:proto",
@@ -85,9 +79,7 @@
   ]
 
   # A directory, since we can't derive the actual file names here.
-  outputs = [
-    output_dir,
-  ]
+  outputs = [ output_dir ]
 
   args = [
     "-w",
diff --git a/chrome/browser/resources/tab_strip/BUILD.gn b/chrome/browser/resources/tab_strip/BUILD.gn
index c95b0b72..1463f06 100644
--- a/chrome/browser/resources/tab_strip/BUILD.gn
+++ b/chrome/browser/resources/tab_strip/BUILD.gn
@@ -31,9 +31,7 @@
 }
 
 js_library("tabs_api_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
   externs_list = [ "$externs_path/chrome_extensions.js" ]
 }
 
@@ -57,9 +55,7 @@
 }
 
 js_library("tab_strip_embedder_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr.m",
-  ]
+  deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
 js_library("tab_strip_options") {
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc
index b6fe44a..0ff221d4 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc
@@ -80,14 +80,6 @@
   return contents_view_.get();
 }
 
-views::Widget* DeepScanningDialogViews::GetWidget() {
-  return contents_view_->GetWidget();
-}
-
-const views::Widget* DeepScanningDialogViews::GetWidget() const {
-  return contents_view_->GetWidget();
-}
-
 void DeepScanningDialogViews::DeleteDelegate() {
   delete this;
 }
@@ -126,6 +118,10 @@
 
 DeepScanningDialogViews::~DeepScanningDialogViews() = default;
 
+const views::Widget* DeepScanningDialogViews::GetWidgetImpl() const {
+  return contents_view_->GetWidget();
+}
+
 void DeepScanningDialogViews::UpdateDialog() {
   DCHECK(shown_);
   DCHECK(scan_success_.has_value());
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h
index 24c4de5b..bc52199c 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h
@@ -38,8 +38,6 @@
   bool Cancel() override;
   bool ShouldShowCloseButton() const override;
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   void DeleteDelegate() override;
   ui::ModalType GetModalType() const override;
 
@@ -50,6 +48,9 @@
  private:
   ~DeepScanningDialogViews() override;
 
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // Update the UI depending on |scan_success_|.
   void UpdateDialog();
 
diff --git a/chrome/browser/safe_browsing/download_protection/check_native_file_system_write_request.cc b/chrome/browser/safe_browsing/download_protection/check_native_file_system_write_request.cc
index 4136a88b..386d51f 100644
--- a/chrome/browser/safe_browsing/download_protection/check_native_file_system_write_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_native_file_system_write_request.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/safe_browsing/download_protection/download_feedback_service.h"
 #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
 #include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/common/safe_browsing/download_type_util.h"
 #include "chrome/common/safe_browsing/file_type_policies.h"
 #include "components/safe_browsing/core/common/utils.h"
diff --git a/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc
index c8f1001..e15a220 100644
--- a/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc
@@ -59,9 +59,6 @@
 
   ~TwoClientExtensionAppsSyncTest() override {}
 
-  // Needed for AwaitQuiescence().
-  bool TestUsesSelfNotifications() override { return true; }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(TwoClientExtensionAppsSyncTest);
 };
@@ -322,8 +319,6 @@
                        E2E_ENABLED(UpdateLaunchType)) {
   ResetSyncForPrimaryAccount();
   ASSERT_TRUE(SetupSync());
-  // Wait until sync settles before we override the apps below.
-  ASSERT_TRUE(AwaitQuiescence());
   ASSERT_TRUE(AppsMatchChecker().Wait());
 
   // Change the launch type to window.
diff --git a/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
index 116587ce..682761df 100644
--- a/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
@@ -38,8 +38,8 @@
   ASSERT_TRUE(ExtensionsMatchChecker().Wait());
 }
 
-// E2E tests flaky on Mac: https://crbug.com/597319
-#if defined(OS_MACOSX)
+// E2E tests flaky on Mac and Windows: https://crbug.com/597319
+#if defined(OS_MACOSX) || defined(OS_WIN)
 #define MAYBE_E2E(test_name) test_name
 #else
 #define MAYBE_E2E(test_name) E2E_ENABLED(test_name)
diff --git a/chrome/browser/task_manager/task_manager_tester.cc b/chrome/browser/task_manager/task_manager_tester.cc
index 1e13d64..2a2fd93 100644
--- a/chrome/browser/task_manager/task_manager_tester.cc
+++ b/chrome/browser/task_manager/task_manager_tester.cc
@@ -7,7 +7,6 @@
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/task_manager/task_manager_table_model.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d063bdb0..a621122 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -656,7 +656,6 @@
       "android/chrome_http_auth_handler.cc",
       "android/chrome_http_auth_handler.h",
       "android/chrome_javascript_app_modal_dialog_android.cc",
-      "android/chrome_javascript_app_modal_dialog_android.h",
       "android/color_chooser_dialog_android.cc",
       "android/content_settings/ads_blocked_infobar_delegate.cc",
       "android/content_settings/ads_blocked_infobar_delegate.h",
@@ -4169,9 +4168,7 @@
     "toolbar/test_toolbar_action_view_controller.cc",
     "toolbar/test_toolbar_action_view_controller.h",
   ]
-  public_deps = [
-    ":ui",
-  ]
+  public_deps = [ ":ui" ]
   deps = [
     "//chrome/app/theme:theme_resources",
     "//chrome/browser",
@@ -4284,16 +4281,12 @@
       "ash/keyboard/chrome_keyboard_controller_client_test_helper.cc",
       "ash/keyboard/chrome_keyboard_controller_client_test_helper.h",
     ]
-    deps = [
-      "//ash",
-    ]
+    deps = [ "//ash" ]
   }
 }
 
 if (is_android) {
   java_cpp_enum("tab_model_enums_java") {
-    sources = [
-      "android/tab_model/tab_model.h",
-    ]
+    sources = [ "android/tab_model/tab_model.h" ]
   }
 }
diff --git a/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.cc b/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.cc
index ebb22c1..dbca071 100644
--- a/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.cc
+++ b/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.cc
@@ -2,57 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.h"
+#include "chrome/browser/ui/javascript_dialogs/chrome_javascript_native_app_modal_dialog_factory.h"
 
 #include "base/android/jni_android.h"
-#include "chrome/browser/android/tab_android.h"
-#include "chrome/browser/ui/javascript_dialogs/chrome_javascript_native_app_modal_dialog_factory.h"
+#include "base/bind.h"
+#include "components/app_modal/android/javascript_app_modal_dialog_android.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
 #include "components/app_modal/javascript_dialog_manager.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-
-void ChromeJavascriptAppModalDialogAndroid::ShowAppModalDialog() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-  TabAndroid* tab = TabAndroid::FromWebContents(dialog()->web_contents());
-  if (!tab) {
-    CancelAppModalDialog();
-    return;
-  }
-
-  DoShowAppModalDialog();
-}
-
-ChromeJavascriptAppModalDialogAndroid::
-    ~ChromeJavascriptAppModalDialogAndroid() = default;
-
-namespace {
-
-class ChromeJavaScriptNativeDialogAndroidFactory
-    : public app_modal::JavaScriptNativeDialogFactory {
- public:
-  ChromeJavaScriptNativeDialogAndroidFactory() = default;
-  ~ChromeJavaScriptNativeDialogAndroidFactory() override = default;
-
- private:
-  app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog(
-      app_modal::JavaScriptAppModalDialog* dialog) override {
-    dialog->web_contents()->GetDelegate()->ActivateContents(
-        dialog->web_contents());
-    return new ChromeJavascriptAppModalDialogAndroid(
-        base::android::AttachCurrentThread(), dialog,
-        dialog->web_contents()->GetTopLevelNativeWindow());
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptNativeDialogAndroidFactory);
-};
-
-}  // namespace
 
 void InstallChromeJavaScriptNativeAppModalDialogFactory() {
   app_modal::JavaScriptDialogManager::GetInstance()->SetNativeDialogFactory(
-      base::WrapUnique(new ChromeJavaScriptNativeDialogAndroidFactory));
+      base::BindRepeating([](app_modal::JavaScriptAppModalDialog* dialog) {
+        app_modal::NativeAppModalDialog* d =
+            new app_modal::JavascriptAppModalDialogAndroid(
+                base::android::AttachCurrentThread(), dialog,
+                dialog->web_contents()->GetTopLevelNativeWindow());
+        return d;
+      }));
 }
diff --git a/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.h b/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.h
deleted file mode 100644
index a3465a3f..0000000
--- a/chrome/browser/ui/android/chrome_javascript_app_modal_dialog_android.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ANDROID_CHROME_JAVASCRIPT_APP_MODAL_DIALOG_ANDROID_H_
-#define CHROME_BROWSER_UI_ANDROID_CHROME_JAVASCRIPT_APP_MODAL_DIALOG_ANDROID_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/app_modal/android/javascript_app_modal_dialog_android.h"
-
-class ChromeJavascriptAppModalDialogAndroid
-    : public app_modal::JavascriptAppModalDialogAndroid {
- public:
-  using JavascriptAppModalDialogAndroid::JavascriptAppModalDialogAndroid;
-
-  // NativeAppModalDialog:
-  void ShowAppModalDialog() override;
-
- protected:
-  ~ChromeJavascriptAppModalDialogAndroid() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ChromeJavascriptAppModalDialogAndroid);
-};
-
-#endif  // CHROME_BROWSER_UI_ANDROID_CHROME_JAVASCRIPT_APP_MODAL_DIALOG_ANDROID_H_
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.h b/chrome/browser/ui/ash/chrome_new_window_client.h
index 6dac7289..d1756a9 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.h
+++ b/chrome/browser/ui/ash/chrome_new_window_client.h
@@ -13,7 +13,6 @@
 #include "base/macros.h"
 #include "components/arc/intent_helper/control_camera_app_delegate.h"
 #include "components/arc/intent_helper/open_url_delegate.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "url/gurl.h"
 
 namespace arc {
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
index 816c1bd..fcce6af9 100644
--- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
@@ -16,7 +16,6 @@
 #include "chrome/browser/ui/javascript_dialogs/chrome_javascript_native_app_modal_dialog_factory.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
 #include "components/app_modal/javascript_dialog_manager.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
 #include "components/remote_cocoa/app_shim/alert.h"
 #include "components/remote_cocoa/browser/application_host.h"
 #include "components/strings/grit/components_strings.h"
@@ -170,30 +169,15 @@
   return is_showing_;
 }
 
-namespace {
-
-class ChromeJavaScriptNativeDialogCocoaFactory
-    : public app_modal::JavaScriptNativeDialogFactory {
- public:
-  ChromeJavaScriptNativeDialogCocoaFactory() {}
-  ~ChromeJavaScriptNativeDialogCocoaFactory() override {}
-
- private:
-  app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog(
-      app_modal::JavaScriptAppModalDialog* dialog) override {
-    app_modal::NativeAppModalDialog* d =
-        new JavaScriptAppModalDialogCocoa(dialog);
-    dialog->web_contents()->GetDelegate()->ActivateContents(
-        dialog->web_contents());
-    return d;
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptNativeDialogCocoaFactory);
-};
-
-}  // namespace
-
 void InstallChromeJavaScriptNativeAppModalDialogFactory() {
   app_modal::JavaScriptDialogManager::GetInstance()->SetNativeDialogFactory(
-      base::WrapUnique(new ChromeJavaScriptNativeDialogCocoaFactory));
+      base::BindRepeating([](app_modal::JavaScriptAppModalDialog* dialog) {
+        app_modal::NativeAppModalDialog* d =
+            new JavaScriptAppModalDialogCocoa(dialog);
+        // Match Views by activating the tab during creation (rather than when
+        // showing).
+        dialog->web_contents()->GetDelegate()->ActivateContents(
+            dialog->web_contents());
+        return d;
+      }));
 }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index 47c4d9b1..0a16f05 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -18,7 +18,6 @@
 #include "base/time/time.h"
 #include "chrome/browser/extensions/extension_message_bubble_controller.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
index f7b9969..2bbeaf3 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/toolbar/test_toolbar_action_view_controller.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/common/extensions/api/extension_action/action_info.h"
diff --git a/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc b/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc
index 86fdf20..e3819e6 100644
--- a/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc
+++ b/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc
@@ -5,10 +5,8 @@
 #include "chrome/browser/ui/javascript_dialogs/chrome_javascript_native_app_modal_dialog_factory.h"
 
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "components/app_modal/javascript_dialog_manager.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
 #include "components/constrained_window/constrained_window_views.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
@@ -34,53 +32,42 @@
   explicit ChromeJavaScriptAppModalDialogViews(
       app_modal::JavaScriptAppModalDialog* parent)
       : app_modal::JavaScriptAppModalDialogViews(parent),
-        popunder_preventer_(new PopunderPreventer(parent->web_contents())) {}
-  ~ChromeJavaScriptAppModalDialogViews() override {}
+        popunder_preventer_(parent->web_contents()) {}
+  ~ChromeJavaScriptAppModalDialogViews() override = default;
 
  private:
-  std::unique_ptr<PopunderPreventer> popunder_preventer_;
+  PopunderPreventer popunder_preventer_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptAppModalDialogViews);
 };
 #endif
 
-class ChromeJavaScriptNativeDialogViewsFactory
-    : public app_modal::JavaScriptNativeDialogFactory {
- public:
-  ChromeJavaScriptNativeDialogViewsFactory() {}
-  ~ChromeJavaScriptNativeDialogViewsFactory() override {}
-
- private:
-  app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog(
-      app_modal::JavaScriptAppModalDialog* dialog) override {
-    app_modal::JavaScriptAppModalDialogViews* d = nullptr;
+app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog(
+    app_modal::JavaScriptAppModalDialog* dialog) {
+  app_modal::JavaScriptAppModalDialogViews* d = nullptr;
 #if defined(USE_X11)
-    d = new JavaScriptAppModalDialogViewsX11(dialog);
+  d = new JavaScriptAppModalDialogViewsX11(dialog);
 #else
-    d = new ChromeJavaScriptAppModalDialogViews(dialog);
+  d = new ChromeJavaScriptAppModalDialogViews(dialog);
 #endif
-
-    dialog->web_contents()->GetDelegate()->ActivateContents(
-        dialog->web_contents());
-    gfx::NativeWindow parent_window =
-        dialog->web_contents()->GetTopLevelNativeWindow();
+  dialog->web_contents()->GetDelegate()->ActivateContents(
+      dialog->web_contents());
+  gfx::NativeWindow parent_window =
+      dialog->web_contents()->GetTopLevelNativeWindow();
 #if defined(USE_AURA)
-    if (!parent_window->GetRootWindow()) {
-      // When we are part of a WebContents that isn't actually being displayed
-      // on the screen, we can't actually attach to it.
-      parent_window = NULL;
-    }
-#endif
-    constrained_window::CreateBrowserModalDialogViews(d, parent_window);
-    return d;
+  if (!parent_window->GetRootWindow()) {
+    // When we are part of a WebContents that isn't actually being displayed
+    // on the screen, we can't actually attach to it.
+    parent_window = nullptr;
   }
-
-  DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptNativeDialogViewsFactory);
-};
+#endif
+  constrained_window::CreateBrowserModalDialogViews(d, parent_window);
+  return d;
+}
 
 }  // namespace
 
 void InstallChromeJavaScriptNativeAppModalDialogFactory() {
   app_modal::JavaScriptDialogManager::GetInstance()->SetNativeDialogFactory(
-      base::WrapUnique(new ChromeJavaScriptNativeDialogViewsFactory));
+      base::BindRepeating(&CreateNativeJavaScriptDialog));
 }
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
index 2d200d8..e663514e 100644
--- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
+++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -78,8 +78,6 @@
   // views::WidgetDelegate:
   views::View* GetInitiallyFocusedView() override;
   void WindowClosing() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   base::string16 GetWindowTitle() const override;
   base::string16 GetAccessibleWindowTitle() const override;
   views::View* GetContentsView() override;
@@ -288,14 +286,6 @@
     GetWebDialogDelegate()->OnDialogClosed(std::string());
 }
 
-views::Widget* ConstrainedDialogWebView::GetWidget() {
-  return View::GetWidget();
-}
-
-const views::Widget* ConstrainedDialogWebView::GetWidget() const {
-  return View::GetWidget();
-}
-
 base::string16 ConstrainedDialogWebView::GetWindowTitle() const {
   return impl_->closed_via_webui() ? base::string16()
                                    : GetWebDialogDelegate()->GetDialogTitle();
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc
index 82cc44b..9e8153856 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -239,10 +239,6 @@
   *bounds = browser_view_->bounds();
 }
 
-views::Widget* DropdownBarHost::GetWidget() {
-  return host_.get();
-}
-
-const views::Widget* DropdownBarHost::GetWidget() const {
+const views::Widget* DropdownBarHost::GetWidgetImpl() const {
   return host_.get();
 }
diff --git a/chrome/browser/ui/views/dropdown_bar_host.h b/chrome/browser/ui/views/dropdown_bar_host.h
index 03f14d6..f4d89bc 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.h
+++ b/chrome/browser/ui/views/dropdown_bar_host.h
@@ -140,10 +140,6 @@
     return animation_.get();
   }
 
-  // views::WidgetDelegate:
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
-
  private:
   // Set the view whose position in the |browser_view_| view hierarchy
   // determines the z-order of |host_| relative to views with layers and
@@ -152,6 +148,9 @@
   // Implemented in platform-specific files.
   void SetHostViewNative(views::View* host_view);
 
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // The BrowserView that created us.
   BrowserView* browser_view_;
 
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
index e4ecd037..6c4e56e8 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
@@ -100,18 +100,14 @@
   return device_chooser_content_view_;
 }
 
-views::Widget* ChooserDialogView::GetWidget() {
-  return device_chooser_content_view_->GetWidget();
-}
-
-const views::Widget* ChooserDialogView::GetWidget() const {
-  return device_chooser_content_view_->GetWidget();
-}
-
 void ChooserDialogView::OnSelectionChanged() {
   DialogModelChanged();
 }
 
+const views::Widget* ChooserDialogView::GetWidgetImpl() const {
+  return device_chooser_content_view_->GetWidget();
+}
+
 void ChromeExtensionChooserDialog::ShowDialogImpl(
     std::unique_ptr<ChooserController> chooser_controller) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.h b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
index 68044c4..f882c8ea 100644
--- a/chrome/browser/ui/views/extensions/chooser_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
@@ -37,8 +37,6 @@
 
   // views::DialogDelegateView:
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
 
   // views::TableViewObserver:
   void OnSelectionChanged() override;
@@ -48,6 +46,9 @@
   }
 
  private:
+  // views::DialogDelegateView:
+  const views::Widget* GetWidgetImpl() const override;
+
   DeviceChooserContentView* device_chooser_content_view_;
 
   DISALLOW_COPY_AND_ASSIGN(ChooserDialogView);
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.cc b/chrome/browser/ui/views/extensions/extension_dialog.cc
index b2521709..648469d 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.cc
+++ b/chrome/browser/ui/views/extensions/extension_dialog.cc
@@ -131,14 +131,6 @@
   Release();
 }
 
-views::Widget* ExtensionDialog::GetWidget() {
-  return GetExtensionView()->GetWidget();
-}
-
-const views::Widget* ExtensionDialog::GetWidget() const {
-  return GetExtensionView()->GetWidget();
-}
-
 views::View* ExtensionDialog::GetContentsView() {
   return GetExtensionView();
 }
@@ -244,3 +236,7 @@
     extensions::ExtensionViewHost* host) {
   return static_cast<ExtensionViewViews*>(host->view());
 }
+
+const views::Widget* ExtensionDialog::GetWidgetImpl() const {
+  return GetExtensionView()->GetWidget();
+}
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.h b/chrome/browser/ui/views/extensions/extension_dialog.h
index be094fe0..ffe06ec 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.h
+++ b/chrome/browser/ui/views/extensions/extension_dialog.h
@@ -75,8 +75,6 @@
   base::string16 GetWindowTitle() const override;
   void WindowClosing() override;
   void DeleteDelegate() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   views::View* GetContentsView() override;
 
   // content::NotificationObserver:
@@ -105,6 +103,9 @@
   static ExtensionViewViews* GetExtensionView(
       extensions::ExtensionViewHost* host);
 
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // Window Title
   base::string16 window_title_;
 
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
index 2f07969f..28bb4c8 100644
--- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -113,10 +113,6 @@
 
   if (ShouldAnchorToAction(extension)) {
     if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
-      // TODO(pbos): Make sure this view pops out so that we can actually
-      // anchor to a visible action. Right now this view is most likely not
-      // visible, and will fall back on the default case on showing the
-      // installed dialog anchored to the general extensions toolbar button.
       ExtensionsToolbarContainer* const container =
           browser_view->toolbar_button_provider()
               ->GetExtensionsToolbarContainer();
@@ -473,7 +469,25 @@
                                        bubble_->extension(), bubble_->icon());
   bubble_reference_ = bubble_reference;
 
-  views::BubbleDialogDelegateView::CreateBubble(bubble_view_)->Show();
+  views::Widget* const widget =
+      views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
+  // When the extension is installed to the ExtensionsToolbarContainer, use the
+  // container to pop out the extension icon and show the widget. Otherwise show
+  // the widget directly.
+  if (ShouldAnchorToAction(bubble_->extension()) &&
+      base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
+    ExtensionsToolbarContainer* const container =
+        BrowserView::GetBrowserViewForBrowser(bubble_->browser())
+            ->toolbar_button_provider()
+            ->GetExtensionsToolbarContainer();
+    if (container) {
+      container->ShowWidgetForExtension(widget, bubble_->extension()->id());
+    } else {
+      widget->Show();
+    }
+  } else {
+    widget->Show();
+  }
   bubble_view_->GetWidget()->AddObserver(this);
 }
 
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
index c8a39836a..a5c9f5f 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/extensions/chrome_test_extension_loader.h"
 #include "chrome/browser/extensions/extension_action_runner.h"
 #include "chrome/browser/extensions/scripting_permissions_modifier.h"
+#include "chrome/browser/ui/extensions/extension_installed_bubble.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/extensions/extensions_menu_button.h"
@@ -58,9 +59,8 @@
   void ShowUi(const std::string& name) override {
     ui_test_name_ = name;
 
-    ClickExtensionsMenuButton();
-
     if (name == "ReloadPageBubble") {
+      ClickExtensionsMenuButton();
       TriggerSingleExtensionButton();
     } else if (ui_test_name_ == "UninstallDialog_Accept" ||
                ui_test_name_ == "UninstallDialog_Cancel") {
@@ -86,6 +86,19 @@
       // Wait for animations to finish so that the dialog should be showing.
       views::test::WaitForAnimatingLayoutManager(
           GetExtensionsToolbarContainer());
+    } else if (ui_test_name_ == "InstallDialog") {
+      LoadTestExtension("extensions/uitest/long_name");
+      LoadTestExtension("extensions/uitest/window_open");
+
+      // Trigger post-install dialog.
+      ExtensionInstalledBubble::ShowBubble(extensions_[0], browser(),
+                                           SkBitmap());
+
+      // Wait for animations to finish so that the dialog should be showing.
+      views::test::WaitForAnimatingLayoutManager(
+          GetExtensionsToolbarContainer());
+    } else {
+      ClickExtensionsMenuButton();
     }
   }
 
@@ -101,10 +114,12 @@
       EXPECT_FALSE(container->GetPoppedOutAction());
       EXPECT_FALSE(ExtensionsMenuView::IsShowing());
     } else if (ui_test_name_ == "UninstallDialog_Accept" ||
-               ui_test_name_ == "UninstallDialog_Cancel") {
+               ui_test_name_ == "UninstallDialog_Cancel" ||
+               ui_test_name_ == "InstallDialog") {
       ExtensionsToolbarContainer* const container =
           GetExtensionsToolbarContainer();
-      // With the anchored uninstall dialog the icon should now be visible.
+      // With the anchored install/uninstall dialog the icon should now be
+      // visible.
       EXPECT_TRUE(container->IsActionVisibleOnToolbar(
           container->GetActionForId(extensions_[0]->id())));
       EXPECT_TRUE(container->GetViewForId(extensions_[0]->id())->GetVisible());
@@ -120,6 +135,17 @@
       return;
     }
 
+    if (ui_test_name_ == "InstallDialog") {
+      ExtensionsToolbarContainer* const container =
+          GetExtensionsToolbarContainer();
+      views::BubbleDialogDelegateView* const install_bubble =
+          container->GetViewForId(extensions_[0]->id())
+              ->GetProperty(views::kAnchoredDialogKey);
+      ASSERT_TRUE(install_bubble);
+      install_bubble->GetWidget()->Close();
+      return;
+    }
+
     // Use default implementation for other tests.
     DialogBrowserTest::DismissUi();
   }
@@ -364,6 +390,10 @@
       browser()->tab_strip_model()->GetActiveWebContents()->GetVisibleURL());
 }
 
+IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest, InvokeUi_InstallDialog) {
+  ShowAndVerifyUi();
+}
+
 IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest,
                        InvokeUi_UninstallDialog_Accept) {
   ShowAndVerifyUi();
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
index 0a70159..9d3d697 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -107,6 +107,10 @@
   web_modal::WebContentsModalDialogManager::TestApi(manager).CloseAllDialogs();
 }
 
+const views::Widget* MediaGalleriesDialogViews::GetWidgetImpl() const {
+  return contents_->GetWidget();
+}
+
 void MediaGalleriesDialogViews::InitChildViews() {
   // Outer dialog layout.
   contents_->RemoveAllChildViews(true);
@@ -237,14 +241,6 @@
   controller_->DialogFinished(accepted_);
 }
 
-views::Widget* MediaGalleriesDialogViews::GetWidget() {
-  return contents_->GetWidget();
-}
-
-const views::Widget* MediaGalleriesDialogViews::GetWidget() const {
-  return contents_->GetWidget();
-}
-
 views::View* MediaGalleriesDialogViews::GetContentsView() {
   return contents_;
 }
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
index 452bba4..e9f60c5 100644
--- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
+++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.h
@@ -42,8 +42,6 @@
   base::string16 GetWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
   void DeleteDelegate() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   views::View* GetContentsView() override;
   bool IsDialogButtonEnabled(ui::DialogButton button) const override;
   ui::ModalType GetModalType() const override;
@@ -69,6 +67,9 @@
   // MediaGalleriesDialog:
   void AcceptDialogForTesting() override;
 
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   void InitChildViews();
 
   // Adds a checkbox or updates an existing checkbox. Returns true if a new one
diff --git a/chrome/browser/ui/views/external_protocol_dialog.cc b/chrome/browser/ui/views/external_protocol_dialog.cc
index 7f221d0..2eb4035d 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.cc
+++ b/chrome/browser/ui/views/external_protocol_dialog.cc
@@ -156,14 +156,6 @@
   return ui::MODAL_TYPE_CHILD;
 }
 
-views::Widget* ExternalProtocolDialog::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* ExternalProtocolDialog::GetWidget() const {
-  return message_box_view_->GetWidget();
-}
-
 void ExternalProtocolDialog::ShowRememberSelectionCheckbox() {
   message_box_view_->SetCheckBoxLabel(
       l10n_util::GetStringUTF16(IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT));
@@ -175,3 +167,7 @@
     ShowRememberSelectionCheckbox();
   message_box_view_->SetCheckBoxSelected(checked);
 }
+
+const views::Widget* ExternalProtocolDialog::GetWidgetImpl() const {
+  return message_box_view_->GetWidget();
+}
diff --git a/chrome/browser/ui/views/external_protocol_dialog.h b/chrome/browser/ui/views/external_protocol_dialog.h
index 662fab4..b1a714a 100644
--- a/chrome/browser/ui/views/external_protocol_dialog.h
+++ b/chrome/browser/ui/views/external_protocol_dialog.h
@@ -41,8 +41,6 @@
   bool Accept() override;
   views::View* GetContentsView() override;
   ui::ModalType GetModalType() const override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
 
  private:
   friend class test::ExternalProtocolDialogTestApi;
@@ -50,6 +48,9 @@
   void ShowRememberSelectionCheckbox();
   void SetRememberSelectionCheckboxCheckedForTesting(bool checked);
 
+  // views::DialogDelegateView:
+  const views::Widget* GetWidgetImpl() const override;
+
   const GURL url_;
   const base::string16 program_name_;
   const base::Optional<url::Origin> initiating_origin_;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 52abc1fc..553bfb1 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2400,14 +2400,6 @@
     location_bar_view->GetOmniboxView()->CloseOmniboxPopup();
 }
 
-views::Widget* BrowserView::GetWidget() {
-  return View::GetWidget();
-}
-
-const views::Widget* BrowserView::GetWidget() const {
-  return View::GetWidget();
-}
-
 void BrowserView::RevealTabStripIfNeeded() {
   if (!immersive_mode_controller_->IsEnabled())
     return;
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index dde5b3b..b464041 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -476,8 +476,6 @@
   void OnWindowBeginUserBoundsChange() override;
   void OnWindowEndUserBoundsChange() override;
   void OnWidgetMove() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   void GetAccessiblePanes(std::vector<View*>* panes) override;
 
   // views::WidgetObserver:
diff --git a/chrome/browser/ui/views/global_media_controls/overlay_media_notification_view.cc b/chrome/browser/ui/views/global_media_controls/overlay_media_notification_view.cc
index f224df8..4df2373c 100644
--- a/chrome/browser/ui/views/global_media_controls/overlay_media_notification_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/overlay_media_notification_view.cc
@@ -70,14 +70,15 @@
 
   // views::WidgetDelegate:
   bool ShouldShowWindowTitle() const override { return false; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   views::NonClientFrameView* CreateNonClientFrameView(
       views::Widget* widget) override {
     return new OverlayMediaNotificationFrameView();
   }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   // Owns OverlayMediaNotificationWidgetDelegate.
   OverlayMediaNotificationView* widget_;
 };
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
index 768b0fa..9585f43 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.cc
@@ -54,12 +54,8 @@
 namespace {
 
 std::unique_ptr<views::ImageButton> CreateCloseButton(
-    views::ButtonListener* listener,
-    SkColor color) {
+    views::ButtonListener* listener) {
   auto close_button = CreateVectorImageButton(listener);
-  SetImageFromVectorIconWithColor(
-      close_button.get(), vector_icons::kCloseRoundedIcon,
-      GetLayoutConstant(LOCATION_BAR_ICON_SIZE), color);
   close_button->SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_CLOSE));
   close_button->SetBorder(views::CreateEmptyBorder(
       gfx::Insets(GetLayoutConstant(LOCATION_BAR_CHILD_INTERIOR_PADDING))));
@@ -85,7 +81,7 @@
 // page.
 class CustomTabBarTitleOriginView : public views::View {
  public:
-  explicit CustomTabBarTitleOriginView(SkColor background_color) {
+  CustomTabBarTitleOriginView() {
     auto title_label = std::make_unique<views::Label>(
         base::string16(), CONTEXT_BODY_TEXT_LARGE,
         views::style::TextStyle::STYLE_PRIMARY);
@@ -94,7 +90,6 @@
         views::style::STYLE_SECONDARY,
         gfx::DirectionalityMode::DIRECTIONALITY_AS_URL);
 
-    title_label->SetBackgroundColor(background_color);
     title_label->SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL);
     title_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
     title_label->SetProperty(views::kFlexBehaviorKey,
@@ -102,7 +97,6 @@
                                  views::MinimumFlexSizeRule::kScaleToMinimum,
                                  views::MaximumFlexSizeRule::kPreferred));
 
-    location_label->SetBackgroundColor(background_color);
     location_label->SetElideBehavior(gfx::ElideBehavior::ELIDE_HEAD);
     location_label->SetHorizontalAlignment(
         gfx::HorizontalAlignment::ALIGN_LEFT);
@@ -126,6 +120,11 @@
     location_label_->SetVisible(!location.empty());
   }
 
+  void SetColors(SkColor background_color) {
+    title_label_->SetBackgroundColor(background_color);
+    location_label_->SetBackgroundColor(background_color);
+  }
+
   int GetMinimumWidth() const {
     // As labels are not multi-line, the layout will calculate a minimum size
     // that would fit the entire text (potentially a long url). Instead, set a
@@ -139,7 +138,8 @@
   }
 
   SkColor GetLocationColor() const {
-    return location_label_->GetEnabledColor();
+    return views::style::GetColor(*this, CONTEXT_BODY_TEXT_SMALL,
+                                  views::style::TextStyle::STYLE_PRIMARY);
   }
 
   // views::View:
@@ -174,38 +174,16 @@
       delegate_(delegate),
       browser_(browser_view->browser()) {
   set_context_menu_controller(this);
-  base::Optional<SkColor> optional_theme_color =
-      browser_->app_controller()->GetThemeColor();
-
-  const bool dark_mode = GetNativeTheme()->ShouldUseDarkColors();
-  const SkColor default_frame_color =
-#if defined(OS_CHROMEOS)
-      // Ash system frames differ from ChromeOS browser frames.
-      ash::kDefaultFrameColor;
-#else
-      ThemeProperties::GetDefaultColor(ThemeProperties::COLOR_FRAME, false,
-                                       dark_mode);
-#endif
-
-  title_bar_color_ = optional_theme_color.value_or(default_frame_color);
-
-  background_color_ = dark_mode ? default_frame_color : SK_ColorWHITE;
-
-  SetBackground(views::CreateSolidBackground(background_color_));
-
-  const SkColor foreground_color =
-      color_utils::GetColorWithMaxContrast(background_color_);
 
   const gfx::FontList& font_list = views::style::GetFont(
       CONTEXT_OMNIBOX_PRIMARY, views::style::STYLE_PRIMARY);
 
-  close_button_ = AddChildView(CreateCloseButton(this, foreground_color));
+  close_button_ = AddChildView(CreateCloseButton(this));
 
   location_icon_view_ =
       AddChildView(std::make_unique<LocationIconView>(font_list, this, this));
 
-  auto title_origin_view =
-      std::make_unique<CustomTabBarTitleOriginView>(background_color_);
+  auto title_origin_view = std::make_unique<CustomTabBarTitleOriginView>();
   title_origin_view->SetProperty(
       views::kFlexBehaviorKey, views::FlexSpecification::ForSizeRule(
                                    views::MinimumFlexSizeRule::kScaleToMinimum,
@@ -232,55 +210,6 @@
   return kViewClassName;
 }
 
-void CustomTabBarView::TabChangedAt(content::WebContents* contents,
-                                    int index,
-                                    TabChangeType change_type) {
-  if (!contents)
-    return;
-
-  // If the toolbar should not be shown don't update the UI, as the toolbar may
-  // be animating out and it looks messy.
-  Browser* browser = chrome::FindBrowserWithWebContents(contents);
-  if (!browser->app_controller()->ShouldShowCustomTabBar())
-    return;
-
-  content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
-  base::string16 title, location;
-  if (entry) {
-    title = Browser::FormatTitleForDisplay(entry->GetTitleForDisplay());
-    if (ShouldDisplayUrl(contents))
-      location = url_formatter::FormatUrl(entry->GetVirtualURL().GetOrigin(),
-                                          url_formatter::kFormatUrlOmitDefaults,
-                                          net::UnescapeRule::NORMAL, nullptr,
-                                          nullptr, nullptr);
-  }
-
-  title_origin_view_->Update(title, location);
-  location_icon_view_->Update(/*suppress animations = */ false);
-
-  // Hide location icon if we're already hiding the origin.
-  location_icon_view_->SetVisible(!location.empty());
-
-  last_title_ = title;
-  last_location_ = location;
-
-  web_app::AppBrowserController* app_controller =
-      chrome::FindBrowserWithWebContents(contents)->app_controller();
-  const bool started_in_scope =
-      app_controller->IsUrlInAppScope(app_controller->initial_url());
-
-  // Only show the 'X' button if:
-  // a) The current url is not in scope (no point showing a back to app button
-  // while in scope).
-  // And b), if the window started in scope (this is
-  // important for popup windows, which may be opened outside the app).
-  close_button_->SetVisible(
-      started_in_scope &&
-      !app_controller->IsUrlInAppScope(contents->GetLastCommittedURL()));
-
-  Layout();
-}
-
 gfx::Size CustomTabBarView::CalculatePreferredSize() const {
   // ToolbarView::GetMinimumSize() uses the preferred size of its children, so
   // tell it the minimum size this control will fit into (its layout will
@@ -330,27 +259,73 @@
   SchedulePaint();
 }
 
-void CustomTabBarView::ShowContextMenuForViewImpl(
-    views::View* source,
-    const gfx::Point& point,
-    ui::MenuSourceType source_type) {
-  if (!context_menu_model_) {
-    context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
-    context_menu_model_->AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL);
-  }
-  context_menu_runner_ = std::make_unique<views::MenuRunner>(
-      context_menu_model_.get(),
-      views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
-  context_menu_runner_->RunMenuAt(
-      views::View::GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
-      views::MenuAnchorPosition::kTopLeft, source_type);
+void CustomTabBarView::OnThemeChanged() {
+  base::Optional<SkColor> optional_theme_color =
+      browser_->app_controller()->GetThemeColor();
+
+  title_bar_color_ = optional_theme_color.value_or(GetDefaultFrameColor());
+
+  background_color_ = GetBackgroundColor();
+
+  SetBackground(views::CreateSolidBackground(background_color_));
+
+  const SkColor foreground_color =
+      color_utils::GetColorWithMaxContrast(background_color_);
+
+  SetImageFromVectorIconWithColor(
+      close_button_, vector_icons::kCloseRoundedIcon,
+      GetLayoutConstant(LOCATION_BAR_ICON_SIZE), foreground_color);
+
+  title_origin_view_->SetColors(background_color_);
 }
 
-void CustomTabBarView::ExecuteCommand(int command_id, int event_flags) {
-  if (command_id == IDC_COPY_URL) {
-    base::RecordAction(base::UserMetricsAction("CopyCustomTabBarUrl"));
-    chrome::ExecuteCommand(browser_, command_id);
+void CustomTabBarView::TabChangedAt(content::WebContents* contents,
+                                    int index,
+                                    TabChangeType change_type) {
+  if (!contents)
+    return;
+
+  // If the toolbar should not be shown don't update the UI, as the toolbar may
+  // be animating out and it looks messy.
+  Browser* browser = chrome::FindBrowserWithWebContents(contents);
+  if (!browser->app_controller()->ShouldShowCustomTabBar())
+    return;
+
+  content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
+  base::string16 title, location;
+  if (entry) {
+    title = Browser::FormatTitleForDisplay(entry->GetTitleForDisplay());
+    if (ShouldDisplayUrl(contents))
+      location = url_formatter::FormatUrl(entry->GetVirtualURL().GetOrigin(),
+                                          url_formatter::kFormatUrlOmitDefaults,
+                                          net::UnescapeRule::NORMAL, nullptr,
+                                          nullptr, nullptr);
   }
+
+  title_origin_view_->Update(title, location);
+  location_icon_view_->Update(/*suppress animations = */ false);
+
+  // Hide location icon if we're already hiding the origin.
+  location_icon_view_->SetVisible(!location.empty());
+
+  last_title_ = title;
+  last_location_ = location;
+
+  web_app::AppBrowserController* app_controller =
+      chrome::FindBrowserWithWebContents(contents)->app_controller();
+  const bool started_in_scope =
+      app_controller->IsUrlInAppScope(app_controller->initial_url());
+
+  // Only show the 'X' button if:
+  // a) The current url is not in scope (no point showing a back to app button
+  // while in scope).
+  // And b), if the window started in scope (this is
+  // important for popup windows, which may be opened outside the app).
+  close_button_->SetVisible(
+      started_in_scope &&
+      !app_controller->IsUrlInAppScope(contents->GetLastCommittedURL()));
+
+  Layout();
 }
 
 SkColor CustomTabBarView::GetIconLabelBubbleSurroundingForegroundColor() const {
@@ -358,7 +333,7 @@
 }
 
 SkColor CustomTabBarView::GetIconLabelBubbleBackgroundColor() const {
-  return background_color_;
+  return GetBackgroundColor();
 }
 
 content::WebContents* CustomTabBarView::GetWebContents() {
@@ -373,6 +348,11 @@
 
 void CustomTabBarView::OnLocationIconDragged(const ui::MouseEvent& event) {}
 
+SkColor CustomTabBarView::GetSecurityChipColor(
+    security_state::SecurityLevel security_level) const {
+  return GetOmniboxSecurityChipColor(GetThemeProvider(), security_level);
+}
+
 bool CustomTabBarView::ShowPageInfoDialog() {
   return ::ShowPageInfoDialog(
       GetWebContents(),
@@ -381,11 +361,8 @@
       bubble_anchor_util::Anchor::kCustomTabBar);
 }
 
-SkColor CustomTabBarView::GetSecurityChipColor(
-    security_state::SecurityLevel security_level) const {
-  return GetOmniboxSecurityChipColor(
-      &ThemeService::GetThemeProviderForProfile(browser_->profile()),
-      security_level);
+const LocationBarModel* CustomTabBarView::GetLocationBarModel() const {
+  return delegate_->GetLocationBarModel();
 }
 
 gfx::ImageSkia CustomTabBarView::GetLocationIcon(
@@ -396,10 +373,6 @@
       GetSecurityChipColor(GetLocationBarModel()->GetSecurityLevel()));
 }
 
-const LocationBarModel* CustomTabBarView::GetLocationBarModel() const {
-  return delegate_->GetLocationBarModel();
-}
-
 void CustomTabBarView::ButtonPressed(views::Button* sender,
                                      const ui::Event& event) {
   GoBackToApp();
@@ -409,6 +382,27 @@
   GoBackToApp();
 }
 
+bool CustomTabBarView::IsShowingOriginForTesting() const {
+  return title_origin_view_ != nullptr &&
+         title_origin_view_->IsShowingOriginForTesting();
+}
+
+SkColor CustomTabBarView::GetBackgroundColor() const {
+  return GetNativeTheme()->ShouldUseDarkColors() ? GetDefaultFrameColor()
+                                                 : SK_ColorWHITE;
+}
+
+SkColor CustomTabBarView::GetDefaultFrameColor() const {
+#if defined(OS_CHROMEOS)
+  // Ash system frames differ from ChromeOS browser frames.
+  return ash::kDefaultFrameColor;
+#else
+  return ThemeProperties::GetDefaultColor(
+      ThemeProperties::COLOR_FRAME, false,
+      GetNativeTheme()->ShouldUseDarkColors());
+#endif
+}
+
 void CustomTabBarView::GoBackToApp() {
   content::WebContents* web_contents = GetWebContents();
   web_app::AppBrowserController* app_controller =
@@ -456,7 +450,25 @@
   GetFocusManager()->SetFocusedView(location_icon_view_);
 }
 
-bool CustomTabBarView::IsShowingOriginForTesting() const {
-  return title_origin_view_ != nullptr &&
-         title_origin_view_->IsShowingOriginForTesting();
+void CustomTabBarView::ExecuteCommand(int command_id, int event_flags) {
+  if (command_id == IDC_COPY_URL) {
+    base::RecordAction(base::UserMetricsAction("CopyCustomTabBarUrl"));
+    chrome::ExecuteCommand(browser_, command_id);
+  }
+}
+
+void CustomTabBarView::ShowContextMenuForViewImpl(
+    views::View* source,
+    const gfx::Point& point,
+    ui::MenuSourceType source_type) {
+  if (!context_menu_model_) {
+    context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
+    context_menu_model_->AddItemWithStringId(IDC_COPY_URL, IDS_COPY_URL);
+  }
+  context_menu_runner_ = std::make_unique<views::MenuRunner>(
+      context_menu_model_.get(),
+      views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
+  context_menu_runner_->RunMenuAt(
+      views::View::GetWidget(), nullptr, gfx::Rect(point, gfx::Size()),
+      views::MenuAnchorPosition::kTopLeft, source_type);
 }
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
index bd41350..86b6b28 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view.h
@@ -13,7 +13,6 @@
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/context_menu_controller.h"
-#include "ui/views/controls/button/button.h"
 
 namespace gfx {
 class Rect;
@@ -22,6 +21,7 @@
 namespace views {
 class FlexLayout;
 class MenuRunner;
+class ImageButton;
 }
 
 class CustomTabBarTitleOriginView;
@@ -47,20 +47,19 @@
 
   LocationIconView* location_icon_view() { return location_icon_view_; }
 
-  // views::View:
+  // views::AccessiblePaneView:
   gfx::Rect GetAnchorBoundsInScreen() const override;
   const char* GetClassName() const override;
+  gfx::Size CalculatePreferredSize() const override;
+  void OnPaintBackground(gfx::Canvas* canvas) override;
+  void ChildPreferredSizeChanged(views::View* child) override;
+  void OnThemeChanged() override;
 
   // TabstripModelObserver:
   void TabChangedAt(content::WebContents* contents,
                     int index,
                     TabChangeType change_type) override;
 
-  // views::View:
-  gfx::Size CalculatePreferredSize() const override;
-  void OnPaintBackground(gfx::Canvas* canvas) override;
-  void ChildPreferredSizeChanged(views::View* child) override;
-
   // IconLabelBubbleView::Delegate:
   SkColor GetIconLabelBubbleSurroundingForegroundColor() const override;
   SkColor GetIconLabelBubbleBackgroundColor() const override;
@@ -83,7 +82,7 @@
   // Methods for testing.
   base::string16 title_for_testing() const { return last_title_; }
   base::string16 location_for_testing() const { return last_location_; }
-  views::Button* close_button_for_testing() const { return close_button_; }
+  views::ImageButton* close_button_for_testing() const { return close_button_; }
   ui::SimpleMenuModel* context_menu_for_testing() const {
     return context_menu_model_.get();
   }
@@ -91,6 +90,11 @@
   bool IsShowingOriginForTesting() const;
 
  private:
+  // Calculate the view's background and frame color from the current theme
+  // provider.
+  SkColor GetBackgroundColor() const;
+  SkColor GetDefaultFrameColor() const;
+
   // Takes the web contents for the custom tab bar back to the app scope.
   void GoBackToApp();
 
@@ -113,7 +117,7 @@
   base::string16 last_title_;
   base::string16 last_location_;
 
-  views::Button* close_button_ = nullptr;
+  views::ImageButton* close_button_ = nullptr;
   LocationBarView::Delegate* delegate_ = nullptr;
   LocationIconView* location_icon_view_ = nullptr;
   CustomTabBarTitleOriginView* title_origin_view_ = nullptr;
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
index 4e8a161..1c0d0aa 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -26,6 +26,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/clipboard/clipboard.h"
+#include "ui/views/controls/button/image_button.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 32b633d..51cba50 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -305,8 +305,8 @@
 }
 
 SkColor LocationBarView::GetColor(OmniboxPart part) const {
-  return GetOmniboxColor(&ThemeService::GetThemeProviderForProfile(profile_),
-                         part);
+  DCHECK(GetWidget());
+  return GetOmniboxColor(GetThemeProvider(), part);
 }
 
 SkColor LocationBarView::GetOpaqueBorderColor() const {
@@ -611,8 +611,6 @@
     image_view->SetIconColor(icon_color);
 
   RefreshBackground();
-
-  location_icon_view_->Update(/*suppress_animations=*/false);
   RefreshClearAllButtonIcon();
 }
 
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index a503154..6e30018 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -36,7 +36,6 @@
   DCHECK(delegate_);
 
   SetID(VIEW_ID_LOCATION_ICON);
-  Update(true);
   SetUpForAnimation();
 
   // Readability is guaranteed by the omnibox theme.
@@ -101,6 +100,15 @@
   node_data->role = ax::mojom::Role::kPopUpButton;
 }
 
+void LocationIconView::AddedToWidget() {
+  Update(true);
+}
+
+void LocationIconView::OnThemeChanged() {
+  IconLabelBubbleView::OnThemeChanged();
+  UpdateIcon();
+}
+
 int LocationIconView::GetMinimumLabelTextWidth() const {
   int width = 0;
 
@@ -187,9 +195,6 @@
     AnimateIn(base::nullopt);
   else
     AnimateOut();
-
-  // The label text color may have changed.
-  OnThemeChanged();
 }
 
 void LocationIconView::UpdateIcon() {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h
index 8c5c4d3..bdbcc9fa 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -72,6 +72,8 @@
   bool IsBubbleShowing() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+  void AddedToWidget() override;
+  void OnThemeChanged() override;
 
   // Returns what the minimum width for the label text.
   int GetMinimumLabelTextWidth() const;
diff --git a/chrome/browser/ui/views/login_handler_views.cc b/chrome/browser/ui/views/login_handler_views.cc
index d2d721a..b9fe6ba 100644
--- a/chrome/browser/ui/views/login_handler_views.cc
+++ b/chrome/browser/ui/views/login_handler_views.cc
@@ -147,10 +147,6 @@
     }
 
     views::View* GetContentsView() override { return login_view_; }
-    views::Widget* GetWidget() override { return login_view_->GetWidget(); }
-    const views::Widget* GetWidget() const override {
-      return login_view_->GetWidget();
-    }
 
    private:
     ~Dialog() override {
@@ -158,6 +154,11 @@
         handler_->OnDialogDestroyed();
     }
 
+    // views::DialogDelegate:
+    const views::Widget* GetWidgetImpl() const override {
+      return login_view_->GetWidget();
+    }
+
     LoginHandlerViews* handler_;
     // The LoginView that contains the user's login information.
     LoginView* login_view_;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index 4af5ead..02c0541 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -179,14 +179,15 @@
   }
   bool ShouldShowWindowTitle() const override { return false; }
   void DeleteDelegate() override { delete this; }
-  views::Widget* GetWidget() override { return widget_; }
-  const views::Widget* GetWidget() const override { return widget_; }
   views::NonClientFrameView* CreateNonClientFrameView(
       views::Widget* widget) override {
     return new OverlayWindowFrameView(widget);
   }
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override { return widget_; }
+
   // Owns OverlayWindowWidgetDelegate.
   views::Widget* widget_;
 
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
index 12e0db6..7f84368a 100644
--- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
+++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
@@ -59,14 +59,6 @@
   return content_view_;
 }
 
-views::Widget* SigninViewControllerDelegateViews::GetWidget() {
-  return content_view_->GetWidget();
-}
-
-const views::Widget* SigninViewControllerDelegateViews::GetWidget() const {
-  return content_view_->GetWidget();
-}
-
 void SigninViewControllerDelegateViews::DeleteDelegate() {
   ResetSigninViewControllerDelegate();
   delete this;
@@ -224,6 +216,10 @@
   content_view_->RequestFocus();
 }
 
+const views::Widget* SigninViewControllerDelegateViews::GetWidgetImpl() const {
+  return content_view_->GetWidget();
+}
+
 // --------------------------------------------------------------------
 // SigninViewControllerDelegate static methods
 // --------------------------------------------------------------------
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
index 851b846..6282713 100644
--- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
+++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.h
@@ -39,8 +39,6 @@
 
   // views::DialogDelegateView:
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   void DeleteDelegate() override;
   ui::ModalType GetModalType() const override;
   bool ShouldShowCloseButton() const override;
@@ -90,6 +88,9 @@
 
   Browser* browser() { return browser_; }
 
+  // views::DialogDelegateView:
+  const views::Widget* GetWidgetImpl() const override;
+
   SigninViewController* signin_view_controller_;  // Not owned.
   content::WebContents* const web_contents_;      // Not owned.
   Browser* const browser_;                        // Not owned.
diff --git a/chrome/browser/ui/views/select_file_dialog_extension.cc b/chrome/browser/ui/views/select_file_dialog_extension.cc
index cf80cb7..a5e482e 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/extensions/extension_view_host.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc
index 4bc813b..13846a46 100644
--- a/chrome/browser/ui/views/simple_message_box_views.cc
+++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -208,14 +208,6 @@
   return message_box_view_;
 }
 
-views::Widget* SimpleMessageBoxViews::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* SimpleMessageBoxViews::GetWidget() const {
-  return message_box_view_->GetWidget();
-}
-
 bool SimpleMessageBoxViews::ShouldShowCloseButton() const {
   return can_close_;
 }
@@ -286,6 +278,10 @@
   std::move(result_callback_).Run(result_);
 }
 
+const views::Widget* SimpleMessageBoxViews::GetWidgetImpl() const {
+  return message_box_view_->GetWidget();
+}
+
 namespace chrome {
 
 void ShowWarningMessageBox(gfx::NativeWindow parent,
diff --git a/chrome/browser/ui/views/simple_message_box_views.h b/chrome/browser/ui/views/simple_message_box_views.h
index 55d72d6..3a29eea 100644
--- a/chrome/browser/ui/views/simple_message_box_views.h
+++ b/chrome/browser/ui/views/simple_message_box_views.h
@@ -36,8 +36,6 @@
   void DeleteDelegate() override;
   ui::ModalType GetModalType() const override;
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   bool ShouldShowCloseButton() const override;
 
   // views::WidgetObserver:
@@ -57,6 +55,9 @@
   void Run(MessageBoxResultCallback result_callback);
   void Done();
 
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   const base::string16 window_title_;
   const chrome::MessageBoxType type_;
   chrome::MessageBoxResult result_;
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
index 8bdddec..ab322a0 100644
--- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
+++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc
@@ -89,14 +89,6 @@
   return message_box_view_;
 }
 
-views::Widget* TabModalConfirmDialogViews::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* TabModalConfirmDialogViews::GetWidget() const {
-  return message_box_view_->GetWidget();
-}
-
 void TabModalConfirmDialogViews::DeleteDelegate() {
   delete this;
 }
@@ -119,6 +111,10 @@
   GetWidget()->Close();
 }
 
+const views::Widget* TabModalConfirmDialogViews::GetWidgetImpl() const {
+  return message_box_view_->GetWidget();
+}
+
 void TabModalConfirmDialogViews::LinkClicked(views::Link* source,
                                              int event_flags) {
   delegate_->LinkClicked(ui::DispositionFromEventFlags(event_flags));
diff --git a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h
index 4f001ad..12b5366e 100644
--- a/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h
+++ b/chrome/browser/ui/views/tab_modal_confirm_dialog_views.h
@@ -42,8 +42,6 @@
   bool Close() override;
   bool ShouldShowCloseButton() const override;
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   void DeleteDelegate() override;
   ui::ModalType GetModalType() const override;
 
@@ -55,6 +53,9 @@
   void CancelTabModalDialog() override;
   void CloseDialog() override;
 
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   void LinkClicked(views::Link* source, int event_flags);
 
   views::View* GetInitiallyFocusedView() override;
diff --git a/chrome/browser/ui/views/test/view_event_test_base.cc b/chrome/browser/ui/views/test/view_event_test_base.cc
index dc7ef2e5..a3385d8 100644
--- a/chrome/browser/ui/views/test/view_event_test_base.cc
+++ b/chrome/browser/ui/views/test/view_event_test_base.cc
@@ -122,14 +122,6 @@
   return content_view_;
 }
 
-const views::Widget* ViewEventTestBase::GetWidget() const {
-  return content_view_->GetWidget();
-}
-
-views::Widget* ViewEventTestBase::GetWidget() {
-  return content_view_->GetWidget();
-}
-
 ViewEventTestBase::~ViewEventTestBase() {
   TestingBrowserProcess::DeleteInstance();
 }
@@ -175,3 +167,7 @@
   if (HasFatalFailure())
     Done();
 }
+
+const views::Widget* ViewEventTestBase::GetWidgetImpl() const {
+  return content_view_->GetWidget();
+}
diff --git a/chrome/browser/ui/views/test/view_event_test_base.h b/chrome/browser/ui/views/test/view_event_test_base.h
index 0a6319d..95e9678 100644
--- a/chrome/browser/ui/views/test/view_event_test_base.h
+++ b/chrome/browser/ui/views/test/view_event_test_base.h
@@ -94,8 +94,6 @@
   // views::WidgetDelegate:
   bool CanResize() const override;
   views::View* GetContentsView() override;
-  const views::Widget* GetWidget() const override;
-  views::Widget* GetWidget() override;
 
  protected:
   ~ViewEventTestBase() override;
@@ -130,6 +128,9 @@
   // failures invokes Done.
   void RunTestMethod(base::OnceClosure task);
 
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // The content of the Window.
   views::View* content_view_ = nullptr;
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
index deb0d387..8ac9b0ba 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button_unittest.cc
@@ -74,10 +74,10 @@
   TestParentView& operator=(const TestParentView&) = delete;
   ~TestParentView() override = default;
 
-  views::Widget* GetWidget() override { return widget_.get(); }
-  const views::Widget* GetWidget() const override { return widget_.get(); }
-
  private:
+  // views::View:
+  const views::Widget* GetWidgetImpl() const override { return widget_.get(); }
+
   std::unique_ptr<views::Widget> widget_;
 };
 
diff --git a/chrome/browser/ui/views/update_recommended_message_box.cc b/chrome/browser/ui/views/update_recommended_message_box.cc
index 79fe5720..4027b02 100644
--- a/chrome/browser/ui/views/update_recommended_message_box.cc
+++ b/chrome/browser/ui/views/update_recommended_message_box.cc
@@ -95,10 +95,6 @@
   return message_box_view_;
 }
 
-views::Widget* UpdateRecommendedMessageBox::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* UpdateRecommendedMessageBox::GetWidget() const {
+const views::Widget* UpdateRecommendedMessageBox::GetWidgetImpl() const {
   return message_box_view_->GetWidget();
 }
diff --git a/chrome/browser/ui/views/update_recommended_message_box.h b/chrome/browser/ui/views/update_recommended_message_box.h
index f3b52a4b7..b171f5c3 100644
--- a/chrome/browser/ui/views/update_recommended_message_box.h
+++ b/chrome/browser/ui/views/update_recommended_message_box.h
@@ -31,8 +31,7 @@
   void DeleteDelegate() override;
   ui::ModalType GetModalType() const override;
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
+  const views::Widget* GetWidgetImpl() const override;
 
   views::MessageBoxView* message_box_view_;
 
diff --git a/chrome/browser/ui/webui/discards/BUILD.gn b/chrome/browser/ui/webui/discards/BUILD.gn
index cf71fc8..91df9ad 100644
--- a/chrome/browser/ui/webui/discards/BUILD.gn
+++ b/chrome/browser/ui/webui/discards/BUILD.gn
@@ -6,9 +6,7 @@
 
 if (is_win || is_mac || is_desktop_linux || is_chromeos) {
   mojom("mojo_bindings") {
-    sources = [
-      "discards.mojom",
-    ]
+    sources = [ "discards.mojom" ]
 
     public_deps = [
       "//chrome/browser/resource_coordinator:mojo_bindings",
diff --git a/chrome/services/cups_proxy/BUILD.gn b/chrome/services/cups_proxy/BUILD.gn
index a8912e54..88bdf62 100644
--- a/chrome/services/cups_proxy/BUILD.gn
+++ b/chrome/services/cups_proxy/BUILD.gn
@@ -36,9 +36,7 @@
     "//net",
   ]
 
-  public_deps = [
-    "//printing",
-  ]
+  public_deps = [ "//printing" ]
 
   configs += [ "//printing:cups" ]
 }
@@ -50,9 +48,7 @@
     "fake_cups_proxy_service_delegate.h",
   ]
 
-  public_deps = [
-    ":cups_proxy",
-  ]
+  public_deps = [ ":cups_proxy" ]
 }
 
 test("libcups_unittests") {
@@ -79,7 +75,5 @@
     "//testing/gtest",
   ]
 
-  data = [
-    "//chrome/services/cups_proxy/test/data",
-  ]
+  data = [ "//chrome/services/cups_proxy/test/data" ]
 }
diff --git a/chrome/services/cups_proxy/public/cpp/BUILD.gn b/chrome/services/cups_proxy/public/cpp/BUILD.gn
index d51cbc3..35a5d53 100644
--- a/chrome/services/cups_proxy/public/cpp/BUILD.gn
+++ b/chrome/services/cups_proxy/public/cpp/BUILD.gn
@@ -18,9 +18,7 @@
     "type_conversions.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   public_deps = [
     "//chrome/services/ipp_parser/public/cpp",
@@ -32,9 +30,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "cups_util_unittest.cc",
-  ]
+  sources = [ "cups_util_unittest.cc" ]
   deps = [
     ":cpp",
     "//base",
diff --git a/chrome/services/cups_proxy/public/mojom/BUILD.gn b/chrome/services/cups_proxy/public/mojom/BUILD.gn
index 5df08c8..be7b494 100644
--- a/chrome/services/cups_proxy/public/mojom/BUILD.gn
+++ b/chrome/services/cups_proxy/public/mojom/BUILD.gn
@@ -6,11 +6,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "proxy.mojom",
-  ]
+  sources = [ "proxy.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chrome/services/media_gallery_util/BUILD.gn b/chrome/services/media_gallery_util/BUILD.gn
index a8afac8..1e2690a 100644
--- a/chrome/services/media_gallery_util/BUILD.gn
+++ b/chrome/services/media_gallery_util/BUILD.gn
@@ -31,9 +31,7 @@
     ]
   }
 
-  public_deps = [
-    "//chrome/services/media_gallery_util/public/mojom",
-  ]
+  public_deps = [ "//chrome/services/media_gallery_util/public/mojom" ]
 
   if (media_use_ffmpeg) {
     deps += [
@@ -46,9 +44,7 @@
 if (is_android) {
   source_set("unit_tests") {
     testonly = true
-    sources = [
-      "media_parser_android_unittest.cc",
-    ]
+    sources = [ "media_parser_android_unittest.cc" ]
 
     data = [
       "//media/test/data/bear.mp4",
diff --git a/chrome/services/media_gallery_util/public/cpp/BUILD.gn b/chrome/services/media_gallery_util/public/cpp/BUILD.gn
index 2cfc031..923f601b 100644
--- a/chrome/services/media_gallery_util/public/cpp/BUILD.gn
+++ b/chrome/services/media_gallery_util/public/cpp/BUILD.gn
@@ -23,9 +23,7 @@
     "//third_party/libyuv",
   ]
 
-  public_deps = [
-    "//chrome/services/media_gallery_util/public/mojom",
-  ]
+  public_deps = [ "//chrome/services/media_gallery_util/public/mojom" ]
 
   if (media_use_ffmpeg) {
     deps += [
@@ -38,9 +36,7 @@
 source_set("browser_tests") {
   testonly = true
 
-  sources = [
-    "media_gallery_util_browsertest.cc",
-  ]
+  sources = [ "media_gallery_util_browsertest.cc" ]
   defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
 
   deps = [
diff --git a/chrome/services/media_gallery_util/public/mojom/BUILD.gn b/chrome/services/media_gallery_util/public/mojom/BUILD.gn
index 93a0c900..6c32e6e 100644
--- a/chrome/services/media_gallery_util/public/mojom/BUILD.gn
+++ b/chrome/services/media_gallery_util/public/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "media_parser.mojom",
-  ]
+  sources = [ "media_parser.mojom" ]
 
   public_deps = [
     "//media/mojo/mojom",
diff --git a/chrome/tools/build/mac/BUILD.gn b/chrome/tools/build/mac/BUILD.gn
index 2beb33b..2189d4c 100644
--- a/chrome/tools/build/mac/BUILD.gn
+++ b/chrome/tools/build/mac/BUILD.gn
@@ -5,9 +5,7 @@
 executable("infoplist_strings_tool") {
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
-  sources = [
-    "infoplist_strings_util.mm",
-  ]
+  sources = [ "infoplist_strings_util.mm" ]
 
   deps = [
     "//base",
diff --git a/chromecast/external_mojo/external_service_support/BUILD.gn b/chromecast/external_mojo/external_service_support/BUILD.gn
index 4dc8dfc..6fe104e 100644
--- a/chromecast/external_mojo/external_service_support/BUILD.gn
+++ b/chromecast/external_mojo/external_service_support/BUILD.gn
@@ -36,15 +36,11 @@
 }
 
 source_set("service_process") {
-  sources = [
-    "service_process.h",
-  ]
+  sources = [ "service_process.h" ]
 }
 
 source_set("standalone_service_main") {
-  sources = [
-    "standalone_service_main.cc",
-  ]
+  sources = [ "standalone_service_main.cc" ]
   deps = [
     ":external_service",
     ":process_setup",
@@ -52,9 +48,7 @@
     "//chromecast/external_mojo/public/cpp:common",
     "//mojo/core/embedder",
   ]
-  public_deps = [
-    ":service_process",
-  ]
+  public_deps = [ ":service_process" ]
 }
 
 source_set("chromium_service") {
@@ -73,9 +67,7 @@
 }
 
 executable("standalone_mojo_broker") {
-  sources = [
-    "standalone_mojo_broker.cc",
-  ]
+  sources = [ "standalone_mojo_broker.cc" ]
   deps = [
     ":process_setup",
     "//base",
diff --git a/chromecast/external_mojo/public/cpp/BUILD.gn b/chromecast/external_mojo/public/cpp/BUILD.gn
index ca1fca0..a8f1316e 100644
--- a/chromecast/external_mojo/public/cpp/BUILD.gn
+++ b/chromecast/external_mojo/public/cpp/BUILD.gn
@@ -7,9 +7,7 @@
     "common.cc",
     "common.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("external_mojo_broker") {
diff --git a/chromecast/external_mojo/public/mojom/BUILD.gn b/chromecast/external_mojo/public/mojom/BUILD.gn
index 0cc2050..6aefba7 100644
--- a/chromecast/external_mojo/public/mojom/BUILD.gn
+++ b/chromecast/external_mojo/public/mojom/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "connector.mojom",
-  ]
+  sources = [ "connector.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 259f5cde..c07132bb 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -35,9 +35,7 @@
     "//build/config/linux/nss:system_nss_no_ssl_config",
     "//build/config/compiler:use_orderfile_for_hugepage",
   ]
-  public_deps = [
-    "//chromeos/constants",
-  ]
+  public_deps = [ "//chromeos/constants" ]
   deps = [
     ":chromeos_export",
     "//base",
@@ -98,12 +96,8 @@
 }
 
 source_set("chromeos_export") {
-  deps = [
-    "//base",
-  ]
-  sources = [
-    "chromeos_export.h",
-  ]
+  deps = [ "//base" ]
+  sources = [ "chromeos_export.h" ]
 }
 
 # This must be a static library instead of a source set because some of the
@@ -113,9 +107,7 @@
 # can be converted to a source set.
 static_library("test_support") {
   testonly = true
-  public_deps = [
-    ":test_support_source_set",
-  ]
+  public_deps = [ ":test_support_source_set" ]
 }
 
 source_set("test_support_source_set") {
@@ -142,9 +134,7 @@
 }
 
 source_set("test_utils") {
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   sources = [
     "test/chromeos_test_utils.cc",
     "test/chromeos_test_utils.h",
@@ -211,9 +201,7 @@
     "test/run_all_unittests.cc",
   ]
 
-  data = [
-    "test/data/",
-  ]
+  data = [ "test/data/" ]
 }
 
 # The following definitions only apply when building for a CrOS board (ie: not
@@ -287,17 +275,11 @@
 
     # TODO(bpastene): Figure out what's generating resources/chromeos/ and
     # declare it as a dep instead of adding the dir directly.
-    data = [
-      "$root_out_dir/resources/chromeos/",
-    ]
+    data = [ "$root_out_dir/resources/chromeos/" ]
   }
 }
 
 fuzzer_test("ppd_line_reader_fuzzer") {
-  sources = [
-    "printing/ppd_line_reader_fuzzer.cc",
-  ]
-  deps = [
-    ":chromeos",
-  ]
+  sources = [ "printing/ppd_line_reader_fuzzer.cc" ]
+  deps = [ ":chromeos" ]
 }
diff --git a/chromeos/components/multidevice/BUILD.gn b/chromeos/components/multidevice/BUILD.gn
index f5628f3..3145706 100644
--- a/chromeos/components/multidevice/BUILD.gn
+++ b/chromeos/components/multidevice/BUILD.gn
@@ -47,9 +47,7 @@
     "remote_device_test_util.h",
   ]
 
-  public_deps = [
-    ":multidevice",
-  ]
+  public_deps = [ ":multidevice" ]
 
   deps = [
     "//base",
diff --git a/chromeos/components/multidevice/debug_webui/BUILD.gn b/chromeos/components/multidevice/debug_webui/BUILD.gn
index dd7e9f1..fa9814b 100644
--- a/chromeos/components/multidevice/debug_webui/BUILD.gn
+++ b/chromeos/components/multidevice/debug_webui/BUILD.gn
@@ -35,7 +35,5 @@
     "//ui/resources",
     "//ui/webui",
   ]
-  public_deps = [
-    "//chromeos/services/device_sync/public/mojom",
-  ]
+  public_deps = [ "//chromeos/services/device_sync/public/mojom" ]
 }
diff --git a/chromeos/components/multidevice/debug_webui/resources/BUILD.gn b/chromeos/components/multidevice/debug_webui/resources/BUILD.gn
index e0bdada..2f90aaa 100644
--- a/chromeos/components/multidevice/debug_webui/resources/BUILD.gn
+++ b/chromeos/components/multidevice/debug_webui/resources/BUILD.gn
@@ -19,9 +19,7 @@
 }
 
 js_library("logs") {
-  deps = [
-    ":webui",
-  ]
+  deps = [ ":webui" ]
 }
 
 js_library("proximity_auth") {
diff --git a/chromeos/components/multidevice/logging/BUILD.gn b/chromeos/components/multidevice/logging/BUILD.gn
index fc9f993..2db4ca0 100644
--- a/chromeos/components/multidevice/logging/BUILD.gn
+++ b/chromeos/components/multidevice/logging/BUILD.gn
@@ -10,16 +10,12 @@
     "logging.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "logging_unittest.cc",
-  ]
+  sources = [ "logging_unittest.cc" ]
 
   deps = [
     ":logging",
diff --git a/chromeos/components/multidevice/mojom/BUILD.gn b/chromeos/components/multidevice/mojom/BUILD.gn
index af858ec..a760830 100644
--- a/chromeos/components/multidevice/mojom/BUILD.gn
+++ b/chromeos/components/multidevice/mojom/BUILD.gn
@@ -5,21 +5,15 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "multidevice_types.mojom",
-  ]
+  sources = [ "multidevice_types.mojom" ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "multidevice_mojom_traits_unittest.cc",
-  ]
+  sources = [ "multidevice_mojom_traits_unittest.cc" ]
 
   deps = [
     ":mojom",
diff --git a/chromeos/services/assistant/platform/audio_stream_handler.h b/chromeos/services/assistant/platform/audio_stream_handler.h
index a002bab..93c67978 100644
--- a/chromeos/services/assistant/platform/audio_stream_handler.h
+++ b/chromeos/services/assistant/platform/audio_stream_handler.h
@@ -10,7 +10,6 @@
 #include "base/synchronization/lock.h"
 #include "chromeos/services/assistant/public/mojom/assistant_audio_decoder.mojom.h"
 #include "libassistant/shared/public/platform_audio_output.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
diff --git a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h
index e66e85f..8081826 100644
--- a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h
+++ b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h
@@ -19,7 +19,6 @@
 #include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
 #include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
 #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 
 namespace chromeos {
 
diff --git a/chromeos/services/ime/decoder/decoder_engine.h b/chromeos/services/ime/decoder/decoder_engine.h
index 82a84cd..2ac515e 100644
--- a/chromeos/services/ime/decoder/decoder_engine.h
+++ b/chromeos/services/ime/decoder/decoder_engine.h
@@ -9,7 +9,6 @@
 #include "chromeos/services/ime/input_engine.h"
 #include "chromeos/services/ime/public/cpp/shared_lib/interfaces.h"
 #include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
 
 namespace chromeos {
 namespace ime {
diff --git a/chromeos/services/multidevice_setup/BUILD.gn b/chromeos/services/multidevice_setup/BUILD.gn
index 62f12c5..7aaacc6 100644
--- a/chromeos/services/multidevice_setup/BUILD.gn
+++ b/chromeos/services/multidevice_setup/BUILD.gn
@@ -75,9 +75,7 @@
     "//url",
   ]
 
-  public_deps = [
-    "//chromeos/services/multidevice_setup/public/mojom",
-  ]
+  public_deps = [ "//chromeos/services/multidevice_setup/public/mojom" ]
 
   visibility = [
     ":*",
diff --git a/chromeos/services/multidevice_setup/proto/BUILD.gn b/chromeos/services/multidevice_setup/proto/BUILD.gn
index 7453653..96f3e4d 100644
--- a/chromeos/services/multidevice_setup/proto/BUILD.gn
+++ b/chromeos/services/multidevice_setup/proto/BUILD.gn
@@ -5,7 +5,5 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "multidevice_setup.proto",
-  ]
+  sources = [ "multidevice_setup.proto" ]
 }
diff --git a/chromeos/services/multidevice_setup/public/cpp/BUILD.gn b/chromeos/services/multidevice_setup/public/cpp/BUILD.gn
index 97635d3..3f5d984 100644
--- a/chromeos/services/multidevice_setup/public/cpp/BUILD.gn
+++ b/chromeos/services/multidevice_setup/public/cpp/BUILD.gn
@@ -20,23 +20,15 @@
 }
 
 source_set("auth_token_validator") {
-  sources = [
-    "auth_token_validator.h",
-  ]
+  sources = [ "auth_token_validator.h" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("android_sms_app_helper_delegate") {
-  sources = [
-    "android_sms_app_helper_delegate.h",
-  ]
+  sources = [ "android_sms_app_helper_delegate.h" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("android_sms_pairing_state_tracker") {
@@ -45,9 +37,7 @@
     "android_sms_pairing_state_tracker.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("prefs") {
@@ -129,17 +119,13 @@
     "//url",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "multidevice_setup_client_impl_unittest.cc",
-  ]
+  sources = [ "multidevice_setup_client_impl_unittest.cc" ]
 
   deps = [
     ":cpp",
diff --git a/chromeos/services/multidevice_setup/public/mojom/BUILD.gn b/chromeos/services/multidevice_setup/public/mojom/BUILD.gn
index 074cdb4..65cbcf37 100644
--- a/chromeos/services/multidevice_setup/public/mojom/BUILD.gn
+++ b/chromeos/services/multidevice_setup/public/mojom/BUILD.gn
@@ -5,11 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "multidevice_setup.mojom",
-  ]
+  sources = [ "multidevice_setup.mojom" ]
 
-  public_deps = [
-    "//chromeos/services/device_sync/public/mojom",
-  ]
+  public_deps = [ "//chromeos/services/device_sync/public/mojom" ]
 }
diff --git a/components/app_modal/BUILD.gn b/components/app_modal/BUILD.gn
index 7f80781..5f84036 100644
--- a/components/app_modal/BUILD.gn
+++ b/components/app_modal/BUILD.gn
@@ -13,7 +13,6 @@
     "javascript_dialog_extensions_client.h",
     "javascript_dialog_manager.cc",
     "javascript_dialog_manager.h",
-    "javascript_native_dialog_factory.h",
     "native_app_modal_dialog.h",
   ]
 
@@ -58,9 +57,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "javascript_dialog_manager_unittest.cc",
-  ]
+  sources = [ "javascript_dialog_manager_unittest.cc" ]
 
   deps = [
     ":app_modal",
diff --git a/components/app_modal/android/javascript_app_modal_dialog_android.cc b/components/app_modal/android/javascript_app_modal_dialog_android.cc
index aca7abb..3243b2e 100644
--- a/components/app_modal/android/javascript_app_modal_dialog_android.cc
+++ b/components/app_modal/android/javascript_app_modal_dialog_android.cc
@@ -13,7 +13,6 @@
 #include "components/app_modal/app_modal_dialog_queue.h"
 #include "components/app_modal/javascript_app_modal_dialog.h"
 #include "components/app_modal/javascript_dialog_manager.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
@@ -33,60 +32,12 @@
     app_modal::JavaScriptAppModalDialog* dialog,
     gfx::NativeWindow parent)
     : dialog_(dialog),
-      parent_jobject_weak_ref_(env, parent->GetJavaObject().obj()) {}
+      parent_jobject_weak_ref_(env, parent->GetJavaObject().obj()) {
+  dialog->web_contents()->GetDelegate()->ActivateContents(
+      dialog->web_contents());
+}
 
 void JavascriptAppModalDialogAndroid::ShowAppModalDialog() {
-  DoShowAppModalDialog();
-}
-
-void JavascriptAppModalDialogAndroid::ActivateAppModalDialog() {
-  ShowAppModalDialog();
-}
-
-void JavascriptAppModalDialogAndroid::CloseAppModalDialog() {
-  CancelAppModalDialog();
-}
-
-void JavascriptAppModalDialogAndroid::AcceptAppModalDialog() {
-  base::string16 prompt_text;
-  dialog_->OnAccept(prompt_text, false);
-  delete this;
-}
-
-void JavascriptAppModalDialogAndroid::DidAcceptAppModalDialog(
-    JNIEnv* env,
-    const JavaParamRef<jobject>&,
-    const JavaParamRef<jstring>& prompt,
-    bool should_suppress_js_dialogs) {
-  base::string16 prompt_text =
-      base::android::ConvertJavaStringToUTF16(env, prompt);
-  dialog_->OnAccept(prompt_text, should_suppress_js_dialogs);
-  delete this;
-}
-
-void JavascriptAppModalDialogAndroid::CancelAppModalDialog() {
-  dialog_->OnCancel(false);
-  delete this;
-}
-
-bool JavascriptAppModalDialogAndroid::IsShowing() const {
-  return true;
-}
-
-void JavascriptAppModalDialogAndroid::DidCancelAppModalDialog(
-    JNIEnv* env,
-    const JavaParamRef<jobject>&,
-    bool should_suppress_js_dialogs) {
-  dialog_->OnCancel(should_suppress_js_dialogs);
-  delete this;
-}
-
-const ScopedJavaGlobalRef<jobject>&
-JavascriptAppModalDialogAndroid::GetDialogObject() const {
-  return dialog_jobject_;
-}
-
-void JavascriptAppModalDialogAndroid::DoShowAppModalDialog() {
   JNIEnv* env = AttachCurrentThread();
   // Keep a strong ref to the parent window while we make the call to java to
   // display the dialog.
@@ -138,6 +89,57 @@
       env, dialog_object, parent_jobj, reinterpret_cast<intptr_t>(this));
 }
 
+void JavascriptAppModalDialogAndroid::ActivateAppModalDialog() {
+  // This is called on desktop (Views) when interacting with a browser window
+  // that does not host the currently active app modal dialog, as a way to
+  // redirect activation to the app modal dialog host. It's not relevant on
+  // Android.
+  NOTREACHED();
+}
+
+void JavascriptAppModalDialogAndroid::CloseAppModalDialog() {
+  CancelAppModalDialog();
+}
+
+void JavascriptAppModalDialogAndroid::AcceptAppModalDialog() {
+  base::string16 prompt_text;
+  dialog_->OnAccept(prompt_text, false);
+  delete this;
+}
+
+void JavascriptAppModalDialogAndroid::DidAcceptAppModalDialog(
+    JNIEnv* env,
+    const JavaParamRef<jobject>&,
+    const JavaParamRef<jstring>& prompt,
+    bool should_suppress_js_dialogs) {
+  base::string16 prompt_text =
+      base::android::ConvertJavaStringToUTF16(env, prompt);
+  dialog_->OnAccept(prompt_text, should_suppress_js_dialogs);
+  delete this;
+}
+
+void JavascriptAppModalDialogAndroid::CancelAppModalDialog() {
+  dialog_->OnCancel(false);
+  delete this;
+}
+
+bool JavascriptAppModalDialogAndroid::IsShowing() const {
+  return true;
+}
+
+void JavascriptAppModalDialogAndroid::DidCancelAppModalDialog(
+    JNIEnv* env,
+    const JavaParamRef<jobject>&,
+    bool should_suppress_js_dialogs) {
+  dialog_->OnCancel(should_suppress_js_dialogs);
+  delete this;
+}
+
+const ScopedJavaGlobalRef<jobject>&
+JavascriptAppModalDialogAndroid::GetDialogObject() const {
+  return dialog_jobject_;
+}
+
 JavascriptAppModalDialogAndroid::~JavascriptAppModalDialogAndroid() {
   // In case the dialog is still displaying, tell it to close itself.
   // This can happen if you trigger a dialog but close the Tab before it's
diff --git a/components/app_modal/android/javascript_app_modal_dialog_android.h b/components/app_modal/android/javascript_app_modal_dialog_android.h
index d713bb4..5281cc0 100644
--- a/components/app_modal/android/javascript_app_modal_dialog_android.h
+++ b/components/app_modal/android/javascript_app_modal_dialog_android.h
@@ -44,8 +44,6 @@
   const base::android::ScopedJavaGlobalRef<jobject>& GetDialogObject() const;
 
  protected:
-  void DoShowAppModalDialog();
-
   JavaScriptAppModalDialog* dialog() { return dialog_.get(); }
 
   ~JavascriptAppModalDialogAndroid() override;
diff --git a/components/app_modal/javascript_app_modal_dialog.cc b/components/app_modal/javascript_app_modal_dialog.cc
index e8ae8565..69cf03b 100644
--- a/components/app_modal/javascript_app_modal_dialog.cc
+++ b/components/app_modal/javascript_app_modal_dialog.cc
@@ -9,7 +9,6 @@
 #include "build/build_config.h"
 #include "components/app_modal/app_modal_dialog_queue.h"
 #include "components/app_modal/javascript_dialog_manager.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
 #include "components/app_modal/native_app_modal_dialog.h"
 #include "ui/gfx/text_elider.h"
 
@@ -98,9 +97,9 @@
 }
 
 void JavaScriptAppModalDialog::ShowModalDialog() {
-  native_dialog_ = JavaScriptDialogManager::GetInstance()
-                       ->native_dialog_factory()
-                       ->CreateNativeJavaScriptDialog(this);
+  native_dialog_ =
+      JavaScriptDialogManager::GetInstance()->native_dialog_factory()->Run(
+          this);
   native_dialog_->ShowAppModalDialog();
   if (app_modal_dialog_observer)
     app_modal_dialog_observer->Notify(this);
diff --git a/components/app_modal/javascript_dialog_manager.cc b/components/app_modal/javascript_dialog_manager.cc
index 1c22bcb..8549069 100644
--- a/components/app_modal/javascript_dialog_manager.cc
+++ b/components/app_modal/javascript_dialog_manager.cc
@@ -14,7 +14,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/app_modal/app_modal_dialog_queue.h"
 #include "components/app_modal/javascript_dialog_extensions_client.h"
-#include "components/app_modal/javascript_native_dialog_factory.h"
 #include "components/app_modal/native_app_modal_dialog.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
@@ -64,7 +63,7 @@
 }
 
 void JavaScriptDialogManager::SetNativeDialogFactory(
-    std::unique_ptr<JavaScriptNativeDialogFactory> factory) {
+    JavaScriptNativeDialogFactory factory) {
   native_dialog_factory_ = std::move(factory);
 }
 
diff --git a/components/app_modal/javascript_dialog_manager.h b/components/app_modal/javascript_dialog_manager.h
index 48bf581..dfe25c1 100644
--- a/components/app_modal/javascript_dialog_manager.h
+++ b/components/app_modal/javascript_dialog_manager.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/singleton.h"
@@ -20,16 +21,20 @@
 
 class JavaScriptDialogManager : public content::JavaScriptDialogManager {
  public:
-  static JavaScriptDialogManager* GetInstance();
+  // A factory method to create and returns a platform-specific dialog class.
+  // The returned object should own itself.
+  using JavaScriptNativeDialogFactory =
+      base::RepeatingCallback<NativeAppModalDialog*(JavaScriptAppModalDialog*)>;
 
-  JavaScriptNativeDialogFactory* native_dialog_factory() {
-    return native_dialog_factory_.get();
-  }
+  static JavaScriptDialogManager* GetInstance();
 
   // Sets the JavaScriptNativeDialogFactory used to create platform specific
   // dialog window instances.
-  void SetNativeDialogFactory(
-      std::unique_ptr<JavaScriptNativeDialogFactory> factory);
+  void SetNativeDialogFactory(JavaScriptNativeDialogFactory factory);
+
+  JavaScriptNativeDialogFactory* native_dialog_factory() {
+    return &native_dialog_factory_;
+  }
 
   // JavaScript dialogs may be opened by an extensions/app, thus they need
   // access to extensions functionality. This sets a client interface to
@@ -95,7 +100,7 @@
   // is a void* because the pointer is just a cookie and is never dereferenced.
   JavaScriptAppModalDialog::ExtraDataMap javascript_dialog_extra_data_;
 
-  std::unique_ptr<JavaScriptNativeDialogFactory> native_dialog_factory_;
+  JavaScriptNativeDialogFactory native_dialog_factory_;
   std::unique_ptr<JavaScriptDialogExtensionsClient> extensions_client_;
 
   DISALLOW_COPY_AND_ASSIGN(JavaScriptDialogManager);
diff --git a/components/app_modal/javascript_native_dialog_factory.h b/components/app_modal/javascript_native_dialog_factory.h
deleted file mode 100644
index 9a88227..0000000
--- a/components/app_modal/javascript_native_dialog_factory.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_APP_MODAL_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
-#define COMPONENTS_APP_MODAL_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
-
-#include "ui/gfx/native_widget_types.h"
-
-namespace app_modal {
-
-class JavaScriptAppModalDialog;
-class NativeAppModalDialog;
-
-class JavaScriptNativeDialogFactory {
- public:
-  virtual ~JavaScriptNativeDialogFactory() {}
-
-  // Creates an native modal dialog for a JavaScript dialog;
-  virtual NativeAppModalDialog* CreateNativeJavaScriptDialog(
-      JavaScriptAppModalDialog* dialog) = 0;
-};
-
-}  // namespace app_modal
-
-#endif  // COMPONENTS_APP_MODAL_JAVASCRIPT_NATIVE_DIALOG_FACTORY_H_
diff --git a/components/app_modal/views/javascript_app_modal_dialog_views.cc b/components/app_modal/views/javascript_app_modal_dialog_views.cc
index 8307e172..044d1bc 100644
--- a/components/app_modal/views/javascript_app_modal_dialog_views.cc
+++ b/components/app_modal/views/javascript_app_modal_dialog_views.cc
@@ -129,11 +129,7 @@
   parent_->OnClose();
 }
 
-views::Widget* JavaScriptAppModalDialogViews::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* JavaScriptAppModalDialogViews::GetWidget() const {
+const views::Widget* JavaScriptAppModalDialogViews::GetWidgetImpl() const {
   return message_box_view_->GetWidget();
 }
 
diff --git a/components/app_modal/views/javascript_app_modal_dialog_views.h b/components/app_modal/views/javascript_app_modal_dialog_views.h
index 1c978c77..3de56fb 100644
--- a/components/app_modal/views/javascript_app_modal_dialog_views.h
+++ b/components/app_modal/views/javascript_app_modal_dialog_views.h
@@ -43,10 +43,11 @@
   views::View* GetInitiallyFocusedView() override;
   bool ShouldShowCloseButton() const override;
   void WindowClosing() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
 
  private:
+  // views::DialogDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // A pointer to the AppModalDialog that owns us.
   std::unique_ptr<JavaScriptAppModalDialog> parent_;
 
diff --git a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
index 4e40e42..6053d3c 100644
--- a/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
+++ b/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -21,7 +21,6 @@
 #include "media/gpu/buffer_validation.h"
 #include "media/gpu/gpu_video_encode_accelerator_factory.h"
 #include "media/gpu/macros.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 
diff --git a/components/blacklist/opt_out_blacklist/BUILD.gn b/components/blacklist/opt_out_blacklist/BUILD.gn
index 05ab868..d2c01ceb3 100644
--- a/components/blacklist/opt_out_blacklist/BUILD.gn
+++ b/components/blacklist/opt_out_blacklist/BUILD.gn
@@ -13,9 +13,7 @@
     "opt_out_store.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/components/blacklist/opt_out_blacklist/sql/BUILD.gn b/components/blacklist/opt_out_blacklist/sql/BUILD.gn
index a115a7a..0277d0d 100644
--- a/components/blacklist/opt_out_blacklist/sql/BUILD.gn
+++ b/components/blacklist/opt_out_blacklist/sql/BUILD.gn
@@ -17,9 +17,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "opt_out_store_sql_unittest.cc",
-  ]
+  sources = [ "opt_out_store_sql_unittest.cc" ]
 
   deps = [
     ":opt_out_blacklist_sql",
diff --git a/components/cast_certificate/proto/BUILD.gn b/components/cast_certificate/proto/BUILD.gn
index a4eaee19..6cb9619 100644
--- a/components/cast_certificate/proto/BUILD.gn
+++ b/components/cast_certificate/proto/BUILD.gn
@@ -5,13 +5,9 @@
 import("//third_party/protobuf/proto_library.gni")
 
 proto_library("proto") {
-  sources = [
-    "revocation.proto",
-  ]
+  sources = [ "revocation.proto" ]
 }
 
 proto_library("unittest_proto") {
-  sources = [
-    "test_suite.proto",
-  ]
+  sources = [ "test_suite.proto" ]
 }
diff --git a/components/cdm/browser/BUILD.gn b/components/cdm/browser/BUILD.gn
index 2ea9d0b..190c343 100644
--- a/components/cdm/browser/BUILD.gn
+++ b/components/cdm/browser/BUILD.gn
@@ -30,9 +30,7 @@
 
 jumbo_source_set("unit_tests") {
   testonly = true
-  sources = [
-    "media_drm_storage_impl_unittest.cc",
-  ]
+  sources = [ "media_drm_storage_impl_unittest.cc" ]
   deps = [
     ":browser",
     "//base/test:test_support",
diff --git a/components/client_update_protocol/BUILD.gn b/components/client_update_protocol/BUILD.gn
index e22ee24..73962cbf 100644
--- a/components/client_update_protocol/BUILD.gn
+++ b/components/client_update_protocol/BUILD.gn
@@ -16,9 +16,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "ecdsa_unittest.cc",
-  ]
+  sources = [ "ecdsa_unittest.cc" ]
 
   deps = [
     ":client_update_protocol",
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn
index f5f1e2c..3968c1d 100644
--- a/components/component_updater/BUILD.gn
+++ b/components/component_updater/BUILD.gn
@@ -45,9 +45,7 @@
     "crl_set_remover.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 static_library("test_support") {
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index 7b1ca62..bcae2e7 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -19,15 +19,11 @@
     "crash_reporter_client.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("crashpad_handler_main") {
-  sources = [
-    "crashpad_handler_main.cc",
-  ]
+  sources = [ "crashpad_handler_main.cc" ]
 
   deps = [
     "//components/gwp_asan/buildflags",
@@ -67,9 +63,7 @@
 
   defines = [ "CRASH_IMPLEMENTATION" ]
 
-  public_deps = [
-    ":lib",
-  ]
+  public_deps = [ ":lib" ]
   deps = [
     "//base",
     "//build:branding_buildflags",
@@ -133,9 +127,7 @@
   }
 
   if (is_linux) {
-    data_deps = [
-      "//third_party/crashpad/crashpad/handler:crashpad_handler",
-    ]
+    data_deps = [ "//third_party/crashpad/crashpad/handler:crashpad_handler" ]
   }
 }
 
@@ -177,9 +169,7 @@
   # to depend on either :crash_export_thunks or :test_support, or in the case of
   # release binaries, on //chrome_elf, which re-exports the thunks.
   source_set("crash_export_thunk_include") {
-    sources = [
-      "crash_export_thunks.h",
-    ]
+    sources = [ "crash_export_thunks.h" ]
   }
 
   # This source set contains a set of functions that allow using the crashpad
@@ -224,9 +214,7 @@
   # We build a chromium-specific crashpad_handler executable so that we can
   # define custom UserStreamDataSources.
   executable("chrome_crashpad_handler") {
-    sources = [
-      "chrome_crashpad_handler.cc",
-    ]
+    sources = [ "chrome_crashpad_handler.cc" ]
 
     deps = [
       ":crashpad_handler_main",
@@ -262,17 +250,11 @@
   # installer will ignore files not named like a shared object, so give the
   # handler executable an acceptable name.
   copy("chrome_crashpad_handler_named_as_so") {
-    deps = [
-      ":chrome_crashpad_handler",
-    ]
+    deps = [ ":chrome_crashpad_handler" ]
 
-    sources = [
-      "$root_out_dir/chrome_crashpad_handler",
-    ]
+    sources = [ "$root_out_dir/chrome_crashpad_handler" ]
 
-    outputs = [
-      "$root_out_dir/libchrome_crashpad_handler.so",
-    ]
+    outputs = [ "$root_out_dir/libchrome_crashpad_handler.so" ]
   }
 }
 
@@ -281,9 +263,7 @@
 source_set("test_support") {
   testonly = true
 
-  deps = [
-    ":lib",
-  ]
+  deps = [ ":lib" ]
 
   if (is_win) {
     deps += [ ":crash_export_stubs" ]
diff --git a/components/crash/content/browser/BUILD.gn b/components/crash/content/browser/BUILD.gn
index 0f38a770..d06fa485 100644
--- a/components/crash/content/browser/BUILD.gn
+++ b/components/crash/content/browser/BUILD.gn
@@ -63,9 +63,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "crash_metrics_reporter_android_unittest.cc",
-  ]
+  sources = [ "crash_metrics_reporter_android_unittest.cc" ]
   deps = [
     ":browser",
     "//base/test:test_support",
diff --git a/components/exo/fullscreen_shell_surface.cc b/components/exo/fullscreen_shell_surface.cc
index b2bc0b7..6f631997 100644
--- a/components/exo/fullscreen_shell_surface.cc
+++ b/components/exo/fullscreen_shell_surface.cc
@@ -171,14 +171,6 @@
   widget_ = nullptr;
 }
 
-views::Widget* FullscreenShellSurface::GetWidget() {
-  return widget_;
-}
-
-const views::Widget* FullscreenShellSurface::GetWidget() const {
-  return widget_;
-}
-
 views::View* FullscreenShellSurface::GetContentsView() {
   return this;
 }
@@ -224,6 +216,10 @@
   child_ax_tree_id_ = child_ax_tree_id;
 }
 
+const views::Widget* FullscreenShellSurface::GetWidgetImpl() const {
+  return widget_;
+}
+
 void FullscreenShellSurface::UpdateHostWindowBounds() {
   // This method applies multiple changes to the window tree. Use ScopedPause
   // to ensure that occlusion isn't recomputed before all changes have been
diff --git a/components/exo/fullscreen_shell_surface.h b/components/exo/fullscreen_shell_surface.h
index c867a791c..0919b0b0 100644
--- a/components/exo/fullscreen_shell_surface.h
+++ b/components/exo/fullscreen_shell_surface.h
@@ -69,8 +69,6 @@
   bool CanMinimize() const override;
   bool ShouldShowWindowTitle() const override;
   void WindowClosing() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   views::View* GetContentsView() override;
   bool WidgetHasHitTestMask() const override;
   void GetWidgetHitTestMask(SkPath* mask) const override;
@@ -84,6 +82,9 @@
   void SetChildAxTreeId(ui::AXTreeID child_ax_tree_id);
 
  private:
+  // views::WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // Keep the bounds in sync with the root surface bounds.
   void UpdateHostWindowBounds() override;
 
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc
index e9f8eb9..51296b2 100644
--- a/components/exo/shell_surface_base.cc
+++ b/components/exo/shell_surface_base.cc
@@ -695,14 +695,6 @@
   widget_ = nullptr;
 }
 
-views::Widget* ShellSurfaceBase::GetWidget() {
-  return widget_;
-}
-
-const views::Widget* ShellSurfaceBase::GetWidget() const {
-  return widget_;
-}
-
 views::View* ShellSurfaceBase::GetContentsView() {
   return this;
 }
@@ -1081,6 +1073,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ShellSurfaceBase, private:
 
+const views::Widget* ShellSurfaceBase::GetWidgetImpl() const {
+  return widget_;
+}
+
 float ShellSurfaceBase::GetScale() const {
   return 1.f;
 }
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h
index 652950e3..066f475 100644
--- a/components/exo/shell_surface_base.h
+++ b/components/exo/shell_surface_base.h
@@ -162,8 +162,6 @@
   gfx::ImageSkia GetWindowIcon() override;
   bool OnCloseRequested(views::Widget::ClosedReason close_reason) override;
   void WindowClosing() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   views::View* GetContentsView() override;
   views::NonClientFrameView* CreateNonClientFrameView(
       views::Widget* widget) override;
@@ -265,6 +263,9 @@
   FRIEND_TEST_ALL_PREFIXES(ShellSurfaceTest,
                            HostWindowBoundsUpdatedAfterCommitWidget);
 
+  // WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   // Called on widget creation to initialize its window state.
   // TODO(reveman): Remove virtual functions below to avoid FBC problem.
   virtual void InitializeWindowState(ash::WindowState* window_state) = 0;
diff --git a/components/image_fetcher/ios/BUILD.gn b/components/image_fetcher/ios/BUILD.gn
index 015a12f..8644fc4 100644
--- a/components/image_fetcher/ios/BUILD.gn
+++ b/components/image_fetcher/ios/BUILD.gn
@@ -56,8 +56,6 @@
     "//components/test/data/webp_transcode/test_small.tiff",
     "//components/test/data/webp_transcode/test_small.webp",
   ]
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
-        "{{source_file_part}}",
-  ]
+  outputs = [ "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
+              "{{source_file_part}}" ]
 }
diff --git a/components/module_installer/android/BUILD.gn b/components/module_installer/android/BUILD.gn
index 2f91065..672b77f 100644
--- a/components/module_installer/android/BUILD.gn
+++ b/components/module_installer/android/BUILD.gn
@@ -63,15 +63,11 @@
 
 java_library("module_interface_java") {
   supports_android = true
-  sources = [
-    "java/src/org/chromium/components/module_installer/builder/ModuleInterface.java",
-  ]
+  sources = [ "java/src/org/chromium/components/module_installer/builder/ModuleInterface.java" ]
 }
 
 java_annotation_processor("module_interface_processor") {
-  sources = [
-    "java/src/org/chromium/components/module_installer/builder/ModuleInterfaceProcessor.java",
-  ]
+  sources = [ "java/src/org/chromium/components/module_installer/builder/ModuleInterfaceProcessor.java" ]
   main_class = "org.chromium.components.module_installer.builder.ModuleInterfaceProcessor"
   annotation_processor_deps =
       [ "//third_party/android_deps:auto_service_processor" ]
@@ -85,9 +81,7 @@
 }
 
 source_set("native") {
-  sources = [
-    "module.cc",
-  ]
+  sources = [ "module.cc" ]
   deps = [
     ":jni_headers",
     "//base",
diff --git a/components/module_installer/android/module_desc_java.gni b/components/module_installer/android/module_desc_java.gni
index 5db20f0..23b33fa4 100644
--- a/components/module_installer/android/module_desc_java.gni
+++ b/components/module_installer/android/module_desc_java.gni
@@ -27,9 +27,7 @@
     if (defined(invoker.shared_libraries)) {
       deps = invoker.shared_libraries
     }
-    outputs = [
-      _libraries,
-    ]
+    outputs = [ _libraries ]
     data_keys = [ "shared_libraries" ]
     walk_keys = [ "shared_libraries_barrier" ]
     rebase = root_build_dir
@@ -39,15 +37,9 @@
   _srcjar = "$target_gen_dir/${_target_name}__srcjar.srcjar"
   action_with_pydeps("${_target_name}__srcjar") {
     script = "//components/module_installer/android/module_desc_java.py"
-    deps = [
-      ":${_target_name}__libraries",
-    ]
-    inputs = [
-      _libraries,
-    ]
-    outputs = [
-      _srcjar,
-    ]
+    deps = [ ":${_target_name}__libraries" ]
+    inputs = [ _libraries ]
+    outputs = [ _srcjar ]
     args = [
       "--module",
       invoker.module_name,
diff --git a/components/nacl/broker/BUILD.gn b/components/nacl/broker/BUILD.gn
index b942bad..bdf2296 100644
--- a/components/nacl/broker/BUILD.gn
+++ b/components/nacl/broker/BUILD.gn
@@ -69,18 +69,12 @@
     }
     nacl64_label = ":nacl64($x64_toolchain)"
     nacl64_out_dir = get_label_info(nacl64_label, "root_out_dir")
-    sources = [
-      "$nacl64_out_dir/nacl64.exe",
-    ]
+    sources = [ "$nacl64_out_dir/nacl64.exe" ]
     if (symbol_level != 0) {
       sources += [ "$nacl64_out_dir/nacl64.exe.pdb" ]
     }
-    outputs = [
-      "$root_out_dir/{{source_file_part}}",
-    ]
-    deps = [
-      nacl64_label,
-    ]
+    outputs = [ "$root_out_dir/{{source_file_part}}" ]
+    deps = [ nacl64_label ]
   }
 } else if (current_cpu == "x64") {
   # In the x64 toolchain context, build nacl64.exe for real.
@@ -98,9 +92,7 @@
       ldflags = [ "/OPT:REF" ]
     }
 
-    sources = [
-      "//chrome/nacl/nacl_exe_win_64.cc",
-    ]
+    sources = [ "//chrome/nacl/nacl_exe_win_64.cc" ]
 
     deps = [
       ":broker",
diff --git a/components/nacl/common/BUILD.gn b/components/nacl/common/BUILD.gn
index 5e0c304..4ea9335 100644
--- a/components/nacl/common/BUILD.gn
+++ b/components/nacl/common/BUILD.gn
@@ -55,9 +55,7 @@
     ]
 
     # Deps required by the above headers.
-    deps = [
-      "//media:media_buildflags",
-    ]
+    deps = [ "//media:media_buildflags" ]
   }
 
   static_library("common") {
@@ -99,34 +97,25 @@
       "nacl_debug_exception_handler_win.h",
     ]
 
-    deps = [
-      "//base",
-    ]
+    deps = [ "//base" ]
   }
 
   source_set("nacl_error_code") {
-    sources = [
-      "//native_client/src/trusted/service_runtime/nacl_error_code.h",
-    ]
+    sources =
+        [ "//native_client/src/trusted/service_runtime/nacl_error_code.h" ]
   }
 
   mojom("mojo_bindings") {
-    sources = [
-      "nacl.mojom",
-    ]
+    sources = [ "nacl.mojom" ]
   }
 }
 
 # Depending on this allows targets to unconditionally include
 # nacl_process_type.h without testing whether nacl is enabled.
 source_set("process_type") {
-  public = [
-    "nacl_process_type.h",
-  ]
+  public = [ "nacl_process_type.h" ]
 
-  deps = [
-    "//content/public/common",
-  ]
+  deps = [ "//content/public/common" ]
 }
 
 static_library("switches") {
diff --git a/components/nacl/loader/BUILD.gn b/components/nacl/loader/BUILD.gn
index e6030d0..75d7465 100644
--- a/components/nacl/loader/BUILD.gn
+++ b/components/nacl/loader/BUILD.gn
@@ -62,15 +62,11 @@
   ]
 
   # Deps required by the above headers.
-  deps = [
-    "//media:media_buildflags",
-  ]
+  deps = [ "//media:media_buildflags" ]
 }
 
 source_set("loader") {
-  public_deps = [
-    ":minimal",
-  ]
+  public_deps = [ ":minimal" ]
   deps = [
     "//components/nacl/common",
     "//content/public/common",
@@ -160,33 +156,24 @@
       configs -= [ "//build/config/compiler:export_dynamic" ]
     }
 
-    data_deps = [
-      "//native_client/src/trusted/service_runtime/linux:bootstrap",
-    ]
+    data_deps =
+        [ "//native_client/src/trusted/service_runtime/linux:bootstrap" ]
   }
 
   # For setting up nacl_helper.
   source_set("nacl_helper_integration") {
-    public = [
-      "nacl_helper_linux.h",
-    ]
-    data_deps = [
-      ":nacl_helper",
-    ]
+    public = [ "nacl_helper_linux.h" ]
+    data_deps = [ ":nacl_helper" ]
   }
 
   if (enable_nacl_nonsfi) {
     test("nacl_helper_nonsfi_unittests") {
-      sources = [
-        "nonsfi/nacl_helper_nonsfi_unittests.cc",
-      ]
+      sources = [ "nonsfi/nacl_helper_nonsfi_unittests.cc" ]
       deps = [
         "//base",
         "//base/test:test_launcher_nacl_nonsfi",
       ]
-      data_deps = [
-        ":nacl_helper_nonsfi_unittests_main_copy(//build/toolchain/nacl:newlib_pnacl_nonsfi)",
-      ]
+      data_deps = [ ":nacl_helper_nonsfi_unittests_main_copy(//build/toolchain/nacl:newlib_pnacl_nonsfi)" ]
     }
 
     group("helper_nonsfi") {
@@ -278,15 +265,9 @@
   }
 
   copy("nacl_helper_nonsfi_copy") {
-    sources = [
-      "${root_out_dir}/nacl_helper_nonsfi",
-    ]
-    outputs = [
-      "${root_build_dir}/{{source_file_part}}",
-    ]
-    deps = [
-      ":nacl_helper_nonsfi_nexe",
-    ]
+    sources = [ "${root_out_dir}/nacl_helper_nonsfi" ]
+    outputs = [ "${root_build_dir}/{{source_file_part}}" ]
+    deps = [ ":nacl_helper_nonsfi_nexe" ]
   }
 
   test("nacl_helper_nonsfi_unittests_main") {
@@ -311,14 +292,8 @@
 
   copy("nacl_helper_nonsfi_unittests_main_copy") {
     testonly = true
-    sources = [
-      "${root_out_dir}/nacl_helper_nonsfi_unittests_main",
-    ]
-    outputs = [
-      "${root_build_dir}/{{source_file_part}}",
-    ]
-    deps = [
-      ":nacl_helper_nonsfi_unittests_main",
-    ]
+    sources = [ "${root_out_dir}/nacl_helper_nonsfi_unittests_main" ]
+    outputs = [ "${root_build_dir}/{{source_file_part}}" ]
+    deps = [ ":nacl_helper_nonsfi_unittests_main" ]
   }
 }
diff --git a/components/optimization_guide/optimization_guide_decider.h b/components/optimization_guide/optimization_guide_decider.h
index 3ccf126..33c3c68 100644
--- a/components/optimization_guide/optimization_guide_decider.h
+++ b/components/optimization_guide/optimization_guide_decider.h
@@ -38,6 +38,9 @@
 
   // Only applicable for the PERFORMANCE_HINTS optimization type.
   proto::PerformanceHintsMetadata performance_hints_metadata;
+
+  // Only applicable for the COMPRESS_PUBLIC_IMAGES optimization type.
+  proto::PublicImageMetadata public_image_metadata;
 };
 
 class OptimizationGuideDecider {
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc
index 9d3328fd..3d46ac06 100644
--- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc
@@ -50,11 +50,6 @@
                             internal::FIRST_MEANINGFUL_PAINT_LAST_ENTRY);
 }
 
-void RecordTimeToInteractiveStatus(internal::TimeToInteractiveStatus status) {
-  UMA_HISTOGRAM_ENUMERATION(internal::kHistogramTimeToInteractiveStatus, status,
-                            internal::TIME_TO_INTERACTIVE_LAST_ENTRY);
-}
-
 }  // namespace
 
 namespace internal {
@@ -101,10 +96,6 @@
 const char kHistogramLargestContentfulPaintMainFrameContentType[] =
     "PageLoad.Internal.PaintTiming.LargestContentfulPaint.MainFrame."
     "ContentType";
-const char kHistogramTimeToInteractive[] =
-    "PageLoad.Experimental.NavigationToInteractive";
-const char kHistogramInteractiveToInteractiveDetection[] =
-    "PageLoad.Internal.InteractiveToInteractiveDetection";
 const char kHistogramFirstInputDelay[] =
     "PageLoad.InteractiveTiming.FirstInputDelay3";
 const char kHistogramFirstInputTimestamp[] =
@@ -212,9 +203,6 @@
 const char kHistogramFirstMeaningfulPaintStatus[] =
     "PageLoad.Experimental.PaintTiming.FirstMeaningfulPaintStatus";
 
-const char kHistogramTimeToInteractiveStatus[] =
-    "PageLoad.Experimental.TimeToInteractiveStatus";
-
 const char kHistogramFirstNonScrollInputAfterFirstPaint[] =
     "PageLoad.InputTiming.NavigationToFirstNonScroll.AfterPaint";
 const char kHistogramFirstScrollInputAfterFirstPaint[] =
@@ -531,40 +519,6 @@
   }
 }
 
-void CorePageLoadMetricsObserver::OnPageInteractive(
-    const page_load_metrics::mojom::PageLoadTiming& timing) {
-  // Both interactive and interactive detection time must be present.
-  DCHECK(timing.interactive_timing->interactive);
-  DCHECK(timing.interactive_timing->interactive_detection);
-  DCHECK_GE(timing.interactive_timing->interactive_detection.value(),
-            timing.interactive_timing->interactive.value());
-
-  if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
-          timing.interactive_timing->interactive_detection, GetDelegate())) {
-    RecordTimeToInteractiveStatus(internal::TIME_TO_INTERACTIVE_BACKGROUNDED);
-    return;
-  }
-
-  if (timing.interactive_timing->first_invalidating_input &&
-      timing.interactive_timing->first_invalidating_input.value() <
-          timing.interactive_timing->interactive) {
-    RecordTimeToInteractiveStatus(
-        internal::TIME_TO_INTERACTIVE_USER_INTERACTION_BEFORE_INTERACTIVE);
-    return;
-  }
-
-  base::TimeDelta time_to_interactive =
-      timing.interactive_timing->interactive.value();
-  base::TimeDelta interactive_to_detection =
-      timing.interactive_timing->interactive_detection.value() -
-      time_to_interactive;
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramTimeToInteractive,
-                      time_to_interactive);
-  PAGE_LOAD_HISTOGRAM(internal::kHistogramInteractiveToInteractiveDetection,
-                      interactive_to_detection);
-  RecordTimeToInteractiveStatus(internal::TIME_TO_INTERACTIVE_RECORDED);
-}
-
 void CorePageLoadMetricsObserver::OnFirstInputInPage(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground(
@@ -848,15 +802,6 @@
                   FIRST_MEANINGFUL_PAINT_DID_NOT_REACH_FIRST_CONTENTFUL_PAINT);
   }
 
-  if (main_frame_timing.paint_timing->first_paint &&
-      !main_frame_timing.interactive_timing->interactive) {
-    RecordTimeToInteractiveStatus(
-        main_frame_timing.paint_timing->first_meaningful_paint
-            ? internal::TIME_TO_INTERACTIVE_DID_NOT_REACH_QUIESCENCE
-            : internal::
-                  TIME_TO_INTERACTIVE_DID_NOT_REACH_FIRST_MEANINGFUL_PAINT);
-  }
-
   if (main_frame_timing.interactive_timing->longest_input_timestamp) {
     DCHECK(main_frame_timing.interactive_timing->longest_input_delay);
     UMA_HISTOGRAM_CUSTOM_TIMES(
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h
index 2e88380..5f7d1e1d 100644
--- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h
+++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h
@@ -37,7 +37,6 @@
 extern const char kHistogramLargestContentfulPaintContentType[];
 extern const char kHistogramLargestContentfulPaintMainFrame[];
 extern const char kHistogramLargestContentfulPaintMainFrameContentType[];
-extern const char kHistogramTimeToInteractive[];
 extern const char kHistogramParseDuration[];
 extern const char kHistogramParseBlockedOnScriptLoad[];
 extern const char kHistogramParseBlockedOnScriptExecution[];
@@ -67,7 +66,6 @@
 extern const char kHistogramForegroundToFirstMeaningfulPaint[];
 
 extern const char kHistogramFirstMeaningfulPaintStatus[];
-extern const char kHistogramTimeToInteractiveStatus[];
 
 extern const char kHistogramFirstNonScrollInputAfterFirstPaint[];
 extern const char kHistogramFirstScrollInputAfterFirstPaint[];
@@ -115,55 +113,6 @@
   FIRST_MEANINGFUL_PAINT_LAST_ENTRY
 };
 
-// Different events can prevent us from recording a successful time to
-// interactive value, and sometimes several of these failure events can happen
-// simultaneously. In the case of multiple invalidating events, we record the
-// failure reason in decreasing order of priority of the following:
-//
-// 1. Did not reach First Meaningful Paint
-// 2. Did not reach quiescence
-// 3. Page was not in foreground until TTI was detected.
-// 4. There was a non-mouse-move user input before interactive time.
-//
-// Table of conditions and the TTI Status recorded for each case:
-// FMP Reached | Quiesence Reached | Always Foreground | No User Input | Status
-// True        | True              | True              | True          | 0
-// True        | True              | True              | False         | 2
-// True        | True              | False             | *             | 1
-// True        | False             | *                 | *             | 3
-// False       | *                 | *                 | *             | 4
-enum TimeToInteractiveStatus {
-  // Time to Interactive recorded successfully.
-  TIME_TO_INTERACTIVE_RECORDED = 0,
-
-  // Main thread and network quiescence reached, but the user backgrounded the
-  // page at least once before reaching quiescence.
-  TIME_TO_INTERACTIVE_BACKGROUNDED = 1,
-
-  // Main thread and network quiescence reached, but there was a non-mouse-move
-  // user input that hit the renderer main thread between navigation start and
-  // interactive time, so the detected interactive time is inaccurate. Note that
-  // Time to Interactive is not invalidated if the user input is after
-  // interactive time, but before quiescence windows are detected. User input
-  // invalidation has less priority than backgrounding - if there was an input
-  // event before reaching interactive, but the page was backgrounded before
-  // reaching interactive detection, the status is recorded as backgrounded
-  // instead of user-interaction-before-interactive.
-  TIME_TO_INTERACTIVE_USER_INTERACTION_BEFORE_INTERACTIVE = 2,
-
-  // User left page before main thread and network quiescence, but after First
-  // Meaningful Paint.
-  TIME_TO_INTERACTIVE_DID_NOT_REACH_QUIESCENCE = 3,
-
-  // User left page before First Meaningful Paint happened, but after First
-  // Paint. This status will also be recorded if the first meaningful paint was
-  // reached on the renderer, but invalidated there due to user input. Input
-  // invalided First Meaningful Paint values do not reach the browser.
-  TIME_TO_INTERACTIVE_DID_NOT_REACH_FIRST_MEANINGFUL_PAINT = 4,
-
-  TIME_TO_INTERACTIVE_LAST_ENTRY
-};
-
 }  // namespace internal
 
 // Observer responsible for recording 'core' page load metrics. Core metrics are
@@ -194,8 +143,6 @@
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnFirstMeaningfulPaintInMainFrameDocument(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
-  void OnPageInteractive(
-      const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnFirstInputInPage(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnParseStart(
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc
index a588960..93c1862 100644
--- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc
+++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc
@@ -1277,122 +1277,6 @@
       internal::kHistogramForegroundToFirstMeaningfulPaint, 1);
 }
 
-TEST_F(CorePageLoadMetricsObserverTest, TimeToInteractiveAlwaysForeground) {
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.interactive_timing->interactive =
-      base::TimeDelta::FromMilliseconds(100);
-  timing.interactive_timing->interactive_detection =
-      base::TimeDelta::FromMilliseconds(5200);
-  PopulateRequiredTimingFields(&timing);
-
-  NavigateAndCommit(GURL(kDefaultTestUrl));
-  tester()->SimulateTimingUpdate(timing);
-  NavigateAndCommit(GURL(kDefaultTestUrl2));
-
-  tester()->histogram_tester().ExpectTotalCount(
-      internal::kHistogramTimeToInteractive, 1);
-  tester()->histogram_tester().ExpectBucketCount(
-      internal::kHistogramTimeToInteractiveStatus,
-      internal::TIME_TO_INTERACTIVE_RECORDED, 1);
-}
-
-TEST_F(CorePageLoadMetricsObserverTest, TimeToInteractiveStatusBackgrounded) {
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.interactive_timing->interactive =
-      base::TimeDelta::FromMilliseconds(100);
-  timing.interactive_timing->interactive_detection =
-      base::TimeDelta::FromMilliseconds(5200);
-  PopulateRequiredTimingFields(&timing);
-
-  NavigateAndCommit(GURL(kDefaultTestUrl));
-
-  // Background the tab, then foreground it.
-  web_contents()->WasHidden();
-  web_contents()->WasShown();
-
-  tester()->SimulateTimingUpdate(timing);
-
-  // Navigate again to force histogram recording.
-  NavigateAndCommit(GURL(kDefaultTestUrl2));
-
-  tester()->histogram_tester().ExpectTotalCount(
-      internal::kHistogramTimeToInteractive, 0);
-  tester()->histogram_tester().ExpectUniqueSample(
-      internal::kHistogramTimeToInteractiveStatus,
-      internal::TIME_TO_INTERACTIVE_BACKGROUNDED, 1);
-}
-
-TEST_F(CorePageLoadMetricsObserverTest,
-       TimeToInteractiveStatusUserInteractionBeforeInteractive) {
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.paint_timing->first_meaningful_paint =
-      base::TimeDelta::FromMilliseconds(200);
-  timing.interactive_timing->first_invalidating_input =
-      base::TimeDelta::FromMilliseconds(1000);
-  timing.interactive_timing->interactive =
-      base::TimeDelta::FromMilliseconds(2000);
-  timing.interactive_timing->interactive_detection =
-      base::TimeDelta::FromMilliseconds(7100);
-  PopulateRequiredTimingFields(&timing);
-
-  NavigateAndCommit(GURL(kDefaultTestUrl));
-  tester()->SimulateTimingUpdate(timing);
-  // Navigate again to force histogram recording.
-  NavigateAndCommit(GURL(kDefaultTestUrl2));
-
-  tester()->histogram_tester().ExpectTotalCount(
-      internal::kHistogramTimeToInteractive, 0);
-  tester()->histogram_tester().ExpectUniqueSample(
-      internal::kHistogramTimeToInteractiveStatus,
-      internal::TIME_TO_INTERACTIVE_USER_INTERACTION_BEFORE_INTERACTIVE, 1);
-}
-
-TEST_F(CorePageLoadMetricsObserverTest,
-       TimeToInteractiveStatusDidNotReachQuiescence) {
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.paint_timing->first_meaningful_paint =
-      base::TimeDelta::FromMilliseconds(200);
-  PopulateRequiredTimingFields(&timing);
-
-  NavigateAndCommit(GURL(kDefaultTestUrl));
-  tester()->SimulateTimingUpdate(timing);
-  // Navigate again to force histogram recording.
-  NavigateAndCommit(GURL(kDefaultTestUrl2));
-
-  tester()->histogram_tester().ExpectTotalCount(
-      internal::kHistogramTimeToInteractive, 0);
-  tester()->histogram_tester().ExpectUniqueSample(
-      internal::kHistogramTimeToInteractiveStatus,
-      internal::TIME_TO_INTERACTIVE_DID_NOT_REACH_QUIESCENCE, 1);
-}
-
-TEST_F(CorePageLoadMetricsObserverTest, TimeToInteractiveStatusDidNotReachFMP) {
-  page_load_metrics::mojom::PageLoadTiming timing;
-  page_load_metrics::InitPageLoadTimingForTest(&timing);
-  timing.navigation_start = base::Time::FromDoubleT(1);
-  timing.paint_timing->first_paint = base::TimeDelta::FromMilliseconds(200);
-  PopulateRequiredTimingFields(&timing);
-
-  NavigateAndCommit(GURL(kDefaultTestUrl));
-  tester()->SimulateTimingUpdate(timing);
-  // Navigate again to force histogram recording.
-  NavigateAndCommit(GURL(kDefaultTestUrl2));
-
-  tester()->histogram_tester().ExpectTotalCount(
-      internal::kHistogramTimeToInteractive, 0);
-  tester()->histogram_tester().ExpectUniqueSample(
-      internal::kHistogramTimeToInteractiveStatus,
-      internal::TIME_TO_INTERACTIVE_DID_NOT_REACH_FIRST_MEANINGFUL_PAINT, 1);
-}
-
 TEST_F(CorePageLoadMetricsObserverTest, FirstInputDelayAndTimestamp) {
   page_load_metrics::mojom::PageLoadTiming timing;
   page_load_metrics::InitPageLoadTimingForTest(&timing);
diff --git a/components/printing/browser/BUILD.gn b/components/printing/browser/BUILD.gn
index 937529a..ddf0569 100644
--- a/components/printing/browser/BUILD.gn
+++ b/components/printing/browser/BUILD.gn
@@ -73,9 +73,7 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "printer_capabilities_unittest.cc",
-  ]
+  sources = [ "printer_capabilities_unittest.cc" ]
 
   deps = [
     "//base",
diff --git a/components/printing/common/BUILD.gn b/components/printing/common/BUILD.gn
index 8f5311538..0a1e9fbf 100644
--- a/components/printing/common/BUILD.gn
+++ b/components/printing/common/BUILD.gn
@@ -29,9 +29,7 @@
 }
 
 mojom("mojo_interfaces") {
-  sources = [
-    "print.mojom",
-  ]
+  sources = [ "print.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/components/pwg_encoder/BUILD.gn b/components/pwg_encoder/BUILD.gn
index 96ae2541..7ef4527 100644
--- a/components/pwg_encoder/BUILD.gn
+++ b/components/pwg_encoder/BUILD.gn
@@ -23,9 +23,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "pwg_encoder_unittest.cc",
-  ]
+  sources = [ "pwg_encoder_unittest.cc" ]
 
   deps = [
     ":pwg_encoder",
diff --git a/components/scheduling_metrics/BUILD.gn b/components/scheduling_metrics/BUILD.gn
index cc99e7fd..b1ceecd 100644
--- a/components/scheduling_metrics/BUILD.gn
+++ b/components/scheduling_metrics/BUILD.gn
@@ -14,9 +14,7 @@
 
   defines = [ "IS_SCHEDULING_METRICS_IMPL" ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/components/services/pdf_compositor/BUILD.gn b/components/services/pdf_compositor/BUILD.gn
index 2e0e99a..5b72f435 100644
--- a/components/services/pdf_compositor/BUILD.gn
+++ b/components/services/pdf_compositor/BUILD.gn
@@ -27,17 +27,13 @@
     deps += [ "//content/public/child" ]
   }
 
-  public_deps = [
-    "//components/services/pdf_compositor/public/mojom",
-  ]
+  public_deps = [ "//components/services/pdf_compositor/public/mojom" ]
 }
 
 if (enable_basic_printing) {
   source_set("unit_tests") {
     testonly = true
-    sources = [
-      "pdf_compositor_impl_unittest.cc",
-    ]
+    sources = [ "pdf_compositor_impl_unittest.cc" ]
 
     include_dirs = [
       "//skia/config",
diff --git a/components/services/pdf_compositor/public/cpp/BUILD.gn b/components/services/pdf_compositor/public/cpp/BUILD.gn
index 799b9eca..ea198e9 100644
--- a/components/services/pdf_compositor/public/cpp/BUILD.gn
+++ b/components/services/pdf_compositor/public/cpp/BUILD.gn
@@ -3,11 +3,7 @@
 # found in the LICENSE file.
 
 source_set("cpp") {
-  sources = [
-    "pdf_service_mojo_types.h",
-  ]
+  sources = [ "pdf_service_mojo_types.h" ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
diff --git a/components/services/pdf_compositor/public/mojom/BUILD.gn b/components/services/pdf_compositor/public/mojom/BUILD.gn
index 901dfb9..412ca45b 100644
--- a/components/services/pdf_compositor/public/mojom/BUILD.gn
+++ b/components/services/pdf_compositor/public/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "pdf_compositor.mojom",
-  ]
+  sources = [ "pdf_compositor.mojom" ]
   public_deps = [
     "//components/discardable_memory/public/mojom",
     "//mojo/public/mojom/base",
diff --git a/components/services/quarantine/BUILD.gn b/components/services/quarantine/BUILD.gn
index 47d1c6d..59f2506 100644
--- a/components/services/quarantine/BUILD.gn
+++ b/components/services/quarantine/BUILD.gn
@@ -18,9 +18,7 @@
     "quarantine_win.cc",
   ]
 
-  public_deps = [
-    "//components/services/quarantine/public/mojom",
-  ]
+  public_deps = [ "//components/services/quarantine/public/mojom" ]
 
   deps = [
     ":common",
diff --git a/components/services/quarantine/public/cpp/BUILD.gn b/components/services/quarantine/public/cpp/BUILD.gn
index d0bb725..40fab13 100644
--- a/components/services/quarantine/public/cpp/BUILD.gn
+++ b/components/services/quarantine/public/cpp/BUILD.gn
@@ -11,8 +11,6 @@
       "quarantine_features_win.h",
     ]
 
-    public_deps = [
-      "//base",
-    ]
+    public_deps = [ "//base" ]
   }
 }
diff --git a/components/services/quarantine/public/mojom/BUILD.gn b/components/services/quarantine/public/mojom/BUILD.gn
index 0c9f91ac..4282d890 100644
--- a/components/services/quarantine/public/mojom/BUILD.gn
+++ b/components/services/quarantine/public/mojom/BUILD.gn
@@ -5,9 +5,7 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "quarantine.mojom",
-  ]
+  sources = [ "quarantine.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/components/services/storage/public/mojom/indexed_db_control.mojom b/components/services/storage/public/mojom/indexed_db_control.mojom
index 05c8e18..baad7d0 100644
--- a/components/services/storage/public/mojom/indexed_db_control.mojom
+++ b/components/services/storage/public/mojom/indexed_db_control.mojom
@@ -4,9 +4,22 @@
 
 module storage.mojom;
 
+import "mojo/public/mojom/base/file_path.mojom";
+import "mojo/public/mojom/base/values.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "url/mojom/origin.mojom";
 
+// Recorded in histograms, so append only.
+enum ForceCloseReason {
+  FORCE_CLOSE_DELETE_ORIGIN = 0,
+  FORCE_CLOSE_BACKING_STORE_FAILURE = 1,
+  FORCE_CLOSE_INTERNALS_PAGE = 2,
+  FORCE_CLOSE_COPY_ORIGIN = 3,
+  FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE = 4,
+  // Append new values here and update IDBContextForcedCloseReason in
+  // enums.xml.
+};
+
 // Conveys basic information about a single origin's data in IndexedDB.
 struct IndexedDBStorageUsageInfo {
   // The origin whose metadata is represented by this structure.
@@ -33,4 +46,22 @@
 
   // Deletes all indexed db files for the given origin.
   DeleteForOrigin(url.mojom.Origin origin) => (bool success);
+
+  // Forcibly closes all connections to all databases within the origin.
+  ForceClose(url.mojom.Origin origin, ForceCloseReason reason) => ();
+
+  // Returns the current number of connections.
+  GetConnectionCount(url.mojom.Origin origin) => (uint64 connection_count);
+
+  // Called by chrome://indexeddb-internals to download all of the indexeddb
+  // data for a particular origin.  This creates a zip file at |zip_path|
+  // using the temporary direction |temp_path| which needs to be cleaned up
+  // after the user downloads the file.
+  DownloadOriginData(url.mojom.Origin origin) => (
+      bool success,
+      mojo_base.mojom.FilePath temp_path,
+      mojo_base.mojom.FilePath zip_path);
+
+  // Called by chrome://indexeddb-internals to populate its page details.
+  GetAllOriginsDetails() => (bool incognito, mojo_base.mojom.ListValue details);
 };
diff --git a/components/storage_monitor/BUILD.gn b/components/storage_monitor/BUILD.gn
index fa5d2c0..1108f78 100644
--- a/components/storage_monitor/BUILD.gn
+++ b/components/storage_monitor/BUILD.gn
@@ -118,15 +118,11 @@
   ]
 
   if (is_chromeos && use_dbus) {
-    deps = [
-      "//services/device/public/mojom",
-    ]
+    deps = [ "//services/device/public/mojom" ]
   }
 
   if (is_win) {
-    deps = [
-      "//testing/gtest",
-    ]
+    deps = [ "//testing/gtest" ]
   }
 }
 
diff --git a/components/upload_list/BUILD.gn b/components/upload_list/BUILD.gn
index 28aaec4..9596549 100644
--- a/components/upload_list/BUILD.gn
+++ b/components/upload_list/BUILD.gn
@@ -12,16 +12,12 @@
     "upload_list.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [
-    "text_log_upload_list_unittest.cc",
-  ]
+  sources = [ "text_log_upload_list_unittest.cc" ]
 
   deps = [
     ":upload_list",
diff --git a/components/wifi/BUILD.gn b/components/wifi/BUILD.gn
index 6c47f52..07dac29 100644
--- a/components/wifi/BUILD.gn
+++ b/components/wifi/BUILD.gn
@@ -54,9 +54,7 @@
 }
 
 executable("wifi_test") {
-  sources = [
-    "wifi_test.cc",
-  ]
+  sources = [ "wifi_test.cc" ]
 
   deps = [
     ":wifi",
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index 53a8f8f..64a1f5d1 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -256,8 +256,9 @@
             ->leveldb_state()
             ->RequestDestruction(loop.QuitClosure(),
                                  base::SequencedTaskRunnerHandle::Get());
-        idb_context_->ForceClose(
-            origin, IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN);
+        idb_context_->ForceCloseSync(
+            origin,
+            storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
         loop.Run();
       }
       // All leveldb databases are closed, and they can be deleted.
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
index f14452a9..76511b9 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/sequenced_task_runner.h"
@@ -39,6 +40,7 @@
 #include "storage/common/database/database_identifier.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+#include "third_party/zlib/google/zip.h"
 #include "ui/base/text/bytes_formatting.h"
 #include "url/origin.h"
 
@@ -53,6 +55,15 @@
 
 namespace {
 
+bool IsAllowedPath(const std::vector<base::FilePath>& allowed_paths,
+                   const base::FilePath& candidate_path) {
+  for (const base::FilePath& allowed_path : allowed_paths) {
+    if (candidate_path == allowed_path || allowed_path.IsParent(candidate_path))
+      return true;
+  }
+  return false;
+}
+
 // This may be called after the IndexedDBContext is destroyed.
 void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path,
                            std::vector<Origin>* origins,
@@ -135,7 +146,8 @@
 void IndexedDBContextImpl::DeleteForOrigin(const Origin& origin,
                                            DeleteForOriginCallback callback) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  ForceClose(origin, FORCE_CLOSE_DELETE_ORIGIN);
+  ForceCloseSync(origin,
+                 storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
   if (!HasOrigin(origin)) {
     std::move(callback).Run(true);
     return;
@@ -163,46 +175,84 @@
   std::move(callback).Run(s.ok());
 }
 
-IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() {
+void IndexedDBContextImpl::ForceClose(const Origin& origin,
+                                      storage::mojom::ForceCloseReason reason,
+                                      base::OnceClosure closure) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  if (!indexeddb_factory_.get()) {
-    // Prime our cache of origins with existing databases so we can
-    // detect when dbs are newly created.
-    GetOriginSet();
-    indexeddb_factory_ = std::make_unique<IndexedDBFactoryImpl>(
-        this, IndexedDBClassFactory::Get(), clock_);
+  base::UmaHistogramEnumeration("WebCore.IndexedDB.Context.ForceCloseReason",
+                                reason);
+  if (!HasOrigin(origin)) {
+    std::move(closure).Run();
+    return;
   }
-  return indexeddb_factory_.get();
+
+  if (!indexeddb_factory_.get()) {
+    std::move(closure).Run();
+    return;
+  }
+
+  // Make a copy of origin, as the ref might go away here during the close.
+  auto origin_copy = origin;
+  indexeddb_factory_->ForceClose(
+      origin_copy,
+      reason == storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
+  DCHECK_EQ(0UL, GetConnectionCountSync(origin_copy));
+  std::move(closure).Run();
 }
 
-base::SequencedTaskRunner* IndexedDBContextImpl::IOTaskRunner() {
-  DCHECK(io_task_runner_.get());
-  return io_task_runner_.get();
+void IndexedDBContextImpl::GetConnectionCount(
+    const Origin& origin,
+    GetConnectionCountCallback callback) {
+  std::move(callback).Run(GetConnectionCountSync(origin));
 }
 
-std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() {
+void IndexedDBContextImpl::DownloadOriginData(
+    const url::Origin& origin,
+    DownloadOriginDataCallback callback) {
+  // All of this must run on the IndexedDB task runner to prevent script from
+  // reopening the origin while we are zipping.
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  std::set<Origin>* origins_set = GetOriginSet();
-  return std::vector<Origin>(origins_set->begin(), origins_set->end());
+
+  bool success = false;
+
+  // Make sure the database hasn't been deleted.
+  if (!HasOrigin(origin)) {
+    std::move(callback).Run(success, base::FilePath(), base::FilePath());
+    return;
+  }
+
+  ForceCloseSync(origin,
+                 storage::mojom::ForceCloseReason::FORCE_CLOSE_INTERNALS_PAGE);
+
+  base::ScopedTempDir temp_dir;
+  if (!temp_dir.CreateUniqueTempDir()) {
+    std::move(callback).Run(success, base::FilePath(), base::FilePath());
+    return;
+  }
+
+  // This will need to get cleaned up after the download has completed.
+  base::FilePath temp_path = temp_dir.Take();
+
+  std::string origin_id = storage::GetIdentifierFromOrigin(origin);
+  base::FilePath zip_path =
+      temp_path.AppendASCII(origin_id).AddExtension(FILE_PATH_LITERAL("zip"));
+
+  std::vector<base::FilePath> paths = GetStoragePaths(origin);
+  zip::ZipWithFilterCallback(data_path(), zip_path,
+                             base::BindRepeating(IsAllowedPath, paths));
+
+  success = true;
+  std::move(callback).Run(success, temp_path, zip_path);
 }
 
-bool IndexedDBContextImpl::HasOrigin(const Origin& origin) {
-  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  std::set<Origin>* set = GetOriginSet();
-  return set->find(origin) != set->end();
-}
-
-static bool HostNameComparator(const Origin& i, const Origin& j) {
-  return i.host() < j.host();
-}
-
-base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
+void IndexedDBContextImpl::GetAllOriginsDetails(
+    GetAllOriginsDetailsCallback callback) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   std::vector<Origin> origins = GetAllOrigins();
 
-  std::sort(origins.begin(), origins.end(), HostNameComparator);
+  std::sort(origins.begin(), origins.end());
 
-  std::unique_ptr<base::ListValue> list(std::make_unique<base::ListValue>());
+  base::ListValue list;
   for (const auto& origin : origins) {
     std::unique_ptr<base::DictionaryValue> info(
         std::make_unique<base::DictionaryValue>());
@@ -218,14 +268,14 @@
       paths->AppendString("N/A");
     }
     info->Set("paths", std::move(paths));
-    info->SetDouble("connection_count", GetConnectionCount(origin));
+    info->SetDouble("connection_count", GetConnectionCountSync(origin));
 
     // This ends up being O(NlogN), where N = number of open databases. We
     // iterate over all open databases to extract just those in the origin, and
     // we're iterating over all origins in the outer loop.
 
     if (!indexeddb_factory_.get()) {
-      list->Append(std::move(info));
+      list.Append(std::move(info));
       continue;
     }
     std::vector<IndexedDBDatabase*> databases =
@@ -315,9 +365,61 @@
       database_list->Append(std::move(db_info));
     }
     info->Set("databases", std::move(database_list));
-    list->Append(std::move(info));
+    list.Append(std::move(info));
   }
-  return list.release();
+
+  std::move(callback).Run(is_incognito(), std::move(list));
+}
+
+void IndexedDBContextImpl::ForceCloseSync(
+    const Origin& origin,
+    storage::mojom::ForceCloseReason reason) {
+  ForceClose(origin, reason, base::DoNothing());
+}
+
+bool IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+
+  if (is_incognito() || !HasOrigin(origin))
+    return false;
+
+  if (indexeddb_factory_.get()) {
+    indexeddb_factory_->ForceSchemaDowngrade(origin);
+    return true;
+  }
+  ForceCloseSync(
+      origin,
+      storage::mojom::ForceCloseReason::FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
+  return false;
+}
+
+IndexedDBFactoryImpl* IndexedDBContextImpl::GetIDBFactory() {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  if (!indexeddb_factory_.get()) {
+    // Prime our cache of origins with existing databases so we can
+    // detect when dbs are newly created.
+    GetOriginSet();
+    indexeddb_factory_ = std::make_unique<IndexedDBFactoryImpl>(
+        this, IndexedDBClassFactory::Get(), clock_);
+  }
+  return indexeddb_factory_.get();
+}
+
+base::SequencedTaskRunner* IndexedDBContextImpl::IOTaskRunner() {
+  DCHECK(io_task_runner_.get());
+  return io_task_runner_.get();
+}
+
+std::vector<Origin> IndexedDBContextImpl::GetAllOrigins() {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  std::set<Origin>* origins_set = GetOriginSet();
+  return std::vector<Origin>(origins_set->begin(), origins_set->end());
+}
+
+bool IndexedDBContextImpl::HasOrigin(const Origin& origin) {
+  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
+  std::set<Origin>* set = GetOriginSet();
+  return set->find(origin) != set->end();
 }
 
 int IndexedDBContextImpl::GetOriginBlobFileCount(const Origin& origin) {
@@ -368,7 +470,8 @@
   IndexedDBContextImpl* dest_context_impl =
       static_cast<IndexedDBContextImpl*>(dest_context);
 
-  ForceClose(origin, FORCE_CLOSE_COPY_ORIGIN);
+  ForceCloseSync(origin,
+                 storage::mojom::ForceCloseReason::FORCE_CLOSE_COPY_ORIGIN);
 
   // Make sure we're not about to delete our own database.
   CHECK_NE(dest_context_impl->data_path().value(), data_path().value());
@@ -389,33 +492,6 @@
   }
 }
 
-void IndexedDBContextImpl::ForceClose(const Origin origin,
-                                      ForceCloseReason reason) {
-  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-  base::UmaHistogramEnumeration("WebCore.IndexedDB.Context.ForceCloseReason",
-                                reason, FORCE_CLOSE_REASON_MAX);
-  if (!HasOrigin(origin))
-    return;
-
-  if (indexeddb_factory_.get())
-    indexeddb_factory_->ForceClose(origin, reason == FORCE_CLOSE_DELETE_ORIGIN);
-  DCHECK_EQ(0UL, GetConnectionCount(origin));
-}
-
-bool IndexedDBContextImpl::ForceSchemaDowngrade(const Origin& origin) {
-  DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
-
-  if (is_incognito() || !HasOrigin(origin))
-    return false;
-
-  if (indexeddb_factory_.get()) {
-    indexeddb_factory_->ForceSchemaDowngrade(origin);
-    return true;
-  }
-  this->ForceClose(origin, FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE);
-  return false;
-}
-
 V2SchemaCorruptionStatus IndexedDBContextImpl::HasV2SchemaCorruption(
     const Origin& origin) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
@@ -428,7 +504,7 @@
   return V2SchemaCorruptionStatus::kUnknown;
 }
 
-size_t IndexedDBContextImpl::GetConnectionCount(const Origin& origin) {
+size_t IndexedDBContextImpl::GetConnectionCountSync(const Origin& origin) {
   DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
   if (!HasOrigin(origin))
     return 0;
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
index 2b7ab22..7935fda4 100644
--- a/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -46,18 +46,6 @@
     : public IndexedDBContext,
       public storage::mojom::IndexedDBControl {
  public:
-  // Recorded in histograms, so append only.
-  enum ForceCloseReason {
-    FORCE_CLOSE_DELETE_ORIGIN = 0,
-    FORCE_CLOSE_BACKING_STORE_FAILURE,
-    FORCE_CLOSE_INTERNALS_PAGE,
-    FORCE_CLOSE_COPY_ORIGIN,
-    FORCE_SCHEMA_DOWNGRADE_INTERNALS_PAGE,
-    // Append new values here and update IDBContextForcedCloseReason in
-    // enums.xml.
-    FORCE_CLOSE_REASON_MAX
-  };
-
   class Observer {
    public:
     virtual void OnIndexedDBListChanged(const url::Origin& origin) = 0;
@@ -89,6 +77,18 @@
   void GetUsage(GetUsageCallback usage_callback) override;
   void DeleteForOrigin(const url::Origin& origin,
                        DeleteForOriginCallback callback) override;
+  void ForceClose(const url::Origin& origin,
+                  storage::mojom::ForceCloseReason reason,
+                  base::OnceClosure callback) override;
+  void GetConnectionCount(const url::Origin& origin,
+                          GetConnectionCountCallback callback) override;
+  void DownloadOriginData(const url::Origin& origin,
+                          DownloadOriginDataCallback callback) override;
+  void GetAllOriginsDetails(GetAllOriginsDetailsCallback callback) override;
+
+  // TODO(enne): fix internal indexeddb callers to use ForceClose async instead.
+  void ForceCloseSync(const url::Origin& origin,
+                      storage::mojom::ForceCloseReason reason);
 
   IndexedDBFactoryImpl* GetIDBFactory();
 
@@ -130,11 +130,6 @@
   // Used by IndexedDBInternalsUI to populate internals page.
   base::ListValue* GetAllOriginsDetails();
 
-  // ForceClose takes a value rather than a reference since it may release the
-  // owning object.
-  // ForceClose needs to move to async to support multi-thread scopes. See
-  // https://crbug.com/965142.
-  void ForceClose(const url::Origin origin, ForceCloseReason reason);
   bool ForceSchemaDowngrade(const url::Origin& origin);
   V2SchemaCorruptionStatus HasV2SchemaCorruption(const url::Origin& origin);
   // GetStoragePaths returns all paths owned by this database, in arbitrary
@@ -143,7 +138,7 @@
 
   base::FilePath data_path() const { return data_path_; }
   bool IsInMemoryContext() const { return data_path_.empty(); }
-  size_t GetConnectionCount(const url::Origin& origin);
+  size_t GetConnectionCountSync(const url::Origin& origin);
   int GetOriginBlobFileCount(const url::Origin& origin);
 
   // For unit tests allow to override the |data_path_|.
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index 9200be9b..9efc0042 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -38,6 +38,7 @@
 #include "components/services/storage/indexed_db/scopes/leveldb_scopes_factory.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h"
 #include "components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_factory.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_connection.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -450,8 +451,9 @@
   // NULL after ContextDestroyed() called, and in some unit tests.
   if (!context_)
     return;
-  context_->ForceClose(origin,
-                       IndexedDBContextImpl::FORCE_CLOSE_BACKING_STORE_FAILURE);
+  context_->ForceCloseSync(
+      origin,
+      storage::mojom::ForceCloseReason::FORCE_CLOSE_BACKING_STORE_FAILURE);
 }
 
 void IndexedDBFactoryImpl::HandleBackingStoreCorruption(
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index d32ab308..3ca9030 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -108,8 +108,9 @@
             ->leveldb_state()
             ->RequestDestruction(callback,
                                  base::SequencedTaskRunnerHandle::Get());
-        context_->ForceClose(origin,
-                             IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN);
+        context_->ForceCloseSync(
+            origin,
+            storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
       }
       loop.Run();
     }
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc
index 28a2329f..30380c6 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/task/post_task.h"
 #include "base/threading/platform_thread.h"
@@ -29,7 +28,6 @@
 #include "content/public/common/url_constants.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "storage/common/database/database_identifier.h"
-#include "third_party/zlib/google/zip.h"
 #include "ui/base/text/bytes_formatting.h"
 #include "url/origin.h"
 
@@ -37,19 +35,6 @@
 
 namespace content {
 
-namespace {
-
-bool AllowWhitelistedPaths(const std::vector<base::FilePath>& allowed_paths,
-                           const base::FilePath& candidate_path) {
-  for (const base::FilePath& allowed_path : allowed_paths) {
-    if (candidate_path == allowed_path || allowed_path.IsParent(candidate_path))
-      return true;
-  }
-  return false;
-}
-
-}  // namespace
-
 IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
     : WebUIController(web_ui) {
   web_ui->RegisterMessageCallback(
@@ -81,15 +66,6 @@
 
 IndexedDBInternalsUI::~IndexedDBInternalsUI() {}
 
-void IndexedDBInternalsUI::AddContextFromStoragePartition(
-    StoragePartition* partition) {
-  scoped_refptr<IndexedDBContext> context = partition->GetIndexedDBContext();
-  context->IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread,
-                     base::Unretained(this), context, partition->GetPath()));
-}
-
 void IndexedDBInternalsUI::GetAllOrigins(const base::ListValue* args) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -98,45 +74,41 @@
 
   BrowserContext::ForEachStoragePartition(
       browser_context,
-      base::BindRepeating(&IndexedDBInternalsUI::AddContextFromStoragePartition,
-                          base::Unretained(this)));
+      base::BindRepeating(
+          [](base::WeakPtr<IndexedDBInternalsUI> ui,
+             StoragePartition* partition) {
+            if (!ui)
+              return;
+            auto& control = partition->GetIndexedDBControl();
+            control.GetAllOriginsDetails(base::BindOnce(
+                [](base::WeakPtr<IndexedDBInternalsUI> ui,
+                   base::FilePath partition_path, bool incognito,
+                   base::Value info_list) {
+                  if (!ui)
+                    return;
+
+                  ui->OnOriginsReady(
+                      info_list, incognito ? base::FilePath() : partition_path);
+                },
+                ui, partition->GetPath()));
+          },
+          weak_factory_.GetWeakPtr()));
 }
 
-void IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread(
-    scoped_refptr<IndexedDBContext> context,
-    const base::FilePath& context_path) {
-  DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
-
-  IndexedDBContextImpl* context_impl =
-      static_cast<IndexedDBContextImpl*>(context.get());
-
-  std::unique_ptr<base::ListValue> info_list(
-      context_impl->GetAllOriginsDetails());
-  bool is_incognito = context_impl->is_incognito();
-
-  base::PostTask(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&IndexedDBInternalsUI::OnOriginsReady,
-                     base::Unretained(this), std::move(info_list),
-                     is_incognito ? base::FilePath() : context_path));
-}
-
-void IndexedDBInternalsUI::OnOriginsReady(
-    std::unique_ptr<base::ListValue> origins,
-    const base::FilePath& path) {
+void IndexedDBInternalsUI::OnOriginsReady(const base::Value& origins,
+                                          const base::FilePath& path) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  web_ui()->CallJavascriptFunctionUnsafe("indexeddb.onOriginsReady", *origins,
+  web_ui()->CallJavascriptFunctionUnsafe("indexeddb.onOriginsReady", origins,
                                          base::Value(path.value()));
 }
 
-static void FindContext(const base::FilePath& partition_path,
+static void FindControl(const base::FilePath& partition_path,
                         StoragePartition** result_partition,
-                        scoped_refptr<IndexedDBContextImpl>* result_context,
+                        storage::mojom::IndexedDBControl** result_control,
                         StoragePartition* storage_partition) {
   if (storage_partition->GetPath() == partition_path) {
     *result_partition = storage_partition;
-    *result_context = static_cast<IndexedDBContextImpl*>(
-        storage_partition->GetIndexedDBContext());
+    *result_control = &storage_partition->GetIndexedDBControl();
   }
 }
 
@@ -144,7 +116,7 @@
     const base::ListValue* args,
     base::FilePath* partition_path,
     Origin* origin,
-    scoped_refptr<IndexedDBContextImpl>* context) {
+    storage::mojom::IndexedDBControl** control) {
   base::FilePath::StringType path_string;
   if (!args->GetString(0, &path_string))
     return false;
@@ -156,23 +128,24 @@
 
   *origin = Origin::Create(GURL(url_string));
 
-  return GetOriginContext(*partition_path, *origin, context);
+  return GetOriginControl(*partition_path, *origin, control);
 }
 
-bool IndexedDBInternalsUI::GetOriginContext(
+bool IndexedDBInternalsUI::GetOriginControl(
     const base::FilePath& path,
     const Origin& origin,
-    scoped_refptr<IndexedDBContextImpl>* context) {
+    storage::mojom::IndexedDBControl** control) {
   // search the origins to find the right context
   BrowserContext* browser_context =
       web_ui()->GetWebContents()->GetBrowserContext();
 
-  StoragePartition* result_partition;
+  StoragePartition* result_partition = nullptr;
+  *control = nullptr;
   BrowserContext::ForEachStoragePartition(
       browser_context,
-      base::BindRepeating(&FindContext, path, &result_partition, context));
+      base::BindRepeating(&FindControl, path, &result_partition, control));
 
-  if (!result_partition || !(context->get()))
+  if (!result_partition || !control)
     return false;
 
   return true;
@@ -183,15 +156,38 @@
 
   base::FilePath partition_path;
   Origin origin;
-  scoped_refptr<IndexedDBContextImpl> context;
-  if (!GetOriginData(args, &partition_path, &origin, &context))
+  storage::mojom::IndexedDBControl* control;
+  if (!GetOriginData(args, &partition_path, &origin, &control))
     return;
 
-  DCHECK(context.get());
-  context->IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread,
-                     base::Unretained(this), partition_path, context, origin));
+  DCHECK(control);
+  control->ForceClose(
+      origin, storage::mojom::ForceCloseReason::FORCE_CLOSE_INTERNALS_PAGE,
+      base::BindOnce(
+          [](base::WeakPtr<IndexedDBInternalsUI> ui, Origin origin,
+             base::FilePath partition_path,
+             storage::mojom::IndexedDBControl* control) {
+            // Is the connection count always zero after closing,
+            // such that this can be simplified?
+            control->GetConnectionCount(
+                origin,
+                base::BindOnce(
+                    [](base::WeakPtr<IndexedDBInternalsUI> ui, Origin origin,
+                       base::FilePath partition_path,
+                       storage::mojom::IndexedDBControl* control,
+                       uint64_t connection_count) {
+                      if (!ui)
+                        return;
+
+                      control->DownloadOriginData(
+                          origin,
+                          base::BindOnce(
+                              &IndexedDBInternalsUI::OnDownloadDataReady, ui,
+                              partition_path, origin, connection_count));
+                    },
+                    ui, origin, partition_path, control));
+          },
+          weak_factory_.GetWeakPtr(), origin, partition_path, control));
 }
 
 void IndexedDBInternalsUI::ForceCloseOrigin(const base::ListValue* args) {
@@ -199,74 +195,28 @@
 
   base::FilePath partition_path;
   Origin origin;
-  scoped_refptr<IndexedDBContextImpl> context;
-  if (!GetOriginData(args, &partition_path, &origin, &context))
+  storage::mojom::IndexedDBControl* control;
+  if (!GetOriginData(args, &partition_path, &origin, &control))
     return;
 
-  context->IDBTaskRunner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread,
-                     base::Unretained(this), partition_path, context, origin));
-}
-
-void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
-    const base::FilePath& partition_path,
-    const scoped_refptr<IndexedDBContextImpl> context,
-    const Origin& origin) {
-  DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
-  // This runs on the IndexedDB task runner to prevent script from reopening
-  // the origin while we are zipping.
-
-  // Make sure the database hasn't been deleted since the page was loaded.
-  if (!context->HasOrigin(origin))
-    return;
-
-  context->ForceClose(origin, IndexedDBContextImpl::FORCE_CLOSE_INTERNALS_PAGE);
-  size_t connection_count = context->GetConnectionCount(origin);
-
-  base::ScopedTempDir temp_dir;
-  if (!temp_dir.CreateUniqueTempDir())
-    return;
-
-  // This will get cleaned up after the download has completed.
-  base::FilePath temp_path = temp_dir.Take();
-
-  std::string origin_id = storage::GetIdentifierFromOrigin(origin);
-  base::FilePath zip_path =
-      temp_path.AppendASCII(origin_id).AddExtension(FILE_PATH_LITERAL("zip"));
-
-  std::vector<base::FilePath> paths = context->GetStoragePaths(origin);
-  zip::ZipWithFilterCallback(context->data_path(), zip_path,
-                             base::BindRepeating(AllowWhitelistedPaths, paths));
-
-  base::PostTask(FROM_HERE, {BrowserThread::UI},
-                 base::BindOnce(&IndexedDBInternalsUI::OnDownloadDataReady,
-                                base::Unretained(this), partition_path, origin,
-                                temp_path, zip_path, connection_count));
-}
-
-void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
-    const base::FilePath& partition_path,
-    const scoped_refptr<IndexedDBContextImpl> context,
-    const Origin& origin) {
-  DCHECK(context->IDBTaskRunner()->RunsTasksInCurrentSequence());
-
-  // Make sure the database hasn't been deleted since the page was loaded.
-  if (!context->HasOrigin(origin))
-    return;
-
-  context->ForceClose(origin, IndexedDBContextImpl::FORCE_CLOSE_INTERNALS_PAGE);
-  size_t connection_count = context->GetConnectionCount(origin);
-
-  base::PostTask(FROM_HERE, {BrowserThread::UI},
-                 base::BindOnce(&IndexedDBInternalsUI::OnForcedClose,
-                                base::Unretained(this), partition_path, origin,
-                                connection_count));
+  control->ForceClose(
+      origin, storage::mojom::ForceCloseReason::FORCE_CLOSE_INTERNALS_PAGE,
+      base::BindOnce(
+          [](base::WeakPtr<IndexedDBInternalsUI> ui,
+             base::FilePath partition_path, Origin origin,
+             storage::mojom::IndexedDBControl* control) {
+            if (!ui)
+              return;
+            control->GetConnectionCount(
+                origin, base::BindOnce(&IndexedDBInternalsUI::OnForcedClose, ui,
+                                       partition_path, origin));
+          },
+          weak_factory_.GetWeakPtr(), partition_path, origin, control));
 }
 
 void IndexedDBInternalsUI::OnForcedClose(const base::FilePath& partition_path,
                                          const Origin& origin,
-                                         size_t connection_count) {
+                                         uint64_t connection_count) {
   web_ui()->CallJavascriptFunctionUnsafe(
       "indexeddb.onForcedClose", base::Value(partition_path.value()),
       base::Value(origin.Serialize()),
@@ -276,10 +226,14 @@
 void IndexedDBInternalsUI::OnDownloadDataReady(
     const base::FilePath& partition_path,
     const Origin& origin,
-    const base::FilePath temp_path,
-    const base::FilePath zip_path,
-    size_t connection_count) {
+    uint64_t connection_count,
+    bool success,
+    const base::FilePath& temp_path,
+    const base::FilePath& zip_path) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (!success)
+    return;
+
   const GURL url = GURL(FILE_PATH_LITERAL("file://") + zip_path.value());
   WebContents* web_contents = web_ui()->GetWebContents();
   net::NetworkTrafficAnnotationTag traffic_annotation =
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.h b/content/browser/indexed_db/indexed_db_internals_ui.h
index 7e2e870..618427d 100644
--- a/content/browser/indexed_db/indexed_db_internals_ui.h
+++ b/content/browser/indexed_db/indexed_db_internals_ui.h
@@ -13,6 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
+#include "components/services/storage/public/mojom/indexed_db_control.mojom.h"
 #include "content/public/browser/indexed_db_context.h"
 #include "content/public/browser/web_ui_controller.h"
 
@@ -30,9 +31,6 @@
 
 namespace content {
 
-class IndexedDBContextImpl;
-class StoragePartition;
-
 // The implementation for the chrome://indexeddb-internals page.
 class IndexedDBInternalsUI : public WebUIController {
  public:
@@ -41,23 +39,15 @@
 
  private:
   void GetAllOrigins(const base::ListValue* args);
-  void GetAllOriginsOnIndexedDBThread(scoped_refptr<IndexedDBContext> context,
-                                      const base::FilePath& context_path);
-  void OnOriginsReady(std::unique_ptr<base::ListValue> origins,
-                      const base::FilePath& path);
-
-  void AddContextFromStoragePartition(StoragePartition* partition);
+  void OnOriginsReady(const base::Value& origins, const base::FilePath& path);
 
   void DownloadOriginData(const base::ListValue* args);
-  void DownloadOriginDataOnIndexedDBThread(
-      const base::FilePath& partition_path,
-      const scoped_refptr<IndexedDBContextImpl> context,
-      const url::Origin& origin);
   void OnDownloadDataReady(const base::FilePath& partition_path,
                            const url::Origin& origin,
-                           const base::FilePath temp_path,
-                           const base::FilePath zip_path,
-                           size_t connection_count);
+                           uint64_t connection_count,
+                           bool success,
+                           const base::FilePath& temp_path,
+                           const base::FilePath& zip_path);
   void OnDownloadStarted(const base::FilePath& partition_path,
                          const url::Origin& origin,
                          const base::FilePath& temp_path,
@@ -66,22 +56,19 @@
                          download::DownloadInterruptReason interrupt_reason);
 
   void ForceCloseOrigin(const base::ListValue* args);
-  void ForceCloseOriginOnIndexedDBThread(
-      const base::FilePath& partition_path,
-      const scoped_refptr<IndexedDBContextImpl> context,
-      const url::Origin& origin);
   void OnForcedClose(const base::FilePath& partition_path,
                      const url::Origin& origin,
-                     size_t connection_count);
+                     uint64_t connection_count);
 
-  bool GetOriginContext(const base::FilePath& path,
+  bool GetOriginControl(const base::FilePath& path,
                         const url::Origin& origin,
-                        scoped_refptr<IndexedDBContextImpl>* context);
+                        storage::mojom::IndexedDBControl** control);
   bool GetOriginData(const base::ListValue* args,
                      base::FilePath* path,
                      url::Origin* origin,
-                     scoped_refptr<IndexedDBContextImpl>* context);
+                     storage::mojom::IndexedDBControl** control);
 
+  base::WeakPtrFactory<IndexedDBInternalsUI> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(IndexedDBInternalsUI);
 };
 
diff --git a/content/browser/indexed_db/indexed_db_unittest.cc b/content/browser/indexed_db/indexed_db_unittest.cc
index 2c7d9dc..83080a1b 100644
--- a/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_unittest.cc
@@ -142,8 +142,9 @@
             ->leveldb_state()
             ->RequestDestruction(callback,
                                  base::SequencedTaskRunnerHandle::Get());
-        context_->ForceClose(origin,
-                             IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN);
+        context_->ForceCloseSync(
+            origin,
+            storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
       }
       loop.Run();
     }
@@ -285,8 +286,8 @@
       IndexedDBConnection::CloseErrorHandling::kAbortAllReturnLastError);
   RunPostedTasks();
 
-  context()->ForceClose(kTestOrigin,
-                        IndexedDBContextImpl::FORCE_CLOSE_DELETE_ORIGIN);
+  context()->ForceCloseSync(
+      kTestOrigin, storage::mojom::ForceCloseReason::FORCE_CLOSE_DELETE_ORIGIN);
   EXPECT_TRUE(open_db_callbacks->forced_close_called());
   EXPECT_FALSE(closed_db_callbacks->forced_close_called());
 
diff --git a/content/public/app/BUILD.gn b/content/public/app/BUILD.gn
index 9d953c6..93ca751 100644
--- a/content/public/app/BUILD.gn
+++ b/content/public/app/BUILD.gn
@@ -71,19 +71,13 @@
 
   # These all just forward to content, which in turn depends on "both_sources".
   group("browser") {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   }
   group("child") {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   }
   group("both") {
-    public_deps = [
-      "//content",
-    ]
+    public_deps = [ "//content" ]
   }
 } else {
   # content_main_delegate.cc conditionally includes content_browser_client.h
@@ -163,14 +157,10 @@
     # When the multi-DLL build is disabled, there is only one type of the
     # "app" target, and "browser" and "child" are the same as "both".
     group("browser") {
-      deps = [
-        ":both",
-      ]
+      deps = [ ":both" ]
     }
     group("child") {
-      deps = [
-        ":both",
-      ]
+      deps = [ ":both" ]
     }
   }
 }
@@ -186,13 +176,9 @@
     "//content/public/common:service_names",
   ]
 
-  public_deps = [
-    "//services/service_manager/public/cpp",
-  ]
+  public_deps = [ "//services/service_manager/public/cpp" ]
 }
 
 group("service_manifests") {
-  public_deps = [
-    ":content_browser_manifest",
-  ]
+  public_deps = [ ":content_browser_manifest" ]
 }
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index a19ec85..338a09a 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -677,16 +677,12 @@
   ]
 
   if (!is_component_build) {
-    public_deps = [
-      ":renderer",
-    ]
+    public_deps = [ ":renderer" ]
   }
 }
 
 fuzzer_test("audio_decoder_fuzzer") {
-  sources = [
-    "media/audio_decoder_fuzzer.cpp",
-  ]
+  sources = [ "media/audio_decoder_fuzzer.cpp" ]
   deps = [
     "//content/public/renderer:renderer_sources",
     "//content/renderer:renderer",
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index bfcb6a9c..2e57e21c 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -285,6 +285,8 @@
 crbug.com/974347 [ win amd vulkan passthrough ] conformance/textures/image/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
 crbug.com/1004581 [ win amd vulkan passthrough ] conformance/rendering/multisample-corruption.html [ Failure ]
 crbug.com/1010942 [ win amd vulkan passthrough ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ]
+crbug.com/angleproject/4286 [ win amd vulkan passthrough ] conformance/rendering/out-of-bounds-array-buffers.html [ Failure ]
+
 
 ####################
 # Mac failures     #
diff --git a/courgette/BUILD.gn b/courgette/BUILD.gn
index fec22382..4c64aab 100644
--- a/courgette/BUILD.gn
+++ b/courgette/BUILD.gn
@@ -84,12 +84,8 @@
 }
 
 source_set("paged_array") {
-  sources = [
-    "third_party/bsdiff/paged_array.h",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "third_party/bsdiff/paged_array.h" ]
+  deps = [ "//base" ]
 }
 
 source_set("bsdiff") {
@@ -132,9 +128,7 @@
       output_name = "courgette64"
     }
 
-    sources = [
-      "courgette_tool.cc",
-    ]
+    sources = [ "courgette_tool.cc" ]
 
     if (is_win) {
       ldflags = [ "/LARGEADDRESSAWARE" ]
@@ -148,9 +142,7 @@
   }
 
   executable("courgette_minimal_tool") {
-    sources = [
-      "courgette_minimal_tool.cc",
-    ]
+    sources = [ "courgette_minimal_tool.cc" ]
 
     deps = [
       ":courgette_lib",
@@ -165,15 +157,9 @@
       # in the official build archives, remove this once they have been updated.
       # https://crbug.com/629243
       copy("copy_courgette_binaries") {
-        sources = [
-          "$root_out_dir/courgette64.exe",
-        ]
-        outputs = [
-          "$root_out_dir/courgette.exe",
-        ]
-        deps = [
-          ":courgette",
-        ]
+        sources = [ "$root_out_dir/courgette64.exe" ]
+        outputs = [ "$root_out_dir/courgette.exe" ]
+        deps = [ ":courgette" ]
       }
     } else {
       # Make sure that we have a copy of courgette64.exe(.pdb) in the root out
@@ -190,28 +176,16 @@
       if (symbol_level > 0) {
         copy("copy_courgette_pdb") {
           visibility = [ ":copy_courgette_binaries" ]
-          sources = [
-            "$courgette64_out_dir/courgette64.exe.pdb",
-          ]
-          outputs = [
-            "$root_out_dir/{{source_file_part}}",
-          ]
-          deps = [
-            courgette64_label,
-          ]
+          sources = [ "$courgette64_out_dir/courgette64.exe.pdb" ]
+          outputs = [ "$root_out_dir/{{source_file_part}}" ]
+          deps = [ courgette64_label ]
         }
       }
 
       copy("copy_courgette_binaries") {
-        sources = [
-          "$courgette64_out_dir/courgette64.exe",
-        ]
-        outputs = [
-          "$root_out_dir/{{source_file_part}}",
-        ]
-        deps = [
-          courgette64_label,
-        ]
+        sources = [ "$courgette64_out_dir/courgette64.exe" ]
+        outputs = [ "$root_out_dir/{{source_file_part}}" ]
+        deps = [ courgette64_label ]
         if (symbol_level > 0) {
           deps += [ ":copy_courgette_pdb" ]
         }
@@ -259,9 +233,7 @@
     "//testing/gtest",
   ]
 
-  data = [
-    "testdata/",
-  ]
+  data = [ "testdata/" ]
 }
 
 test("courgette_fuzz") {
diff --git a/device/bluetooth/public/cpp/BUILD.gn b/device/bluetooth/public/cpp/BUILD.gn
index 03775b0..ded001e 100644
--- a/device/bluetooth/public/cpp/BUILD.gn
+++ b/device/bluetooth/public/cpp/BUILD.gn
@@ -8,7 +8,5 @@
     "bluetooth_uuid.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/device/bluetooth/public/mojom/BUILD.gn b/device/bluetooth/public/mojom/BUILD.gn
index 7a8bd86..a0f99c8 100644
--- a/device/bluetooth/public/mojom/BUILD.gn
+++ b/device/bluetooth/public/mojom/BUILD.gn
@@ -5,19 +5,13 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("mojom") {
-  sources = [
-    "uuid.mojom",
-  ]
+  sources = [ "uuid.mojom" ]
 }
 
 mojom("fake_bluetooth_interfaces") {
-  sources = [
-    "test/fake_bluetooth.mojom",
-  ]
+  sources = [ "test/fake_bluetooth.mojom" ]
 
-  public_deps = [
-    ":mojom",
-  ]
+  public_deps = [ ":mojom" ]
 }
 
 # Experimental interfaces are not ready for production use yet. See README.md
@@ -27,9 +21,7 @@
     "device.mojom",
   ]
 
-  public_deps = [
-    ":mojom",
-  ]
+  public_deps = [ ":mojom" ]
 
   visibility = [
     # Experimental interfaces are not ready for production use yet. See
diff --git a/device/bluetooth/uribeacon/BUILD.gn b/device/bluetooth/uribeacon/BUILD.gn
index 484e2727..2a4d31d 100644
--- a/device/bluetooth/uribeacon/BUILD.gn
+++ b/device/bluetooth/uribeacon/BUILD.gn
@@ -7,7 +7,5 @@
     "uri_encoder.cc",
     "uri_encoder.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn
index b2f833ed..405dbab9 100644
--- a/device/gamepad/BUILD.gn
+++ b/device/gamepad/BUILD.gn
@@ -102,9 +102,7 @@
     "//third_party/blink/public:blink_headers",
   ]
 
-  public_deps = [
-    "//services/device/public/mojom",
-  ]
+  public_deps = [ "//services/device/public/mojom" ]
 
   defines = [ "DEVICE_GAMEPAD_IMPLEMENTATION" ]
 
@@ -171,9 +169,8 @@
 
 if (is_android) {
   generate_jni("jni_headers") {
-    sources = [
-      "android/java/src/org/chromium/device/gamepad/GamepadList.java",
-    ]
+    sources =
+        [ "android/java/src/org/chromium/device/gamepad/GamepadList.java" ]
   }
 
   android_library("java") {
@@ -192,8 +189,6 @@
   }
 
   java_cpp_enum("java_enums_srcjar") {
-    sources = [
-      "gamepad_standard_mappings.h",
-    ]
+    sources = [ "gamepad_standard_mappings.h" ]
   }
 }
diff --git a/device/gamepad/public/cpp/BUILD.gn b/device/gamepad/public/cpp/BUILD.gn
index b380d1a..aff9913 100644
--- a/device/gamepad/public/cpp/BUILD.gn
+++ b/device/gamepad/public/cpp/BUILD.gn
@@ -23,9 +23,7 @@
 
   # Do not add deps here per the above comment.
   defines = [ "IS_GAMEPAD_PUBLIC_IMPL" ]
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
 
 # Normally typemap traits sources should be build directly into mojom targets
@@ -56,7 +54,5 @@
     "gamepad_switches.h",
   ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 }
diff --git a/device/gamepad/public/mojom/BUILD.gn b/device/gamepad/public/mojom/BUILD.gn
index 1bd367a..5671c9d 100644
--- a/device/gamepad/public/mojom/BUILD.gn
+++ b/device/gamepad/public/mojom/BUILD.gn
@@ -5,13 +5,9 @@
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom_component("mojom") {
-  sources = [
-    "gamepad.mojom",
-  ]
+  sources = [ "gamepad.mojom" ]
 
-  deps = [
-    "//mojo/public/mojom/base",
-  ]
+  deps = [ "//mojo/public/mojom/base" ]
 
   output_prefix = "gamepad_mojom"
   macro_prefix = "GAMEPAD_MOJOM"
diff --git a/extensions/browser/api/cast_channel/BUILD.gn b/extensions/browser/api/cast_channel/BUILD.gn
index b1b1f2e..1227f29 100644
--- a/extensions/browser/api/cast_channel/BUILD.gn
+++ b/extensions/browser/api/cast_channel/BUILD.gn
@@ -25,7 +25,5 @@
     "//third_party/openscreen/src/cast/common/channel/proto:channel_proto",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/messaging/BUILD.gn b/extensions/browser/api/messaging/BUILD.gn
index d67b942..0252290c 100644
--- a/extensions/browser/api/messaging/BUILD.gn
+++ b/extensions/browser/api/messaging/BUILD.gn
@@ -32,7 +32,5 @@
     "//extensions/common/api",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/printer_provider_internal/BUILD.gn b/extensions/browser/api/printer_provider_internal/BUILD.gn
index a054f06..9b60358 100644
--- a/extensions/browser/api/printer_provider_internal/BUILD.gn
+++ b/extensions/browser/api/printer_provider_internal/BUILD.gn
@@ -24,7 +24,5 @@
     "//extensions/common/api",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/browser/api/web_request/BUILD.gn b/extensions/browser/api/web_request/BUILD.gn
index ce65fc5..117c87d 100644
--- a/extensions/browser/api/web_request/BUILD.gn
+++ b/extensions/browser/api/web_request/BUILD.gn
@@ -52,7 +52,5 @@
     "//third_party/re2",
   ]
 
-  public_deps = [
-    "//extensions/browser:browser_sources",
-  ]
+  public_deps = [ "//extensions/browser:browser_sources" ]
 }
diff --git a/extensions/components/native_app_window/native_app_window_views.cc b/extensions/components/native_app_window/native_app_window_views.cc
index bb91add..59ab516 100644
--- a/extensions/components/native_app_window/native_app_window_views.cc
+++ b/extensions/components/native_app_window/native_app_window_views.cc
@@ -212,14 +212,6 @@
   app_window_->OnNativeClose();
 }
 
-views::Widget* NativeAppWindowViews::GetWidget() {
-  return widget_;
-}
-
-const views::Widget* NativeAppWindowViews::GetWidget() const {
-  return widget_;
-}
-
 bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling(
     gfx::NativeView child,
     const gfx::Point& location) {
@@ -438,4 +430,8 @@
     observer.OnPositionRequiresUpdate();
 }
 
+const views::Widget* NativeAppWindowViews::GetWidgetImpl() const {
+  return widget_;
+}
+
 }  // namespace native_app_window
diff --git a/extensions/components/native_app_window/native_app_window_views.h b/extensions/components/native_app_window/native_app_window_views.h
index 360f1d5..a2726b6 100644
--- a/extensions/components/native_app_window/native_app_window_views.h
+++ b/extensions/components/native_app_window/native_app_window_views.h
@@ -99,8 +99,6 @@
   void SaveWindowPlacement(const gfx::Rect& bounds,
                            ui::WindowShowState show_state) override;
   void DeleteDelegate() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   bool ShouldDescendIntoChildForEventHandling(
       gfx::NativeView child,
       const gfx::Point& location) override;
@@ -158,6 +156,9 @@
   // Informs modal dialogs that they need to update their positions.
   void OnViewWasResized();
 
+  // WidgetDelegate:
+  const views::Widget* GetWidgetImpl() const override;
+
   extensions::AppWindow* app_window_ = nullptr;  // Not owned.
   views::WebView* web_view_ = nullptr;
   views::Widget* widget_ = nullptr;
diff --git a/google_apis/gcm/BUILD.gn b/google_apis/gcm/BUILD.gn
index 5c1ac6b2..d3c43634 100644
--- a/google_apis/gcm/BUILD.gn
+++ b/google_apis/gcm/BUILD.gn
@@ -104,9 +104,7 @@
     "monitoring/fake_gcm_stats_recorder.h",
   ]
 
-  public_deps = [
-    ":gcm",
-  ]
+  public_deps = [ ":gcm" ]
   deps = [
     "//base",
     "//mojo/public/cpp/system:system",
@@ -120,9 +118,7 @@
 if (!is_ios) {
   executable("mcs_probe") {
     testonly = true
-    sources = [
-      "tools/mcs_probe.cc",
-    ]
+    sources = [ "tools/mcs_probe.cc" ]
 
     deps = [
       ":gcm",
diff --git a/gpu/command_buffer/client/BUILD.gn b/gpu/command_buffer/client/BUILD.gn
index 883c193..3938bdf 100644
--- a/gpu/command_buffer/client/BUILD.gn
+++ b/gpu/command_buffer/client/BUILD.gn
@@ -15,49 +15,33 @@
 # separate static libraries in non-component build.
 group("client") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu",
-    ]
+    public_deps = [ "//gpu" ]
   } else {
-    public_deps = [
-      ":client_sources",
-    ]
+    public_deps = [ ":client_sources" ]
   }
 }
 
 group("gles2_cmd_helper") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:gles2",
-    ]
+    public_deps = [ "//gpu:gles2" ]
   } else {
-    public_deps = [
-      ":gles2_cmd_helper_sources",
-    ]
+    public_deps = [ ":gles2_cmd_helper_sources" ]
   }
 }
 
 group("raster") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:raster",
-    ]
+    public_deps = [ "//gpu:raster" ]
   } else {
-    public_deps = [
-      ":raster_sources",
-    ]
+    public_deps = [ ":raster_sources" ]
   }
 }
 
 group("webgpu") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:webgpu",
-    ]
+    public_deps = [ "//gpu:webgpu" ]
   } else {
-    public_deps = [
-      ":webgpu_sources",
-    ]
+    public_deps = [ ":webgpu_sources" ]
   }
 }
 
@@ -171,13 +155,9 @@
 ]
 
 source_set("interface_base") {
-  sources = [
-    "interface_base.h",
-  ]
+  sources = [ "interface_base.h" ]
   public_configs = [ "//third_party/khronos:khronos_headers" ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 # Provides GLES2 interface, but does not cause any implementation to be linked
@@ -301,9 +281,7 @@
     ":webgpu_interface",
     "//gpu/command_buffer/common:webgpu",
   ]
-  public_deps = [
-    "//third_party/dawn/src/dawn:dawn_headers",
-  ]
+  public_deps = [ "//third_party/dawn/src/dawn:dawn_headers" ]
   sources = [
     "webgpu_cmd_helper.cc",
     "webgpu_cmd_helper.h",
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn
index 21631d9..b1d05d4 100644
--- a/gpu/command_buffer/common/BUILD.gn
+++ b/gpu/command_buffer/common/BUILD.gn
@@ -12,44 +12,30 @@
 
 group("common") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu",
-    ]
+    public_deps = [ "//gpu" ]
   } else {
-    public_deps = [
-      ":common_sources",
-    ]
+    public_deps = [ ":common_sources" ]
   }
 }
 
 group("gles2") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:gles2",
-    ]
+    public_deps = [ "//gpu:gles2" ]
   } else {
-    public_deps = [
-      ":gles2_sources",
-    ]
+    public_deps = [ ":gles2_sources" ]
   }
 }
 
 group("raster") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:gles2",
-    ]
+    public_deps = [ "//gpu:gles2" ]
   } else {
-    public_deps = [
-      ":raster_sources",
-    ]
+    public_deps = [ ":raster_sources" ]
   }
 }
 
 group("webgpu") {
-  public_deps = [
-    ":webgpu_sources",
-  ]
+  public_deps = [ ":webgpu_sources" ]
 }
 
 jumbo_source_set("common_sources") {
@@ -112,9 +98,7 @@
     "//ui/gfx/geometry",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   # TODO(piman): needed for gpu_memory_buffer_support.cc. Split common vs gles2
   # specifics.
@@ -141,9 +125,7 @@
     ":gles2_utils",
     "//base",
   ]
-  public_deps = [
-    ":common",
-  ]
+  public_deps = [ ":common" ]
 }
 
 source_set("raster_sources") {
@@ -215,9 +197,7 @@
 
   defines = [ "GLES2_UTILS_IMPLEMENTATION" ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 
   all_dependent_configs = [ "//third_party/khronos:khronos_headers" ]
 }
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 5b79fa99..05fd988 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -11,25 +11,17 @@
 
 group("service") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu",
-    ]
+    public_deps = [ "//gpu" ]
   } else {
-    public_deps = [
-      ":service_sources",
-    ]
+    public_deps = [ ":service_sources" ]
   }
 }
 
 group("gles2") {
   if (is_component_build) {
-    public_deps = [
-      "//gpu:gles2",
-    ]
+    public_deps = [ "//gpu:gles2" ]
   } else {
-    public_deps = [
-      ":gles2_sources",
-    ]
+    public_deps = [ ":gles2_sources" ]
   }
 }
 
@@ -449,9 +441,7 @@
 }
 
 proto_library("disk_cache_proto") {
-  sources = [
-    "disk_cache_proto.proto",
-  ]
+  sources = [ "disk_cache_proto.proto" ]
 }
 
 if (is_android) {
diff --git a/gpu/config/skia_limits.cc b/gpu/config/skia_limits.cc
index 0863d31..82fb1dc 100644
--- a/gpu/config/skia_limits.cc
+++ b/gpu/config/skia_limits.cc
@@ -15,12 +15,7 @@
     size_t* max_resource_cache_bytes,
     size_t* max_glyph_cache_texture_bytes) {
   // Default limits.
-#if defined(OS_FUCHSIA)
-  // Reduce protected budget on fuchsia due to https://fxb/36620.
-  constexpr size_t kMaxGaneshResourceCacheBytes = 24 * 1024 * 1024;
-#else
   constexpr size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
-#endif  // defined(OS_FUCHSIA)
   constexpr size_t kMaxDefaultGlyphCacheTextureBytes = 2048 * 1024 * 4;
 
   *max_resource_cache_bytes = kMaxGaneshResourceCacheBytes;
@@ -41,13 +36,12 @@
   constexpr size_t kMaxLowEndGlyphCacheTextureBytes = 1024 * 512 * 4;
   // High-end / low-end memory cutoffs.
   constexpr int64_t kHighEndMemoryThreshold = 4096LL * 1024 * 1024;
-  constexpr int64_t kLowEndMemoryThreshold = 512LL * 1024 * 1024;
 
-  int64_t amount_of_physical_memory = base::SysInfo::AmountOfPhysicalMemory();
-  if (amount_of_physical_memory <= kLowEndMemoryThreshold) {
+  if (base::SysInfo::IsLowEndDevice()) {
     *max_resource_cache_bytes = kMaxLowEndGaneshResourceCacheBytes;
     *max_glyph_cache_texture_bytes = kMaxLowEndGlyphCacheTextureBytes;
-  } else if (amount_of_physical_memory >= kHighEndMemoryThreshold) {
+  } else if (base::SysInfo::AmountOfPhysicalMemory() >=
+             kHighEndMemoryThreshold) {
     *max_resource_cache_bytes = kMaxHighEndGaneshResourceCacheBytes;
   }
 #endif
diff --git a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
index a8a4f7c..5b5d9239 100644
--- a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
@@ -24,7 +24,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -33,7 +33,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone 7",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -42,7 +42,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -51,7 +51,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -60,7 +60,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -68,7 +68,7 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -76,7 +76,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -85,7 +85,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -94,7 +94,7 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -103,7 +103,7 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -112,7 +112,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -120,7 +120,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -128,7 +128,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -136,7 +136,7 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -144,7 +144,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -153,7 +153,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -162,7 +162,7 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -171,7 +171,7 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -180,7 +180,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -188,7 +188,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -196,7 +196,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -204,7 +204,7 @@
       "app": "crashpad_tests",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     }
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-device.json b/ios/build/bots/chromium.fyi/ios13-sdk-device.json
index 3de4aaf..9e6a326 100644
--- a/ios/build/bots/chromium.fyi/ios13-sdk-device.json
+++ b/ios/build/bots/chromium.fyi/ios13-sdk-device.json
@@ -3,7 +3,7 @@
     "Builder for Xcode 11 iOS 13 SDK",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "11b53",
+  "xcode build version": "11b500",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
index 3460aea..8914fce8 100644
--- a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
@@ -2,7 +2,7 @@
   "comments": [
     "Runs tests with Xcode11 Beta SDK on iOS 13 beta simulators."
   ],
-  "xcode build version": "11b53",
+  "xcode build version": "11b500",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
@@ -21,7 +21,6 @@
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -30,7 +29,6 @@
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -39,7 +37,6 @@
     {
       "include": "common_tests.json",
       "device type": "iPhone 6s",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -48,7 +45,6 @@
     {
       "include": "eg_tests.json",
       "device type": "iPhone 7",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -58,7 +54,6 @@
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -68,7 +63,6 @@
     {
       "include": "eg_tests.json",
       "device type": "iPhone X",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -78,7 +72,6 @@
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -88,7 +81,6 @@
     {
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
-      "xcode build version": "11b53",
       "os": "13.2.2",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6",
@@ -100,7 +92,6 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -109,7 +100,6 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "12.4",
-      "xcode build version": "11b53",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -117,7 +107,6 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -125,7 +114,6 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -134,7 +122,6 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -143,7 +130,6 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -152,7 +138,6 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -161,7 +146,6 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -169,7 +153,6 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -177,7 +160,6 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.4",
-      "xcode build version": "11b53",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     }
diff --git a/ios/build/bots/chromium.mac/ios13-beta-simulator.json b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
index f882f57e..f67e624 100644
--- a/ios/build/bots/chromium.mac/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
@@ -24,7 +24,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -33,7 +33,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone 7",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -42,7 +42,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -51,7 +51,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -60,7 +60,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "pool":"chromium.tests",
       "host os": "Mac-10.14.6"
     },
@@ -68,7 +68,7 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -76,7 +76,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -85,7 +85,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -94,7 +94,7 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -103,7 +103,7 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests",
       "xcode parallelization": true
@@ -112,7 +112,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -120,7 +120,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -128,7 +128,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "13.2.2",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     },
@@ -136,7 +136,7 @@
       "app": "crashpad_tests",
       "device type": "iPhone X",
       "os": "12.4",
-      "xcode build version": "11b53",
+      "xcode build version": "11b500",
       "host os": "Mac-10.14.6",
       "pool":"chromium.tests"
     }
diff --git a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
index efcc52b..d97648e 100644
--- a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
@@ -5,7 +5,7 @@
     "Note: This file exists only to support the trybot.",
     "It should be kept in sync with the CI configuration in ../chromium.fyi/."
   ],
-  "xcode build version": "11b53",
+  "xcode build version": "11b500",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/chrome/browser/infobars/overlays/BUILD.gn b/ios/chrome/browser/infobars/overlays/BUILD.gn
index 905d7e40..60a5ca7 100644
--- a/ios/chrome/browser/infobars/overlays/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/BUILD.gn
@@ -14,8 +14,8 @@
     "infobar_overlay_request_inserter.mm",
     "infobar_overlay_tab_helper.h",
     "infobar_overlay_tab_helper.mm",
-    "infobar_overlay_type.h",
   ]
+  public_deps = [ ":overlay_type" ]
   deps = [
     "//base",
     "//components/infobars/core",
@@ -30,6 +30,11 @@
   ]
 }
 
+source_set("overlay_type") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [ "infobar_overlay_type.h" ]
+}
+
 source_set("util") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
index 29e6d60..99e25e3 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
@@ -5,9 +5,7 @@
 source_set("browser_agent") {
   configs += [ "//build/config/compiler:enable_arc" ]
   friend = [ ":unit_tests" ]
-  public = [
-    "infobar_overlay_browser_agent.h",
-  ]
+  public = [ "infobar_overlay_browser_agent.h" ]
   sources = [
     "infobar_banner_overlay_request_callback_installer.h",
     "infobar_banner_overlay_request_callback_installer.mm",
@@ -37,6 +35,7 @@
   deps = [
     ":browser_agent",
     "//base",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/ui/infobars:feature_flags",
   ]
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/infobar_banner_overlay_request_callback_installer_unittest.mm
index dd0c8f6d..5012fc7 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/infobar_banner_overlay_request_callback_installer_unittest.mm
@@ -30,7 +30,7 @@
                    &mock_handler_) {
     std::unique_ptr<OverlayRequest> request =
         OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
-            &infobar_);
+            &infobar_, InfobarOverlayType::kBanner);
     request_ = request.get();
     queue()->AddRequest(std::move(request));
     installer_.InstallCallbacks(request_);
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 dbbaf0d..5f8db11 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
@@ -94,7 +94,8 @@
   // Add an infobar request to the banner modality, expecting
   // InfobarBannerInteractionHandler::BannerVisibilityChanged() to be called.
   std::unique_ptr<OverlayRequest> added_request =
-      OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(&infobar_);
+      OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
+          &infobar_, InfobarOverlayType::kBanner);
   OverlayRequest* request = added_request.get();
   MockInfobarBannerInteractionHandler& mock_banner_handler =
       *mock_interaction_handler_->mock_banner_handler();
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 7b7635a..5050696 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
@@ -6,6 +6,7 @@
 
 #include "base/feature_list.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -16,6 +17,11 @@
   if (!base::FeatureList::IsEnabled(kInfobarOverlayUI))
     return;
   InfobarOverlayBrowserAgent::CreateForBrowser(browser);
+  InfobarOverlayBrowserAgent* browser_agent =
+      InfobarOverlayBrowserAgent::FromBrowser(browser);
+  browser_agent->SetInfobarInteractionHandler(
+      InfobarType::kInfobarTypePasswordSave,
+      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/passwords/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
new file mode 100644
index 0000000..27a7a64
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
@@ -0,0 +1,43 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("passwords") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "password_infobar_banner_interaction_handler.h",
+    "password_infobar_banner_interaction_handler.mm",
+    "password_infobar_interaction_handler.h",
+    "password_infobar_interaction_handler.mm",
+  ]
+  deps = [
+    "//base",
+    "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
+    "//ios/chrome/browser/passwords:infobar_delegates",
+  ]
+}
+
+source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  testonly = true
+  sources = [ "password_infobar_banner_interaction_handler_unittest.mm" ]
+  deps = [
+    ":passwords",
+    "//base/test:test_support",
+    "//components/password_manager/core/browser:test_support",
+    "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/infobars",
+    "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/test",
+    "//ios/chrome/browser/overlays",
+    "//ios/chrome/browser/passwords:infobar_delegates",
+    "//ios/chrome/browser/passwords/test",
+    "//ios/chrome/browser/ui/infobars:feature_flags",
+    "//ios/chrome/browser/ui/infobars/test",
+    "//ios/chrome/test:test_support",
+    "//ios/web/public/test/fakes",
+    "//testing/gtest",
+  ]
+}
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
new file mode 100644
index 0000000..baa678f
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h
@@ -0,0 +1,29 @@
+// 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_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"
+
+class IOSChromeSavePasswordInfoBarDelegate;
+
+// Helper object that updates the model layer for interaction events with the
+// passwords infobar banner UI.
+class PasswordInfobarBannerInteractionHandler
+    : public InfobarBannerInteractionHandler {
+ public:
+  // InfobarBannerInteractionHandler:
+  void BannerVisibilityChanged(InfoBarIOS* infobar, bool visible) override;
+  void MainButtonTapped(InfoBarIOS* infobar) override;
+  void ShowModalButtonTapped(InfoBarIOS* infobar,
+                             web::WebState* web_state) override;
+  void BannerDismissedByUser(InfoBarIOS* infobar) override;
+
+ private:
+  // Returns the password delegate from |infobar|.
+  IOSChromeSavePasswordInfoBarDelegate* GetInfobarDelegate(InfoBarIOS* infobar);
+};
+
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_BANNER_INTERACTION_HANDLER_H_
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
new file mode 100644
index 0000000..3d686681
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.mm
@@ -0,0 +1,60 @@
+// 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/passwords/password_infobar_banner_interaction_handler.h"
+
+#include "base/logging.h"
+#include "ios/chrome/browser/infobars/infobar_ios.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
+
+#pragma mark - InfobarBannerInteractionHandler
+
+void PasswordInfobarBannerInteractionHandler::BannerVisibilityChanged(
+    InfoBarIOS* infobar,
+    bool visible) {
+  if (visible) {
+    GetInfobarDelegate(infobar)->InfobarPresenting(/*automatic=*/YES);
+  } else {
+    GetInfobarDelegate(infobar)->InfobarDismissed();
+  }
+}
+
+void PasswordInfobarBannerInteractionHandler::MainButtonTapped(
+    InfoBarIOS* infobar) {
+  infobar->set_accepted(GetInfobarDelegate(infobar)->Accept());
+}
+
+void PasswordInfobarBannerInteractionHandler::ShowModalButtonTapped(
+    InfoBarIOS* infobar,
+    web::WebState* web_state) {
+  // TODO(crbug.com/1033154): Add support for showing modal UI via
+  // OverlayPresenter.
+}
+
+void PasswordInfobarBannerInteractionHandler::BannerDismissedByUser(
+    InfoBarIOS* infobar) {
+  // Notify the delegate that a user-initiated dismissal has been triggered.
+  // NOTE: InfoBarDismissed() (camel cased) is used to notify the delegate that
+  // the user initiated the upcoming dismissal (i.e. swiped to dismiss in the
+  // refresh UI).  InfobarDismissed() (not camel cased) is called in
+  // BannerVisibilityChanged() to notify the delegate of the dismissal of the
+  // UI.
+  GetInfobarDelegate(infobar)->InfoBarDismissed();
+}
+
+#pragma mark - Private
+
+IOSChromeSavePasswordInfoBarDelegate*
+PasswordInfobarBannerInteractionHandler::GetInfobarDelegate(
+    InfoBarIOS* infobar) {
+  IOSChromeSavePasswordInfoBarDelegate* delegate =
+      IOSChromeSavePasswordInfoBarDelegate::FromInfobarDelegate(
+          infobar->delegate());
+  DCHECK(delegate);
+  return delegate;
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler_unittest.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler_unittest.mm
new file mode 100644
index 0000000..921bfae
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler_unittest.mm
@@ -0,0 +1,75 @@
+// 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/passwords/password_infobar_banner_interaction_handler.h"
+
+#include "base/test/scoped_feature_list.h"
+#import "ios/chrome/browser/infobars/test/fake_infobar_ios.h"
+#import "ios/chrome/browser/overlays/public/overlay_request_queue.h"
+#import "ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
+#import "ios/chrome/browser/ui/infobars/infobar_feature.h"
+#import "ios/chrome/browser/ui/infobars/test/fake_infobar_ui_delegate.h"
+#import "ios/web/public/test/fakes/test_web_state.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// Test fixture for PasswordInfobarBannerInteractionHandler.
+class PasswordInfobarBannerInteractionHandlerTest : public PlatformTest {
+ public:
+  PasswordInfobarBannerInteractionHandlerTest()
+      : infobar_([[FakeInfobarUIDelegate alloc] init],
+                 MockIOSChromeSavePasswordInfoBarDelegate::Create()) {
+    scoped_feature_list_.InitWithFeatures({kInfobarUIReboot}, {});
+  }
+
+  MockIOSChromeSavePasswordInfoBarDelegate& mock_delegate() {
+    return *static_cast<MockIOSChromeSavePasswordInfoBarDelegate*>(
+        infobar_.delegate());
+  }
+
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  PasswordInfobarBannerInteractionHandler handler_;
+  web::TestWebState web_state_;
+  InfoBarIOS infobar_;
+};
+
+// Tests that BannerVisibilityChanged() calls InfobarPresenting() and
+// InfobarDismissed() on the mock delegate.
+TEST_F(PasswordInfobarBannerInteractionHandlerTest, Presentation) {
+  EXPECT_CALL(mock_delegate(), InfobarPresenting(true));
+  handler_.BannerVisibilityChanged(&infobar_, true);
+  EXPECT_CALL(mock_delegate(), InfobarDismissed());
+  handler_.BannerVisibilityChanged(&infobar_, false);
+}
+
+// Tests MainButtonTapped() calls Accept() on the mock delegate and resets
+// the infobar to be accepted.
+TEST_F(PasswordInfobarBannerInteractionHandlerTest, MainButton) {
+  ASSERT_FALSE(infobar_.accepted());
+  EXPECT_CALL(mock_delegate(), Accept()).WillOnce(testing::Return(true));
+  handler_.MainButtonTapped(&infobar_);
+  EXPECT_TRUE(infobar_.accepted());
+}
+
+// Tests that pressing the modal button calls adds an OverlayRequest for the
+// modal UI to the WebState's queue at OverlayModality::kInfobarModal.
+TEST_F(PasswordInfobarBannerInteractionHandlerTest, ShowModal) {
+  OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
+      &web_state_, OverlayModality::kInfobarModal);
+  ASSERT_EQ(0U, queue->size());
+  handler_.ShowModalButtonTapped(&infobar_, &web_state_);
+  // TODO(crbug.com/1033154): Verify that modal request has been added once
+  // modal passwords UI is implemented.
+}
+
+// Tests that BannerVisibilityChanged() calls InfobarPresenting() and
+// InfobarDismissed() on the mock delegate.
+TEST_F(PasswordInfobarBannerInteractionHandlerTest, UserInitiatedDismissal) {
+  EXPECT_CALL(mock_delegate(), InfoBarDismissed());
+  handler_.BannerDismissedByUser(&infobar_);
+}
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.h
new file mode 100644
index 0000000..4697defc
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.h
@@ -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.
+
+#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
+#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
+
+#include <memory>
+
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
+
+// An InfobarInteractionHandler that updates the model layer for interaction
+// events with the UI for password infobars.
+class PasswordInfobarInteractionHandler : public InfobarInteractionHandler {
+ public:
+  PasswordInfobarInteractionHandler();
+  ~PasswordInfobarInteractionHandler() override;
+};
+
+#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
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
new file mode 100644
index 0000000..8287687
--- /dev/null
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.mm
@@ -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.
+
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_interaction_handler.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"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+PasswordInfobarInteractionHandler::PasswordInfobarInteractionHandler()
+    : InfobarInteractionHandler(
+          SavePasswordInfobarBannerOverlayRequestConfig::RequestSupport(),
+          std::make_unique<PasswordInfobarBannerInteractionHandler>(),
+          /*sheet_handler=*/nullptr,
+          /*modal_handler=*/nullptr) {
+  // TODO(crbug.com/1033154): Create interaction handlers for detail sheet and
+  // modal.
+}
+
+PasswordInfobarInteractionHandler::~PasswordInfobarInteractionHandler() =
+    default;
diff --git a/ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.mm b/ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.mm
index 861d74c..cbeab154 100644
--- a/ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.mm
+++ b/ios/chrome/browser/infobars/overlays/fake_infobar_overlay_request_factory.mm
@@ -21,5 +21,5 @@
     infobars::InfoBar* infobar,
     InfobarOverlayType type) {
   return OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
-      static_cast<InfoBarIOS*>(infobar));
+      static_cast<InfoBarIOS*>(infobar), type);
 }
diff --git a/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn b/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
index 7c62994..35830f2 100644
--- a/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
+++ b/ios/chrome/browser/overlays/public/common/infobars/BUILD.gn
@@ -17,6 +17,7 @@
     "//components/infobars/core",
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:public",
+    "//ios/chrome/browser/infobars/overlays:overlay_type",
     "//ios/chrome/browser/overlays",
     "//ios/chrome/browser/ui/infobars:infobars_ui",
   ]
diff --git a/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h b/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h
index a424a9a0..40482404 100644
--- a/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h
+++ b/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_COMMON_INFOBARS_INFOBAR_OVERLAY_REQUEST_CONFIG_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_config.h"
 
 class InfoBarIOS;
@@ -17,20 +18,24 @@
  public:
   ~InfobarOverlayRequestConfig() override;
 
-  // The InfoBar that triggered this OverlayRequest.
+  // The infobar that triggered this OverlayRequest.
   InfoBarIOS* infobar() const { return infobar_; }
   // |infobar_|'s type.
   InfobarType infobar_type() const { return infobar_type_; }
   // Whether |infobar_| has a badge.
   bool has_badge() const { return has_badge_; }
+  // The overlay type for this infobar OverlayRequest.
+  InfobarOverlayType overlay_type() const { return overlay_type_; }
 
  private:
   OVERLAY_USER_DATA_SETUP(InfobarOverlayRequestConfig);
-  explicit InfobarOverlayRequestConfig(InfoBarIOS* infobar);
+  explicit InfobarOverlayRequestConfig(InfoBarIOS* infobar,
+                                       InfobarOverlayType overlay_type);
 
   InfoBarIOS* infobar_ = nullptr;
   InfobarType infobar_type_;
   bool has_badge_ = false;
+  InfobarOverlayType overlay_type_;
 };
 
 #endif  // IOS_CHROME_BROWSER_OVERLAYS_PUBLIC_COMMON_INFOBARS_INFOBAR_OVERLAY_REQUEST_CONFIG_H_
diff --git a/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.mm b/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.mm
index a378f9f..668592b 100644
--- a/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.mm
+++ b/ios/chrome/browser/overlays/public/common/infobars/infobar_overlay_request_config.mm
@@ -16,9 +16,12 @@
 
 OVERLAY_USER_DATA_SETUP_IMPL(InfobarOverlayRequestConfig);
 
-InfobarOverlayRequestConfig::InfobarOverlayRequestConfig(InfoBarIOS* infobar)
+InfobarOverlayRequestConfig::InfobarOverlayRequestConfig(
+    InfoBarIOS* infobar,
+    InfobarOverlayType overlay_type)
     : infobar_(infobar),
       infobar_type_(infobar->InfobarUIDelegate().infobarType),
-      has_badge_(infobar->InfobarUIDelegate().hasBadge) {}
+      has_badge_(infobar->InfobarUIDelegate().hasBadge),
+      overlay_type_(overlay_type) {}
 
 InfobarOverlayRequestConfig::~InfobarOverlayRequestConfig() = default;
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
index 7aa405a..1178354 100644
--- a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
+++ b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
@@ -45,5 +45,6 @@
 void SavePasswordInfobarBannerOverlayRequestConfig::CreateAuxilliaryData(
     base::SupportsUserData* user_data) {
   InfobarOverlayRequestConfig::CreateForUserData(
-      user_data, static_cast<InfoBarIOS*>(infobar_));
+      user_data, static_cast<InfoBarIOS*>(infobar_),
+      InfobarOverlayType::kBanner);
 }
diff --git a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
index fc66e6d0..1a4db77c 100644
--- a/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
+++ b/ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h
@@ -54,10 +54,16 @@
   // Informs the delegate that the Infobar has been presented. If |automatic|
   // YES the Infobar was presented automatically (e.g. The banner was
   // presented), if NO the user triggered it  (e.g. Tapped on the badge).
-  void InfobarPresenting(bool automatic);
+  // TODO(crbug.com/1040653): This function is only virtual so it can be mocked
+  // for testing purposes.  It should become non-virtual once this test is
+  // refactored for testability.
+  virtual void InfobarPresenting(bool automatic);
 
   // Informs the delegate that the Infobar has been dismissed.
-  void InfobarDismissed();
+  // TODO(crbug.com/1040653): This function is only virtual so it can be mocked
+  // for testing purposes.  It should become non-virtual once this test is
+  // refactored for testability.
+  virtual void InfobarDismissed();
 
   // true if password is being updated at the moment the InfobarModal is
   // created.
diff --git a/ios/chrome/browser/passwords/test/BUILD.gn b/ios/chrome/browser/passwords/test/BUILD.gn
index 96843d1..0b5a317c4 100644
--- a/ios/chrome/browser/passwords/test/BUILD.gn
+++ b/ios/chrome/browser/passwords/test/BUILD.gn
@@ -7,6 +7,8 @@
   testonly = true
 
   sources = [
+    "mock_ios_chrome_save_passwords_infobar_delegate.h",
+    "mock_ios_chrome_save_passwords_infobar_delegate.mm",
     "test_password_manager_client.h",
     "test_password_manager_client.mm",
   ]
@@ -16,6 +18,8 @@
     "//components/password_manager/core/common",
     "//components/prefs",
     "//components/prefs:test_support",
+    "//ios/chrome/browser/passwords:infobar_delegates",
+    "//testing/gmock",
     "//testing/gtest",
   ]
 }
diff --git a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h
new file mode 100644
index 0000000..8052f9c
--- /dev/null
+++ b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_PASSWORDS_TEST_MOCK_IOS_CHROME_SAVE_PASSWORDS_INFOBAR_DELEGATE_H_
+#define IOS_CHROME_BROWSER_PASSWORDS_TEST_MOCK_IOS_CHROME_SAVE_PASSWORDS_INFOBAR_DELEGATE_H_
+
+#include <memory>
+
+#import "ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+// Mock queue observer.
+class MockIOSChromeSavePasswordInfoBarDelegate
+    : public IOSChromeSavePasswordInfoBarDelegate {
+ public:
+  MockIOSChromeSavePasswordInfoBarDelegate(
+      bool is_sync_user,
+      bool password_update,
+      std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save);
+  ~MockIOSChromeSavePasswordInfoBarDelegate() override;
+
+  // Factory method that creates a MockIOSChromeSavePasswordInfoBarDelegate
+  // using a mock form.
+  static std::unique_ptr<MockIOSChromeSavePasswordInfoBarDelegate> Create();
+
+  MOCK_METHOD0(InfoBarDismissed, void());
+  MOCK_METHOD0(Accept, bool());
+  MOCK_METHOD1(InfobarPresenting, void(bool automatic));
+  MOCK_METHOD0(InfobarDismissed, void());
+};
+
+#endif  // IOS_CHROME_BROWSER_PASSWORDS_TEST_MOCK_IOS_CHROME_SAVE_PASSWORDS_INFOBAR_DELEGATE_H_
diff --git a/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm
new file mode 100644
index 0000000..dd26a3f
--- /dev/null
+++ b/ios/chrome/browser/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.mm
@@ -0,0 +1,40 @@
+// 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/passwords/test/mock_ios_chrome_save_passwords_infobar_delegate.h"
+
+#include "components/password_manager/core/browser/mock_password_form_manager_for_ui.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// static
+std::unique_ptr<MockIOSChromeSavePasswordInfoBarDelegate>
+MockIOSChromeSavePasswordInfoBarDelegate::Create() {
+  std::unique_ptr<password_manager::MockPasswordFormManagerForUI> form =
+      std::make_unique<password_manager::MockPasswordFormManagerForUI>();
+  EXPECT_CALL(*form, GetMetricsRecorder())
+      .WillRepeatedly(testing::Return(nullptr));
+  EXPECT_CALL(*form, GetCredentialSource())
+      .WillRepeatedly(testing::Return(
+          password_manager::metrics_util::CredentialSourceType::kUnknown));
+  return std::make_unique<MockIOSChromeSavePasswordInfoBarDelegate>(
+      /*is_sync_user=*/false,
+      /*password_update=*/false, std::move(form));
+}
+
+MockIOSChromeSavePasswordInfoBarDelegate::
+    MockIOSChromeSavePasswordInfoBarDelegate(
+        bool is_sync_user,
+        bool password_update,
+        std::unique_ptr<password_manager::PasswordFormManagerForUI>
+            form_to_save)
+    : IOSChromeSavePasswordInfoBarDelegate(is_sync_user,
+                                           password_update,
+                                           std::move(form_to_save)) {}
+
+MockIOSChromeSavePasswordInfoBarDelegate::
+    ~MockIOSChromeSavePasswordInfoBarDelegate() = default;
diff --git a/ios/chrome/browser/ssl/BUILD.gn b/ios/chrome/browser/ssl/BUILD.gn
index 74040cc..66f276a 100644
--- a/ios/chrome/browser/ssl/BUILD.gn
+++ b/ios/chrome/browser/ssl/BUILD.gn
@@ -53,9 +53,7 @@
     "captive_portal_features.cc",
     "captive_portal_features.h",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests") {
diff --git a/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm b/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
index b4eda88..5b1ad55c 100644
--- a/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/badges/badge_mediator_unittest.mm
@@ -303,7 +303,8 @@
   OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
       web_state(), OverlayModality::kInfobarBanner);
   queue->AddRequest(
-      OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(infobar));
+      OverlayRequest::CreateWithConfig<InfobarOverlayRequestConfig>(
+          infobar, InfobarOverlayType::kBanner));
   EXPECT_TRUE(item.badgeState & BadgeStatePresented);
 
   // Simulate dismissal of the banner and verify that the badge state is no
diff --git a/ios/chrome/browser/ui/dialogs/BUILD.gn b/ios/chrome/browser/ui/dialogs/BUILD.gn
index 71ad2b33..65f5939 100644
--- a/ios/chrome/browser/ui/dialogs/BUILD.gn
+++ b/ios/chrome/browser/ui/dialogs/BUILD.gn
@@ -33,9 +33,7 @@
 source_set("unit_tests") {
   testonly = true
 
-  sources = [
-    "java_script_dialog_blocking_state_unittest.mm",
-  ]
+  sources = [ "java_script_dialog_blocking_state_unittest.mm" ]
 
   deps = [
     ":dialogs",
@@ -96,9 +94,7 @@
     "completion_block_util.h",
     "completion_block_util.mm",
   ]
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
 
 source_set("unit_tests_internal") {
@@ -132,9 +128,7 @@
   defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "javascript_dialog_egtest.mm",
-  ]
+  sources = [ "javascript_dialog_egtest.mm" ]
   deps = [
     ":constants",
     ":feature_flags",
@@ -171,9 +165,7 @@
     "//build/config/ios:xctest_config",
   ]
   testonly = true
-  sources = [
-    "javascript_dialog_egtest.mm",
-  ]
+  sources = [ "javascript_dialog_egtest.mm" ]
   deps = [
     ":constants",
     ":feature_flags",
diff --git a/ios/chrome/browser/web/fake_mailto_handler_helpers.h b/ios/chrome/browser/web/fake_mailto_handler_helpers.h
deleted file mode 100644
index 8f30cfe..0000000
--- a/ios/chrome/browser/web/fake_mailto_handler_helpers.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
-#define IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
-
-#import "ios/chrome/browser/web/mailto_handler.h"
-#import "ios/chrome/browser/web/mailto_handler_gmail.h"
-#import "ios/chrome/browser/web/mailto_handler_manager.h"
-
-// Test fixtures for faking MailtoHandlerGmail objects that reports whether
-// Gmail app as installed or not.
-
-// Fakes Gmail handler where Gmail app is not installed.
-@interface FakeMailtoHandlerGmailNotInstalled : MailtoHandlerGmail
-@end
-
-// Fakes Gmail handler where Gmail app is installed.
-@interface FakeMailtoHandlerGmailInstalled : MailtoHandlerGmail
-@end
-
-// Fake mailto: handler
-@interface FakeMailtoHandlerForTesting : MailtoHandler
-@end
-
-// An observer object that counts and reports the number of times it has been
-// called by the MailtoHandlerManager object.
-@interface CountingMailtoHandlerManagerObserver
-    : NSObject<MailtoHandlerManagerObserver>
-// Returns the number of times that observer has been called.
-@property(nonatomic, readonly) int changeCount;
-@end
-
-#endif  // IOS_CHROME_BROWSER_WEB_FAKE_MAILTO_HANLDERS_H_
diff --git a/ios/chrome/browser/web/fake_mailto_handler_helpers.mm b/ios/chrome/browser/web/fake_mailto_handler_helpers.mm
deleted file mode 100644
index 8c41695..0000000
--- a/ios/chrome/browser/web/fake_mailto_handler_helpers.mm
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/web/fake_mailto_handler_helpers.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@implementation FakeMailtoHandlerGmailNotInstalled
-- (BOOL)isAvailable {
-  return NO;
-}
-@end
-
-@implementation FakeMailtoHandlerGmailInstalled
-- (BOOL)isAvailable {
-  return YES;
-}
-@end
-
-@implementation FakeMailtoHandlerForTesting
-- (instancetype)init {
-  return [super initWithName:@"FakeMail" appStoreID:@"12345678"];
-}
-- (BOOL)isAvailable {
-  return NO;
-}
-- (NSString*)beginningScheme {
-  return @"fakemail:/compose?";
-}
-@end
-
-@implementation CountingMailtoHandlerManagerObserver
-@synthesize changeCount = _changeCount;
-- (void)handlerDidChangeForMailtoHandlerManager:(MailtoHandlerManager*)manager {
-  ++_changeCount;
-}
-@end
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 1df0f72..973476ff 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -38,9 +38,7 @@
     "testing_application_context.mm",
   ]
 
-  public_deps = [
-    ":block_cleanup_test",
-  ]
+  public_deps = [ ":block_cleanup_test" ]
 
   deps = [
     "//base",
@@ -119,9 +117,7 @@
 
 source_set("run_all_unittests") {
   testonly = true
-  sources = [
-    "run_all_unittests.cc",
-  ]
+  sources = [ "run_all_unittests.cc" ]
   deps = [
     ":test_support",
     "//base",
@@ -192,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/passwords:unit_tests",
     "//ios/chrome/browser/itunes_urls:unit_tests",
     "//ios/chrome/browser/json_parser:unit_tests",
     "//ios/chrome/browser/language:unit_tests",
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn
index 93d614a..d491615 100644
--- a/ios/chrome/test/earl_grey2/BUILD.gn
+++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -26,17 +26,13 @@
 chrome_ios_eg2_test("ios_chrome_autofill_automation_eg2tests_module") {
   xcode_test_application_name = "ios_chrome_eg2tests"
 
-  deps = [
-    "//ios/chrome/browser/autofill/automation:eg2_tests",
-  ]
+  deps = [ "//ios/chrome/browser/autofill/automation:eg2_tests" ]
 }
 
 chrome_ios_eg2_test("ios_chrome_bookmarks_eg2tests_module") {
   xcode_test_application_name = "ios_chrome_eg2tests"
 
-  deps = [
-    "//ios/chrome/browser/ui/bookmarks:eg2_tests",
-  ]
+  deps = [ "//ios/chrome/browser/ui/bookmarks:eg2_tests" ]
 }
 
 chrome_ios_eg2_test("ios_chrome_integration_eg2tests_module") {
@@ -63,9 +59,7 @@
 chrome_ios_eg2_test("ios_chrome_smoke_eg2tests_module") {
   xcode_test_application_name = "ios_chrome_eg2tests"
 
-  deps = [
-    "//ios/chrome/test/earl_grey2:eg2_tests",
-  ]
+  deps = [ "//ios/chrome/test/earl_grey2:eg2_tests" ]
 }
 
 chrome_ios_eg2_test("ios_chrome_settings_eg2tests_module") {
@@ -119,9 +113,7 @@
 chrome_ios_eg2_test("ios_chrome_web_eg2tests_module") {
   xcode_test_application_name = "ios_chrome_eg2tests"
 
-  deps = [
-    "//ios/chrome/browser/web:eg2_tests",
-  ]
+  deps = [ "//ios/chrome/browser/web:eg2_tests" ]
 }
 
 source_set("eg2_tests") {
@@ -132,9 +124,7 @@
   ]
   testonly = true
 
-  sources = [
-    "smoke_egtest.mm",
-  ]
+  sources = [ "smoke_egtest.mm" ]
 
   deps = [
     "//ios/chrome/app/strings",
diff --git a/ios/chrome/test/perf/BUILD.gn b/ios/chrome/test/perf/BUILD.gn
index 93723b00..b79acf0a 100644
--- a/ios/chrome/test/perf/BUILD.gn
+++ b/ios/chrome/test/perf/BUILD.gn
@@ -5,9 +5,7 @@
 source_set("eg_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "chrome_perf_egtest.mm",
-  ]
+  sources = [ "chrome_perf_egtest.mm" ]
   deps = [
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/test/wpt/BUILD.gn b/ios/chrome/test/wpt/BUILD.gn
index a70b635..852f035e 100644
--- a/ios/chrome/test/wpt/BUILD.gn
+++ b/ios/chrome/test/wpt/BUILD.gn
@@ -15,24 +15,18 @@
 }
 
 chrome_ios_eg2_test_app_host("ios_cwt_chromedriver_tests") {
-  deps = [
-    ":eg_app_support+eg2",
-  ]
+  deps = [ ":eg_app_support+eg2" ]
 }
 
 chrome_ios_eg2_test("ios_cwt_chromedriver_tests_module") {
   xcode_test_application_name = "ios_cwt_chromedriver_tests"
 
-  deps = [
-    ":cwt_chromedriver_tests",
-  ]
+  deps = [ ":cwt_chromedriver_tests" ]
 }
 
 source_set("shared_helper_headers") {
   testonly = true
-  sources = [
-    "cwt_webdriver_app_interface.h",
-  ]
+  sources = [ "cwt_webdriver_app_interface.h" ]
 }
 
 source_set("eg_app_support+eg2") {
@@ -40,9 +34,7 @@
   testonly = true
   configs += [ "//build/config/compiler:enable_arc" ]
 
-  sources = [
-    "cwt_webdriver_app_interface.mm",
-  ]
+  sources = [ "cwt_webdriver_app_interface.mm" ]
 
   deps = [
     "//base",
@@ -59,9 +51,7 @@
     "//ui/gfx",
   ]
 
-  public_deps = [
-    ":shared_helper_headers",
-  ]
+  public_deps = [ ":shared_helper_headers" ]
 }
 
 source_set("cwt_chromedriver_tests") {
diff --git a/ios/components/BUILD.gn b/ios/components/BUILD.gn
index 03fb2b9..d3b5bed 100644
--- a/ios/components/BUILD.gn
+++ b/ios/components/BUILD.gn
@@ -9,9 +9,7 @@
 # "gn_all" target (i.e. by the bots).
 group("all_tests") {
   testonly = true
-  deps = [
-    ":ios_components_unittests",
-  ]
+  deps = [ ":ios_components_unittests" ]
 }
 
 # To add a unit test to this target, make a "unit_tests" source_set in your
diff --git a/ios/components/io_thread/BUILD.gn b/ios/components/io_thread/BUILD.gn
index bc1f92c..4f07383 100644
--- a/ios/components/io_thread/BUILD.gn
+++ b/ios/components/io_thread/BUILD.gn
@@ -29,9 +29,7 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [
-    "ios_io_thread_unittest.mm",
-  ]
+  sources = [ "ios_io_thread_unittest.mm" ]
   deps = [
     ":io_thread",
     "//base",
diff --git a/ios/web/favicon/BUILD.gn b/ios/web/favicon/BUILD.gn
index b6f26ebd..def37dc 100644
--- a/ios/web/favicon/BUILD.gn
+++ b/ios/web/favicon/BUILD.gn
@@ -29,9 +29,7 @@
     "//ios/web/public/favicon",
     "//testing/gtest",
   ]
-  sources = [
-    "favicon_util_unittest.mm",
-  ]
+  sources = [ "favicon_util_unittest.mm" ]
 }
 
 source_set("inttests") {
@@ -44,7 +42,5 @@
     "//ios/web/public:web_state_observer",
     "//ios/web/public/test",
   ]
-  sources = [
-    "favicon_callbacks_inttest.mm",
-  ]
+  sources = [ "favicon_callbacks_inttest.mm" ]
 }
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn
index 55fdcc19..bb024da 100644
--- a/ios/web/web_state/ui/BUILD.gn
+++ b/ios/web/web_state/ui/BUILD.gn
@@ -82,13 +82,9 @@
 }
 
 source_set("crw_web_view_navigation_proxy") {
-  sources = [
-    "crw_web_view_navigation_proxy.h",
-  ]
+  sources = [ "crw_web_view_navigation_proxy.h" ]
 
-  deps = [
-    "//ios/third_party/webkit",
-  ]
+  deps = [ "//ios/third_party/webkit" ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
 }
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index d9089b3..05fda3d3 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -345,9 +345,7 @@
   script = "//build/config/ios/generate_umbrella_header.py"
 
   full_header_path = target_gen_dir + "/ChromeWebView.h"
-  outputs = [
-    full_header_path,
-  ]
+  outputs = [ full_header_path ]
 
   args = [
     "--output-path",
@@ -397,9 +395,7 @@
 
 source_set("run_all_unittests") {
   testonly = true
-  sources = [
-    "test/run_all_unittests.cc",
-  ]
+  sources = [ "test/run_all_unittests.cc" ]
   deps = [
     "//base",
     "//base/test:test_support",
@@ -469,9 +465,7 @@
 test("ios_web_view_inttests") {
   testonly = true
 
-  deps = [
-    "//ios/web_view/test:inttests",
-  ]
+  deps = [ "//ios/web_view/test:inttests" ]
 
   bundle_deps = [ ":web_view+bundle" ]
 
@@ -557,12 +551,8 @@
     _license_path = "$_package_dir/LICENSE"
 
     script = "//tools/licenses.py"
-    inputs = [
-      "//buildtools/$host_os/gn",
-    ]
-    outputs = [
-      _license_path,
-    ]
+    inputs = [ "//buildtools/$host_os/gn" ]
+    outputs = [ _license_path ]
     args = [
       "license_file",
       rebase_path(_license_path, root_build_dir),
@@ -579,13 +569,9 @@
       "//AUTHORS",
       "//chrome/VERSION",
     ]
-    outputs = [
-      "$_package_dir/{{source_file_part}}",
-    ]
+    outputs = [ "$_package_dir/{{source_file_part}}" ]
 
-    deps = [
-      ":web_view",
-    ]
+    deps = [ ":web_view" ]
   }
 
   if (enable_dsyms) {
@@ -598,22 +584,16 @@
       # generate both the dSYM and binary image are listed in deps.
       _dsyms = [ "$root_out_dir/$ios_web_view_output_name.dSYM" ]
 
-      sources = [
-        "$root_out_dir/$ios_web_view_output_name.framework",
-      ]
+      sources = [ "$root_out_dir/$ios_web_view_output_name.framework" ]
 
       _output = "$_package_dir/$ios_web_view_output_name.dSYM.tar.bz2"
 
-      outputs = [
-        _output,
-      ]
+      outputs = [ _output ]
 
       args = [ rebase_path(_output, root_out_dir) ] +
              rebase_path(_dsyms, root_out_dir)
 
-      deps = [
-        ":web_view",
-      ]
+      deps = [ ":web_view" ]
     }
   } else {
     group("ios_web_view_dsym_archive") {
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
index bf5a59a..abcfedd4 100644
--- a/ipc/ipc_mojo_bootstrap.cc
+++ b/ipc/ipc_mojo_bootstrap.cc
@@ -989,6 +989,12 @@
     return true;
   }
 
+  bool WaitForFlushToComplete(
+      mojo::ScopedMessagePipeHandle flush_pipe) override {
+    // We don't support async flushing on the IPC Channel pipe.
+    return false;
+  }
+
   // Checked in places which must be run on the master endpoint's thread.
   base::ThreadChecker thread_checker_;
 
diff --git a/media/capture/video/chromeos/request_builder.h b/media/capture/video/chromeos/request_builder.h
index a23ef6a..95f4d8e5 100644
--- a/media/capture/video/chromeos/request_builder.h
+++ b/media/capture/video/chromeos/request_builder.h
@@ -13,7 +13,6 @@
 #include "media/capture/video/chromeos/camera_device_delegate.h"
 #include "media/capture/video/chromeos/mojom/camera3.mojom.h"
 #include "media/capture/video_capture_types.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace media {
 
diff --git a/media/capture/video/chromeos/stream_buffer_manager.h b/media/capture/video/chromeos/stream_buffer_manager.h
index cd231498..bd89f891 100644
--- a/media/capture/video/chromeos/stream_buffer_manager.h
+++ b/media/capture/video/chromeos/stream_buffer_manager.h
@@ -21,7 +21,6 @@
 #include "media/capture/video/chromeos/camera_device_delegate.h"
 #include "media/capture/video/chromeos/mojom/camera3.mojom.h"
 #include "media/capture/video_capture_types.h"
-#include "mojo/public/cpp/bindings/binding.h"
 
 namespace gfx {
 
diff --git a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
index da4a3c59..fdbe9d7 100644
--- a/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
+++ b/media/capture/video/chromeos/video_capture_device_factory_chromeos.cc
@@ -10,7 +10,6 @@
 #include "media/base/bind_to_current_loop.h"
 #include "media/capture/video/chromeos/camera_app_device_bridge_impl.h"
 #include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 
 namespace media {
 
diff --git a/media/fuchsia/cdm/BUILD.gn b/media/fuchsia/cdm/BUILD.gn
index 03bf20e..c06e17ee 100644
--- a/media/fuchsia/cdm/BUILD.gn
+++ b/media/fuchsia/cdm/BUILD.gn
@@ -18,9 +18,7 @@
     "fuchsia_stream_decryptor.h",
   ]
 
-  public_deps = [
-    "//third_party/fuchsia-sdk/sdk:fuchsia-media-drm",
-  ]
+  public_deps = [ "//third_party/fuchsia-sdk/sdk:fuchsia-media-drm" ]
 
   configs += [ "//media:subcomponent_config" ]
 
diff --git a/media/fuchsia/cdm/service/BUILD.gn b/media/fuchsia/cdm/service/BUILD.gn
index 6cf573a..0eae812 100644
--- a/media/fuchsia/cdm/service/BUILD.gn
+++ b/media/fuchsia/cdm/service/BUILD.gn
@@ -10,9 +10,7 @@
     "fuchsia_cdm_manager.h",
   ]
 
-  public_deps = [
-    "//third_party/fuchsia-sdk/sdk:fuchsia-media-drm",
-  ]
+  public_deps = [ "//third_party/fuchsia-sdk/sdk:fuchsia-media-drm" ]
 
   deps = [
     "//fuchsia/base",
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
index 9fead832..43e3cd3d 100644
--- a/mojo/public/cpp/bindings/BUILD.gn
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -129,6 +129,8 @@
     "associated_receiver.h",
     "associated_receiver_set.h",
     "associated_remote.h",
+    "async_flusher.cc",
+    "async_flusher.h",
     "binder_map.cc",
     "binder_map.h",
     "binding.h",
@@ -183,6 +185,8 @@
     "native_enum.h",
     "pending_associated_receiver.h",
     "pending_associated_remote.h",
+    "pending_flush.cc",
+    "pending_flush.h",
     "pending_receiver.h",
     "pending_remote.h",
     "pipe_control_message_handler.h",
@@ -240,9 +244,7 @@
     "//mojo/public/interfaces/bindings",
   ]
 
-  deps = [
-    "//ipc:native_handle_type_converters",
-  ]
+  deps = [ "//ipc:native_handle_type_converters" ]
 
   defines = [ "IS_MOJO_CPP_BINDINGS_IMPL" ]
 }
diff --git a/mojo/public/cpp/bindings/async_flusher.cc b/mojo/public/cpp/bindings/async_flusher.cc
new file mode 100644
index 0000000..f469545
--- /dev/null
+++ b/mojo/public/cpp/bindings/async_flusher.cc
@@ -0,0 +1,27 @@
+// 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 "mojo/public/cpp/bindings/async_flusher.h"
+
+#include <utility>
+
+namespace mojo {
+
+AsyncFlusher::AsyncFlusher() = default;
+
+AsyncFlusher::AsyncFlusher(AsyncFlusher&&) = default;
+
+AsyncFlusher& AsyncFlusher::operator=(AsyncFlusher&&) = default;
+
+AsyncFlusher::~AsyncFlusher() = default;
+
+void AsyncFlusher::SetPipe(ScopedMessagePipeHandle pipe) {
+  pipe_ = std::move(pipe);
+}
+
+ScopedMessagePipeHandle AsyncFlusher::PassPipe() {
+  return std::move(pipe_);
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/async_flusher.h b/mojo/public/cpp/bindings/async_flusher.h
new file mode 100644
index 0000000..b550d746
--- /dev/null
+++ b/mojo/public/cpp/bindings/async_flusher.h
@@ -0,0 +1,54 @@
+// 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 MOJO_PUBLIC_CPP_BINDINGS_ASYNC_FLUSHER_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_ASYNC_FLUSHER_H_
+
+#include "base/component_export.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace mojo {
+
+class PendingFlush;
+class PipeControlMessageProxy;
+
+// An object that can be consumed by |FlushAsync()| on a Remote or Receiver in
+// order to perform an asynchronous flush operation on the object. Every
+// AsyncFlusher is associated with a PendingFlush object which can be monitored
+// or consumed to remotely observe completion of the corresponding flush
+// operation.
+//
+// NOTE: Most commonly for asynchronous flush operations, |FlushAsync()| can
+// be called on a Remote or Receiver with no arguments. This creates an
+// AsyncFlusher/PendingFlush pair and immediately flushes the callee with the
+// resulting AsyncFlusher. The entangled PendingFlush is returned for subsequent
+// consumption.
+//
+// Direct use of AsyncFlusher (and in particular of the PendingFlush constructor
+// which takes an AsyncFlusher* argument to initialize) is reserved for edge
+// cases where a PendingFlush is needed before its corresponding flush operation
+// can be initiated (e.g. when the interface to flush lives on a different
+// thread from the interface that will wait on its PendingFlush).
+class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) AsyncFlusher {
+ public:
+  AsyncFlusher();
+  AsyncFlusher(AsyncFlusher&&);
+  AsyncFlusher(const AsyncFlusher&) = delete;
+  AsyncFlusher& operator=(AsyncFlusher&&);
+  AsyncFlusher& operator=(const AsyncFlusher&) = delete;
+  ~AsyncFlusher();
+
+ private:
+  friend class PendingFlush;
+  friend class PipeControlMessageProxy;
+
+  void SetPipe(ScopedMessagePipeHandle pipe);
+  ScopedMessagePipeHandle PassPipe();
+
+  ScopedMessagePipeHandle pipe_;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_ASYNC_FLUSHER_H_
diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc
index 11f948ba..f0eab65 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.cc
+++ b/mojo/public/cpp/bindings/lib/binding_state.cc
@@ -41,6 +41,15 @@
   return router_->WaitForIncomingMessage(deadline);
 }
 
+void BindingStateBase::PauseRemoteCallbacksUntilFlushCompletes(
+    PendingFlush flush) {
+  router_->PausePeerUntilFlushCompletes(std::move(flush));
+}
+
+void BindingStateBase::FlushAsync(AsyncFlusher flusher) {
+  router_->FlushAsync(std::move(flusher));
+}
+
 void BindingStateBase::Close() {
   if (!router_)
     return;
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h
index 6260885d..cadb81a 100644
--- a/mojo/public/cpp/bindings/lib/binding_state.h
+++ b/mojo/public/cpp/bindings/lib/binding_state.h
@@ -17,6 +17,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
@@ -27,6 +28,7 @@
 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
 #include "mojo/public/cpp/bindings/lib/pending_receiver_state.h"
 #include "mojo/public/cpp/bindings/message_header_validator.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 #include "mojo/public/cpp/system/core.h"
 
@@ -49,6 +51,9 @@
   bool WaitForIncomingMethodCall(
       MojoDeadline deadline = MOJO_DEADLINE_INDEFINITE);
 
+  void PauseRemoteCallbacksUntilFlushCompletes(PendingFlush flush);
+  void FlushAsync(AsyncFlusher flusher);
+
   void Close();
   void CloseWithReason(uint32_t custom_reason, const std::string& description);
 
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.cc b/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
index 696108a..348c63d7 100644
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
@@ -34,6 +34,15 @@
   endpoint_client_->RequireVersion(version);
 }
 
+void InterfacePtrStateBase::PauseReceiverUntilFlushCompletes(
+    PendingFlush flush) {
+  router_->PausePeerUntilFlushCompletes(std::move(flush));
+}
+
+void InterfacePtrStateBase::FlushAsync(AsyncFlusher flusher) {
+  router_->FlushAsync(std::move(flusher));
+}
+
 void InterfacePtrStateBase::Swap(InterfacePtrStateBase* other) {
   using std::swap;
   swap(other->router_, router_);
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
index f3f64fe..0d259f3 100644
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
@@ -23,6 +23,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
 #include "mojo/public/cpp/bindings/associated_group.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/interface_endpoint_client.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
@@ -30,6 +31,7 @@
 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
 #include "mojo/public/cpp/bindings/lib/pending_remote_state.h"
 #include "mojo/public/cpp/bindings/message_header_validator.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
 
 namespace mojo {
@@ -80,6 +82,8 @@
 
   void QueryVersion(base::OnceCallback<void(uint32_t)> callback);
   void RequireVersion(uint32_t version);
+  void PauseReceiverUntilFlushCompletes(PendingFlush flush);
+  void FlushAsync(AsyncFlusher flusher);
   void Swap(InterfacePtrStateBase* other);
   void Bind(PendingRemoteState* remote_state,
             scoped_refptr<base::SequencedTaskRunner> task_runner);
@@ -146,6 +150,16 @@
     InterfacePtrStateBase::RequireVersion(version);
   }
 
+  void PauseReceiverUntilFlushCompletes(PendingFlush flush) {
+    ConfigureProxyIfNecessary();
+    InterfacePtrStateBase::PauseReceiverUntilFlushCompletes(std::move(flush));
+  }
+
+  void FlushAsync(AsyncFlusher flusher) {
+    ConfigureProxyIfNecessary();
+    InterfacePtrStateBase::FlushAsync(std::move(flusher));
+  }
+
   void FlushForTesting() {
     ConfigureProxyIfNecessary();
     endpoint_client()->FlushForTesting();
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
index 6cfc97f..4a825fd6 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
@@ -514,6 +514,8 @@
 void MultiplexRouter::CloseMessagePipe() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.CloseMessagePipe();
+  flush_pipe_watcher_.reset();
+  active_flush_pipe_.reset();
   // CloseMessagePipe() above won't trigger connection error handler.
   // Explicitly call OnPipeConnectionError() so that associated endpoints will
   // get notified.
@@ -521,22 +523,28 @@
 }
 
 void MultiplexRouter::PauseIncomingMethodCallProcessing() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  connector_.PauseIncomingMethodCallProcessing();
-
-  MayAutoLock locker(&lock_);
-  paused_ = true;
-
-  for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter)
-    iter->second->ResetSyncMessageSignal();
+  PauseInternal(/*must_resume_manually=*/true);
 }
 
 void MultiplexRouter::ResumeIncomingMethodCallProcessing() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // If the owner is manually resuming from a previous pause request, the
+  // interface may also still be paused due to waiting on a pending async flush
+  // in the system.
+  //
+  // In that case we ignore the caller, except to subsequently allow implicit
+  // resume once the pending flush operation is finished.
+  if (active_flush_pipe_) {
+    MayAutoLock locker(&lock_);
+    must_resume_manually_ = false;
+    return;
+  }
+
   connector_.ResumeIncomingMethodCallProcessing();
 
   MayAutoLock locker(&lock_);
   paused_ = false;
+  must_resume_manually_ = false;
 
   for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) {
     auto sync_iter = sync_message_tasks_.find(iter->first);
@@ -550,6 +558,14 @@
   ProcessTasks(NO_DIRECT_CLIENT_CALLS, nullptr);
 }
 
+void MultiplexRouter::FlushAsync(AsyncFlusher flusher) {
+  control_message_proxy_.FlushAsync(std::move(flusher));
+}
+
+void MultiplexRouter::PausePeerUntilFlushCompletes(PendingFlush flush) {
+  control_message_proxy_.PausePeerUntilFlushCompletes(std::move(flush));
+}
+
 bool MultiplexRouter::HasAssociatedEndpoints() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   MayAutoLock locker(&lock_);
@@ -656,6 +672,31 @@
   return true;
 }
 
+bool MultiplexRouter::WaitForFlushToComplete(ScopedMessagePipeHandle pipe) {
+  // If this MultiplexRouter has an associated interface on some task runner
+  // other than the master interface's task runner, it is possible to process
+  // incoming control messages on that task runner. We don't support this
+  // control message on anything but the main interface though.
+  if (!task_runner_->RunsTasksInCurrentSequence())
+    return false;
+
+  flush_pipe_watcher_.emplace(FROM_HERE, SimpleWatcher::ArmingPolicy::MANUAL,
+                              task_runner_);
+  flush_pipe_watcher_->Watch(
+      pipe.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+      MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+      base::BindRepeating(&MultiplexRouter::OnFlushPipeSignaled, this));
+  if (flush_pipe_watcher_->Arm() != MOJO_RESULT_OK) {
+    // The peer must already be closed, so consider the flush to be complete.
+    flush_pipe_watcher_.reset();
+    return true;
+  }
+
+  active_flush_pipe_ = std::move(pipe);
+  PauseInternal(/*must_resume_manually=*/false);
+  return true;
+}
+
 void MultiplexRouter::OnPipeConnectionError(bool force_async_dispatch) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -688,6 +729,35 @@
   ProcessTasks(call_behavior, connector_.task_runner());
 }
 
+void MultiplexRouter::OnFlushPipeSignaled(MojoResult result,
+                                          const HandleSignalsState& state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  flush_pipe_watcher_.reset();
+  active_flush_pipe_.reset();
+
+  // If there is not an explicit Pause waiting for a Resume, we can unpause.
+  if (!must_resume_manually_)
+    ResumeIncomingMethodCallProcessing();
+}
+
+void MultiplexRouter::PauseInternal(bool must_resume_manually) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  connector_.PauseIncomingMethodCallProcessing();
+
+  MayAutoLock locker(&lock_);
+
+  paused_ = true;
+  for (auto& entry : endpoints_)
+    entry.second->ResetSyncMessageSignal();
+
+  // We do not want to override this to |false| if it's already |true|. If it's
+  // ever |true|, that means there's been at least one explicit Pause call since
+  // the last Resume and we must never unpause until at least one call to Resume
+  // is made.
+  must_resume_manually_ = must_resume_manually_ || must_resume_manually;
+}
+
 void MultiplexRouter::ProcessTasks(
     ClientCallBehavior client_call_behavior,
     base::SequencedTaskRunner* current_task_runner) {
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
index 8b31e51..3063ec4 100644
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
@@ -24,11 +24,13 @@
 #include "base/sequenced_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "mojo/public/cpp/bindings/associated_group_controller.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
 #include "mojo/public/cpp/bindings/connector.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/message_dispatcher.h"
 #include "mojo/public/cpp/bindings/message_header_validator.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
 #include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
@@ -139,6 +141,14 @@
   void PauseIncomingMethodCallProcessing();
   void ResumeIncomingMethodCallProcessing();
 
+  // Initiates an async flush operation. |flusher| signals its corresponding
+  // PendingFlush when the flush is actually complete.
+  void FlushAsync(AsyncFlusher flusher);
+
+  // Pauses the peer endpoint's message processing until a (potentially remote)
+  // flush operation corresponding to |flush| is completed.
+  void PausePeerUntilFlushCompletes(PendingFlush flush);
+
   // Whether there are any associated interfaces running currently.
   bool HasAssociatedEndpoints() const;
 
@@ -180,8 +190,11 @@
   bool OnPeerAssociatedEndpointClosed(
       InterfaceId id,
       const base::Optional<DisconnectReason>& reason) override;
+  bool WaitForFlushToComplete(ScopedMessagePipeHandle flush_pipe) override;
 
   void OnPipeConnectionError(bool force_async_dispatch);
+  void OnFlushPipeSignaled(MojoResult result, const HandleSignalsState& state);
+  void PauseInternal(bool must_resume_manually);
 
   // Specifies whether we are allowed to directly call into
   // InterfaceEndpointClient (given that we are already on the same sequence as
@@ -257,6 +270,10 @@
   MessageDispatcher dispatcher_;
   Connector connector_;
 
+  // Active whenever dispatch is blocked by a pending remote flush.
+  ScopedMessagePipeHandle active_flush_pipe_;
+  base::Optional<mojo::SimpleWatcher> flush_pipe_watcher_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   // Protects the following members.
@@ -280,8 +297,16 @@
 
   bool encountered_error_ = false;
 
+  // Indicates whether this router is paused, meaning it is not currently
+  // listening for or dispatching available inbound messages.
   bool paused_ = false;
 
+  // If this router is paused, this indicates whether the pause is due to an
+  // explicit call to |PauseIncomingMethodCallProcessing()| when |true|, or
+  // due implicit pause when waiting on an async flush operation when |false|.
+  // When |paused_| is |false|, this value is ignored.
+  bool must_resume_manually_ = false;
+
   bool testing_mode_ = false;
 
   bool being_destructed_ = false;
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
index 84136f81..0070eaf 100644
--- a/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
+++ b/mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
@@ -43,8 +43,8 @@
 
 bool PipeControlMessageHandler::Validate(Message* message) {
   internal::ValidationContext validation_context(
-      message->payload(), message->payload_num_bytes(), 0, 0, message,
-      description_.c_str());
+      message->payload(), message->payload_num_bytes(),
+      message->handles()->size(), 0, message, description_.c_str());
 
   if (message->name() == pipe_control::kRunOrClosePipeMessageId) {
     if (!internal::ValidateMessageIsRequestWithoutResponse(
@@ -53,7 +53,7 @@
     }
     return internal::ValidateMessagePayload<
         pipe_control::internal::RunOrClosePipeMessageParams_Data>(
-            message, &validation_context);
+        message, &validation_context);
   }
 
   return false;
@@ -65,6 +65,7 @@
       reinterpret_cast<
           pipe_control::internal::RunOrClosePipeMessageParams_Data*>(
           message->mutable_payload());
+  context.TakeHandlesFromMessage(message);
   pipe_control::RunOrClosePipeMessageParamsPtr params_ptr;
   internal::Deserialize<pipe_control::RunOrClosePipeMessageParamsDataView>(
       params, &params_ptr, &context);
@@ -81,6 +82,19 @@
     return delegate_->OnPeerAssociatedEndpointClosed(event->id, reason);
   }
 
+  if (params_ptr->input->is_flush_async()) {
+    // NOTE: There's nothing to do here but let the attached pipe go out of
+    // scoped and be closed. This means that the corresponding PendingFlush will
+    // eventually be signalled, unblocking the endpoint which is waiting on it,
+    // if any.
+    return true;
+  }
+
+  if (params_ptr->input->is_pause_until_flush_completes()) {
+    return delegate_->WaitForFlushToComplete(std::move(
+        params_ptr->input->get_pause_until_flush_completes()->flush_pipe));
+  }
+
   DVLOG(1) << "Unsupported command in a RunOrClosePipe message pipe control "
            << "message. Closing the pipe.";
   return false;
diff --git a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
index 7a2f42f..a810df4 100644
--- a/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
+++ b/mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
@@ -30,6 +30,7 @@
       params_ptr, message.payload_buffer(), &params, &context);
   message.set_interface_id(kInvalidInterfaceId);
   message.set_heap_profiler_tag(kMessageTag);
+  message.AttachHandlesFromSerializationContext(&context);
   return message;
 }
 
@@ -46,6 +47,23 @@
   ignore_result(receiver_->Accept(&message));
 }
 
+void PipeControlMessageProxy::PausePeerUntilFlushCompletes(PendingFlush flush) {
+  auto input = pipe_control::RunOrClosePipeInput::New();
+  input->set_pause_until_flush_completes(
+      pipe_control::PauseUntilFlushCompletes::New(flush.PassPipe()));
+  Message message(ConstructRunOrClosePipeMessage(std::move(input)));
+  message.set_heap_profiler_tag(kMessageTag);
+  ignore_result(receiver_->Accept(&message));
+}
+
+void PipeControlMessageProxy::FlushAsync(AsyncFlusher flusher) {
+  auto input = pipe_control::RunOrClosePipeInput::New();
+  input->set_flush_async(pipe_control::FlushAsync::New(flusher.PassPipe()));
+  Message message(ConstructRunOrClosePipeMessage(std::move(input)));
+  message.set_heap_profiler_tag(kMessageTag);
+  ignore_result(receiver_->Accept(&message));
+}
+
 // static
 Message PipeControlMessageProxy::ConstructPeerEndpointClosedMessage(
     InterfaceId id,
diff --git a/mojo/public/cpp/bindings/pending_flush.cc b/mojo/public/cpp/bindings/pending_flush.cc
new file mode 100644
index 0000000..779d1b28
--- /dev/null
+++ b/mojo/public/cpp/bindings/pending_flush.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/bindings/pending_flush.h"
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/async_flusher.h"
+
+namespace mojo {
+
+PendingFlush::PendingFlush(AsyncFlusher* flusher) {
+  ScopedMessagePipeHandle flusher_pipe;
+  CreateMessagePipe(/*options=*/nullptr, &pipe_, &flusher_pipe);
+  flusher->SetPipe(std::move(flusher_pipe));
+}
+
+PendingFlush::PendingFlush(PendingFlush&& other) = default;
+
+PendingFlush& PendingFlush::operator=(PendingFlush&& other) = default;
+
+PendingFlush::~PendingFlush() = default;
+
+ScopedMessagePipeHandle PendingFlush::PassPipe() {
+  DCHECK(pipe_) << "This PendingFlush has already been consumed.";
+  return std::move(pipe_);
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/pending_flush.h b/mojo/public/cpp/bindings/pending_flush.h
new file mode 100644
index 0000000..ee05fd35
--- /dev/null
+++ b/mojo/public/cpp/bindings/pending_flush.h
@@ -0,0 +1,73 @@
+// 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 MOJO_PUBLIC_CPP_BINDINGS_PENDING_FLUSH_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_PENDING_FLUSH_H_
+
+#include "base/component_export.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace mojo {
+
+class AsyncFlusher;
+
+// A PendingFlush represents an asynchronous flush operation on an arbitrary
+// (and potentially remote) interface pipe. This is generally used to allow
+// another pipe in the system to pause its own message processing until the
+// original pipe has been flushed. As such, it's a useful primitive for
+// arbitrarily complex synchronization operations across the system.
+//
+// The most common way to create a PendingFlush is to call |FlushAsync()| with
+// arguments on a Remote or Receiver. For example, consider a storage API with a
+// central control interface as well as multiple independent writers:
+//
+//     Remote<mojom::Storage> storage = ...;
+//     Remote<mojom::Writer> writer1, writer2;
+//     storage->GetWriter(writer1.BindNewPipeAndPassReceiver());
+//     storage->GetWriter(writer2.BindNewPipeAndPassReceiver());
+//
+// Suppose we want to issue some commands on each Writer, followed by a query on
+// the remote Storage object; but we want to ensure that the Storage query is
+// not dispatched until all previous Writer operations are dispatched. We could
+// write something like:
+//
+//     writer1->Put(...);
+//     storage.PauseReceiverUntilFlushCompletes(writer1.FlushAsync());
+//     writer2->Put(...);
+//     storage.PauseReceiverUntilFlushCompletes(writer2.FlushAsync());
+//     storage->Query(...);
+//
+// This effectively guarantees that the |Query()| call will never dispatch on
+// the Storage receiver before both |Put()| calls have dispatched on their
+// respective Writer receivers. This holds even if the receiving endpoints are
+// all in different processes.
+//
+// Note that |FlushAsync()| returns a PendingFlush object. For some use cases,
+// it may be desirable to create a PendingFlush before issuing a corresponding
+// |FlushAsync()| call. In that case, use the single-argument constructor
+// defined below.
+class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) PendingFlush {
+ public:
+  // Constructs a new PendingFlush associated with |*flusher|. |*flusher| should
+  // be a default-constructed AsyncFlusher, and once it is initialized by this
+  // constructor it should be used to flush some Remote or Receiver using their
+  // |FlushAsyncWithFlusher()| method.
+  explicit PendingFlush(AsyncFlusher* flusher);
+  PendingFlush(PendingFlush&&);
+  PendingFlush(const PendingFlush&) = delete;
+  PendingFlush& operator=(PendingFlush&&);
+  PendingFlush& operator=(const PendingFlush&) = delete;
+  ~PendingFlush();
+
+ private:
+  friend class PipeControlMessageProxy;
+
+  ScopedMessagePipeHandle PassPipe();
+
+  ScopedMessagePipeHandle pipe_;
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BINDINGS_PENDING_FLUSH_H_
diff --git a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h b/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
index 16fd918..93d2f79f 100644
--- a/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
+++ b/mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h
@@ -20,6 +20,10 @@
       InterfaceId id,
       const base::Optional<DisconnectReason>& reason) = 0;
 
+  // The implementation should cease dispatching messages until the
+  // |flush_pipe|'s peer is closed.
+  virtual bool WaitForFlushToComplete(ScopedMessagePipeHandle flush_pipe) = 0;
+
  protected:
   virtual ~PipeControlMessageHandlerDelegate() {}
 };
diff --git a/mojo/public/cpp/bindings/pipe_control_message_proxy.h b/mojo/public/cpp/bindings/pipe_control_message_proxy.h
index 1eb949f..b36745ac 100644
--- a/mojo/public/cpp/bindings/pipe_control_message_proxy.h
+++ b/mojo/public/cpp/bindings/pipe_control_message_proxy.h
@@ -8,10 +8,12 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/optional.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/disconnect_reason.h"
 #include "mojo/public/cpp/bindings/interface_id.h"
 #include "mojo/public/cpp/bindings/lib/serialization_context.h"
 #include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 
 namespace mojo {
 
@@ -28,6 +30,8 @@
 
   void NotifyPeerEndpointClosed(InterfaceId id,
                                 const base::Optional<DisconnectReason>& reason);
+  void PausePeerUntilFlushCompletes(PendingFlush flush);
+  void FlushAsync(AsyncFlusher flusher);
 
   static Message ConstructPeerEndpointClosedMessage(
       InterfaceId id,
diff --git a/mojo/public/cpp/bindings/receiver.h b/mojo/public/cpp/bindings/receiver.h
index 8bc25e09..045bd3e5d 100644
--- a/mojo/public/cpp/bindings/receiver.h
+++ b/mojo/public/cpp/bindings/receiver.h
@@ -13,10 +13,12 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequenced_task_runner.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/connection_group.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "mojo/public/cpp/bindings/lib/binding_state.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -205,6 +207,49 @@
     return internal_state_.WaitForIncomingMethodCall(MOJO_DEADLINE_INDEFINITE);
   }
 
+  // Pauses the Remote endpoint, stopping dispatch of callbacks on that end. Any
+  // callbacks called prior to this will dispatch before the Remote endpoint is
+  // paused; any callbacks called after this will only be called once the flush
+  // operation corresponding to |flush| is completed or canceled.
+  //
+  // See documentation for |FlushAsync()| on Remote and Receiver for how to
+  // acquire a PendingFlush object, and documentation on PendingFlush for
+  // example usage.
+  void PauseRemoteCallbacksUntilFlushCompletes(PendingFlush flush) {
+    internal_state_.PauseRemoteCallbacksUntilFlushCompletes(std::move(flush));
+  }
+
+  // Flushes the Remote endpoint asynchronously using |flusher|. The
+  // corresponding PendingFlush will be notified only once all response
+  // callbacks issued prior to this operation have been dispatched at the Remote
+  // endpoint.
+  //
+  // NOTE: It is more common to use |FlushAsync()| defined below. If you really
+  // want to provide your own AsyncFlusher using this method, see the
+  // single-arugment constructor on PendingFlush. This would typically be used
+  // when code executing on the current sequence wishes to immediately pause
+  // one of its remote endpoints to wait on a flush operation that needs to be
+  // initiated on a separate sequence. Rather than bouncing to the second
+  // sequence to initiate a flush and then passing a PendingFlush back to the
+  // original sequence, the AsyncFlusher/PendingFlush can be created on the
+  // original sequence and a single task can be posted to pass the AsyncFlusher
+  // to the second sequence for use with this method.
+  void FlushAsyncWithFlusher(AsyncFlusher flusher) {
+    internal_state_.FlushAsync(std::move(flusher));
+  }
+
+  // Same as above but an AsyncFlusher/PendingFlush pair is created on the
+  // caller's behalf. The AsyncFlusher is immediately passed to a
+  // |FlushAsyncWithFlusher()| call on this object, while the PendingFlush is
+  // returned for use by the caller. See documentation on PendingFlush for
+  // example usage.
+  PendingFlush FlushAsync() {
+    AsyncFlusher flusher;
+    PendingFlush flush(&flusher);
+    FlushAsyncWithFlusher(std::move(flusher));
+    return flush;
+  }
+
   // Flushes any replies previously sent by the Receiver, only unblocking once
   // acknowledgement from the Remote is received.
   void FlushForTesting() { internal_state_.FlushForTesting(); }
diff --git a/mojo/public/cpp/bindings/remote.h b/mojo/public/cpp/bindings/remote.h
index 51349cd..bdc07f0 100644
--- a/mojo/public/cpp/bindings/remote.h
+++ b/mojo/public/cpp/bindings/remote.h
@@ -15,8 +15,10 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
 #include "mojo/public/cpp/bindings/interface_ptr_info.h"
 #include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -307,6 +309,51 @@
     internal_state_.RequireVersion(version);
   }
 
+  // Pauses the receiving endpoint until the flush corresponding to |flush| has
+  // completed. Any calls made on this Remote prior to this call will be
+  // dispatched at the receiving endpoint before pausing. The endpoint will not
+  // dispatch any subsequent calls until the flush operation corresponding to
+  // |flush| has been completed or canceled.
+  //
+  // See documentation for |FlushAsync()| on Remote and Receiver for how to
+  // acquire a PendingFlush object, and documentation on PendingFlush for
+  // example usage.
+  void PauseReceiverUntilFlushCompletes(PendingFlush flush) {
+    internal_state_.PauseReceiverUntilFlushCompletes(std::move(flush));
+  }
+
+  // Flushes the receiving endpoint asynchronously using |flusher|. Once all
+  // calls made on this Remote prior to this |FlushAsyncWithFlusher()| call have
+  // dispatched at the receiving endpoint, |flusher| will signal its
+  // corresponding PendingFlush, unblocking any endpoint waiting on the flush
+  // operation.
+  //
+  // NOTE: It is more common to use |FlushAsync()| defined below. If you really
+  // want to provide your own AsyncFlusher using this method, see the
+  // single-arugment constructor on PendingFlush. This would typically be used
+  // when code executing on the current sequence wishes to immediately pause
+  // one of its remote endpoints to wait on a flush operation that needs to be
+  // initiated on a separate sequence. Rather than bouncing to the second
+  // sequence to initiate a flush and then passing a PendingFlush back to the
+  // original sequence, the AsyncFlusher/PendingFlush can be created on the
+  // original sequence and a single task can be posted to pass the AsyncFlusher
+  // to the second sequence for use with this method.
+  void FlushAsyncWithFlusher(AsyncFlusher flusher) {
+    internal_state_.FlushAsync(std::move(flusher));
+  }
+
+  // Same as above but an AsyncFlusher/PendingFlush pair is created on the
+  // caller's behalf. The AsyncFlusher is immediately passed to a
+  // |FlushAsyncWithFlusher()| call on this object, while the PendingFlush is
+  // returned for use by the caller. See documentation on PendingFlush for
+  // example usage.
+  PendingFlush FlushAsync() {
+    AsyncFlusher flusher;
+    PendingFlush flush(&flusher);
+    FlushAsyncWithFlusher(std::move(flusher));
+    return flush;
+  }
+
   // Sends a no-op message on the underlying message pipe and runs the current
   // message loop until its response is received. This can be used in tests to
   // verify that no message was sent on a message pipe in response to some
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
index 95b9c1da..32175796 100644
--- a/mojo/public/cpp/bindings/tests/BUILD.gn
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -23,6 +23,7 @@
     "data_view_unittest.cc",
     "enum_headers_unittest.cc",
     "equals_unittest.cc",
+    "flush_async_unittest.cc",
     "handle_passing_unittest.cc",
     "hash_unittest.cc",
     "idle_tracking_unittest.cc",
@@ -76,9 +77,7 @@
     "//testing/gtest",
   ]
 
-  data = [
-    "//mojo/public/interfaces/bindings/tests/data/validation/",
-  ]
+  data = [ "//mojo/public/interfaces/bindings/tests/data/validation/" ]
 
   if (is_ios) {
     assert_no_deps = [ "//third_party/blink/*" ]
@@ -141,6 +140,7 @@
     "binder_map_unittest.test-mojom",
     "connection_group_unittest.test-mojom",
     "enum_headers_unittest.test-mojom",
+    "flush_async_unittest.test-mojom",
     "idle_tracking_unittest.test-mojom",
     "receiver_unittest.test-mojom",
     "remote_unittest.test-mojom",
@@ -148,9 +148,7 @@
     "struct_headers_unittest.test-mojom",
   ]
 
-  public_deps = [
-    "//mojo/public/mojom/base",
-  ]
+  public_deps = [ "//mojo/public/mojom/base" ]
 
   support_lazy_serialization = true
 }
@@ -158,9 +156,7 @@
 source_set("perftests") {
   testonly = true
 
-  sources = [
-    "bindings_perftest.cc",
-  ]
+  sources = [ "bindings_perftest.cc" ]
 
   if (!is_ios) {
     sources += [ "e2e_perftest.cc" ]
@@ -184,7 +180,5 @@
     "validation_test_input_parser.h",
   ]
 
-  deps = [
-    "//mojo/public/c/system",
-  ]
+  deps = [ "//mojo/public/c/system" ]
 }
diff --git a/mojo/public/cpp/bindings/tests/flush_async_unittest.cc b/mojo/public/cpp/bindings/tests/flush_async_unittest.cc
new file mode 100644
index 0000000..9dcbe7d
--- /dev/null
+++ b/mojo/public/cpp/bindings/tests/flush_async_unittest.cc
@@ -0,0 +1,451 @@
+// 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 <memory>
+#include <utility>
+#include <vector>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/memory/ref_counted.h"
+#include "base/optional.h"
+#include "base/synchronization/lock.h"
+#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
+#include "mojo/public/cpp/bindings/async_flusher.h"
+#include "mojo/public/cpp/bindings/pending_flush.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
+#include "mojo/public/cpp/bindings/tests/flush_async_unittest.test-mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace test {
+namespace flush_async_unittest {
+
+// This implementation binds its receiver on an arbitrary ThreadPool task
+// runner. Any incoming Writer receivers are in turn bound on arbitrary (and
+// potentially different) ThreadPool task runners. There is therefore no general
+// ordering guarantee regarding message dispatch among each bound interface,
+// yielding generally racy behavior.
+//
+// This allows tests to reliably verify correctness of async flushing behavior.
+class KeyValueStoreImpl : public base::RefCountedThreadSafe<KeyValueStoreImpl>,
+                          public mojom::KeyValueStore {
+ public:
+  KeyValueStoreImpl()
+      : task_runner_(base::CreateSequencedTaskRunner({base::ThreadPool()})) {}
+
+  void Bind(PendingReceiver<mojom::KeyValueStore> receiver) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&KeyValueStoreImpl::BindOnTaskRunner, this,
+                                  std::move(receiver)));
+  }
+
+  void ShutDown(base::OnceClosure callback) {
+    task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&KeyValueStoreImpl::ShutDownOnTaskRunner,
+                                  this, std::move(callback)));
+  }
+
+  void StoreValue(const std::string& key, const std::string& value) {
+    base::AutoLock locker(lock_);
+    contents_[key] = value;
+  }
+
+ private:
+  friend class base::RefCountedThreadSafe<KeyValueStoreImpl>;
+
+  class WriterImpl : public mojom::Writer {
+   public:
+    WriterImpl(KeyValueStoreImpl* key_value_store)
+        : task_runner_(base::CreateSequencedTaskRunner({base::ThreadPool()})),
+          key_value_store_(key_value_store) {}
+    ~WriterImpl() override = default;
+
+    void Bind(PendingReceiver<mojom::Writer> receiver) {
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&WriterImpl::BindOnTaskRunner, base::Unretained(this),
+                         std::move(receiver)));
+    }
+
+    void ShutDown(base::OnceClosure callback) {
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&WriterImpl::ShutDownOnTaskRunner,
+                         base::Unretained(this), std::move(callback)));
+    }
+
+    // mojom::Writer implementation:
+    void Put(const std::string& key, const std::string& value) override {
+      key_value_store_->StoreValue(key, value);
+    }
+
+   private:
+    void BindOnTaskRunner(PendingReceiver<mojom::Writer> receiver) {
+      receiver_ =
+          std::make_unique<Receiver<mojom::Writer>>(this, std::move(receiver));
+    }
+
+    void ShutDownOnTaskRunner(base::OnceClosure callback) {
+      receiver_.reset();
+      std::move(callback).Run();
+    }
+
+    const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+    KeyValueStoreImpl* const key_value_store_;
+    std::unique_ptr<Receiver<mojom::Writer>> receiver_;
+  };
+
+  void BindOnTaskRunner(PendingReceiver<mojom::KeyValueStore> receiver) {
+    receiver_ = std::make_unique<Receiver<mojom::KeyValueStore>>(
+        this, std::move(receiver));
+  }
+
+  void ShutDownOnTaskRunner(base::OnceClosure callback) {
+    receiver_.reset();
+    client_.reset();
+
+    // Shutdown all WriterImpls too.
+    auto shutdown = base::BarrierClosure(writers_.size(), std::move(callback));
+    for (auto& writer : writers_)
+      writer->ShutDown(base::BindOnce(shutdown));
+  }
+
+  // mojom::KeyValueStore implementation:
+  void SetClient(PendingRemote<mojom::KeyValueStoreClient> client) override {
+    client_.Bind(std::move(client));
+  }
+
+  void BindWriter(PendingReceiver<mojom::Writer> receiver) override {
+    // NOTE: Each WriterImpl internally binds on an arbitrary ThreadPool task
+    // runner, leaving us with no ordering guarantee among Writers with respect
+    // to each other or this KeyValueStore.
+    auto new_writer = std::make_unique<WriterImpl>(this);
+    new_writer->Bind(std::move(receiver));
+    writers_.push_back(std::move(new_writer));
+  }
+
+  void GetSnapshot(GetSnapshotCallback callback) override {
+    base::AutoLock locker(lock_);
+    std::move(callback).Run(contents_);
+
+    // If we have a client, notify it that a snapshot was taken, but ensure that
+    // it doesn't dispatch that notification until the above callback is
+    // dispatched. Then also ensure that our remote doesn't receiver any
+    // subsequent callbacks until the client processes this |OnSnapshotTaken()|.
+    if (client_) {
+      client_.PauseReceiverUntilFlushCompletes(receiver_->FlushAsync());
+      client_->OnSnapshotTaken();
+      receiver_->PauseRemoteCallbacksUntilFlushCompletes(client_.FlushAsync());
+    }
+  }
+
+  ~KeyValueStoreImpl() override = default;
+
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  std::unique_ptr<Receiver<mojom::KeyValueStore>> receiver_;
+  Remote<mojom::KeyValueStoreClient> client_;
+  std::vector<std::unique_ptr<WriterImpl>> writers_;
+  base::Lock lock_;
+  base::flat_map<std::string, std::string> contents_;
+};
+
+class FlushAsyncTest : public BindingsTestBase {
+ public:
+  FlushAsyncTest() {
+    key_value_store_->Bind(
+        remote_key_value_store_.BindNewPipeAndPassReceiver());
+  }
+
+  void TearDown() override {
+    base::RunLoop wait_for_clean_shutdown;
+    key_value_store_->ShutDown(wait_for_clean_shutdown.QuitClosure());
+    wait_for_clean_shutdown.Run();
+  }
+
+  Remote<mojom::KeyValueStore>& key_value_store() {
+    return remote_key_value_store_;
+  }
+
+  Remote<mojom::Writer> MakeWriter() {
+    Remote<mojom::Writer> writer;
+    key_value_store()->BindWriter(writer.BindNewPipeAndPassReceiver());
+    return writer;
+  }
+
+ private:
+  Remote<mojom::KeyValueStore> remote_key_value_store_;
+  scoped_refptr<KeyValueStoreImpl> key_value_store_{
+      base::MakeRefCounted<KeyValueStoreImpl>()};
+};
+
+TEST_P(FlushAsyncTest, WaitForMultipleFlushes) {
+  const std::string kKey1 = "bar";
+  const std::string kKey2 = "foo";
+  const std::string kValue1 = "42";
+  const std::string kValue2 = "37";
+
+  Remote<mojom::Writer> writer1 = MakeWriter();
+  Remote<mojom::Writer> writer2 = MakeWriter();
+  writer1->Put(kKey1, kValue1);
+  writer2->Put(kKey2, kValue2);
+
+  // Both |Put()| calls must be received by the time |GetSnapshot()| is
+  // dispatched.
+  base::flat_map<std::string, std::string> snapshot;
+  base::RunLoop loop;
+  key_value_store().PauseReceiverUntilFlushCompletes(writer1.FlushAsync());
+  key_value_store().PauseReceiverUntilFlushCompletes(writer2.FlushAsync());
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>& contents) {
+        snapshot = contents;
+        loop.Quit();
+      }));
+  loop.Run();
+
+  EXPECT_EQ(2u, snapshot.size());
+  EXPECT_EQ(kValue1, snapshot[kKey1]);
+  EXPECT_EQ(kValue2, snapshot[kKey2]);
+}
+
+TEST_P(FlushAsyncTest, MultipleFlushesInSequence) {
+  const std::string kKey1 = "foo";
+  const std::string kKey2 = "bar";
+  const std::string kKey3 = "baz";
+  const std::string kValue1 = "1";
+  const std::string kValue2 = "2";
+  const std::string kValue3 = "3";
+
+  Remote<mojom::Writer> writer1 = MakeWriter();
+  Remote<mojom::Writer> writer2 = MakeWriter();
+  writer1->Put(kKey1, kValue1);
+  writer1.FlushForTesting();
+
+  // Pause each Writer until the |GetSnapshot()| call below has executed,
+  // ensuring that the snapshot never reflects the result of the |Put()| calls
+  // below.
+  base::RunLoop loop;
+  base::flat_map<std::string, std::string> snapshot;
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>& contents) {
+        snapshot = contents;
+        loop.Quit();
+      }));
+  writer1.PauseReceiverUntilFlushCompletes(key_value_store().FlushAsync());
+  writer2.PauseReceiverUntilFlushCompletes(key_value_store().FlushAsync());
+  writer1->Put(kKey2, kValue2);
+  writer2->Put(kKey3, kValue3);
+  loop.Run();
+
+  EXPECT_EQ(1u, snapshot.size());
+  EXPECT_EQ(kValue1, snapshot[kKey1]);
+}
+
+TEST_P(FlushAsyncTest, DroppedFlusherCompletesPendingFlush) {
+  const std::string kKey = "foo";
+  const std::string kValue = "bar";
+  Remote<mojom::Writer> writer = MakeWriter();
+  writer->Put(kKey, kValue);
+  writer.FlushForTesting();
+
+  // Pause the KeyValueStore to block |GetSnapshot()|, but drop the
+  // corresponding AsyncFlusher. The call should eventually execute.
+  base::RunLoop loop;
+  base::flat_map<std::string, std::string> snapshot;
+  base::Optional<AsyncFlusher> flusher(base::in_place);
+  key_value_store().PauseReceiverUntilFlushCompletes(
+      PendingFlush(&flusher.value()));
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>& contents) {
+        snapshot = contents;
+        loop.Quit();
+      }));
+  flusher.reset();
+  loop.Run();
+
+  EXPECT_EQ(1u, snapshot.size());
+  EXPECT_EQ(kValue, snapshot[kKey]);
+}
+
+class PingerImpl : public mojom::Pinger {
+ public:
+  explicit PingerImpl(PendingReceiver<mojom::Pinger> receiver)
+      : receiver_(this, std::move(receiver)) {}
+  ~PingerImpl() override = default;
+
+  Receiver<mojom::Pinger>& receiver() { return receiver_; }
+
+  // mojom::Pinger implementation:
+  void Ping(PingCallback callback) override { std::move(callback).Run(); }
+
+ private:
+  Receiver<mojom::Pinger> receiver_;
+};
+
+TEST_P(FlushAsyncTest, PausedInterfaceDoesNotAutoResumeOnFlush) {
+  // Verifies that if a receiver is implicitly paused via a remote call to
+  // |PauseReceiverUntilFlushCompletes()|, but also explicitly paused by its
+  // owner calling |Pause()|, it does not auto-resume when the flush completes.
+
+  Remote<mojom::Pinger> pinger;
+  PingerImpl impl(pinger.BindNewPipeAndPassReceiver());
+
+  base::Optional<AsyncFlusher> flusher(base::in_place);
+  PendingFlush flush(&flusher.value());
+  pinger.PauseReceiverUntilFlushCompletes(std::move(flush));
+
+  // Allow the receiver to become implicitly paused as a result of the above
+  // call. Using |RunUntilIdle()| is safe here since this is a simple unit test
+  // and we are only concerned with activity on the calling sequence.
+  base::RunLoop().RunUntilIdle();
+
+  // We should not see a reply until the receiver is unpaused.
+  bool got_reply = false;
+  base::RunLoop ping_loop;
+  pinger->Ping(base::BindLambdaForTesting([&] {
+    ping_loop.Quit();
+    got_reply = true;
+  }));
+
+  // Explicitly pause the receiver and complete the AsyncFlusher.
+  impl.receiver().Pause();
+  flusher.reset();
+
+  // Ensure that any asynchronous side-effects of resetting the AsyncFlusher
+  // have a chance to execute.
+  base::RunLoop().RunUntilIdle();
+
+  // The receiver should still be paused despite the flush completing, because
+  // we haven't called an explicit |Resume()| to match the explicit |Pause()|
+  // above.
+  EXPECT_FALSE(got_reply);
+
+  // Now allow it to resume and verify that everything's cool.
+  impl.receiver().Resume();
+  ping_loop.Run();
+  EXPECT_TRUE(got_reply);
+}
+
+TEST_P(FlushAsyncTest, ResumeDoesNotInterruptWaitingOnFlush) {
+  // Verifies that an explicit |Resume()| does not actually resume message
+  // processing if the endpoint is still waiting on an asynchronous flush
+  // operation.
+
+  Remote<mojom::Pinger> pinger;
+  PingerImpl impl(pinger.BindNewPipeAndPassReceiver());
+
+  base::Optional<AsyncFlusher> flusher(base::in_place);
+  PendingFlush flush(&flusher.value());
+  pinger.PauseReceiverUntilFlushCompletes(std::move(flush));
+
+  // Allow the receiver to become implicitly paused as a result of the above
+  // call. Using |RunUntilIdle()| is safe here since this is a simple unit test
+  // and we are only concerned with activity on the calling sequence.
+  base::RunLoop().RunUntilIdle();
+
+  // We should not see a reply until the receiver is unpaused.
+  bool got_reply = false;
+  base::RunLoop ping_loop;
+  pinger->Ping(base::BindLambdaForTesting([&] {
+    ping_loop.Quit();
+    got_reply = true;
+  }));
+
+  // Explicitly resume the receiver and let tasks settle. There should still be
+  // no reply, because |flusher| is still active and the receiver is waiting on
+  // it to complete.
+  impl.receiver().Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(got_reply);
+
+  // Now allow the flush to complete and verify that the receiver is unblocked.
+  flusher.reset();
+  ping_loop.Run();
+  EXPECT_TRUE(got_reply);
+}
+
+class KeyValueStoreClientImpl : public mojom::KeyValueStoreClient {
+ public:
+  explicit KeyValueStoreClientImpl(
+      PendingReceiver<mojom::KeyValueStoreClient> receiver)
+      : receiver_(this, std::move(receiver)) {}
+  ~KeyValueStoreClientImpl() override = default;
+
+  Receiver<mojom::KeyValueStoreClient>& receiver() { return receiver_; }
+
+  void set_snapshot_taken_callback(base::RepeatingClosure callback) {
+    snapshot_taken_callback_ = std::move(callback);
+  }
+
+  // mojom::KeyValueStoreClient implementation:
+  void OnSnapshotTaken() override {
+    if (snapshot_taken_callback_)
+      snapshot_taken_callback_.Run();
+  }
+
+ private:
+  Receiver<mojom::KeyValueStoreClient> receiver_;
+  base::RepeatingClosure snapshot_taken_callback_;
+};
+
+TEST_P(FlushAsyncTest, PauseRemote) {
+  // Smoke test to exercise the async flushing APIs on a Receiver to pause
+  // callback dispatch on its corresponding Remote. |GetSnapshot()| replies are
+  // strictly ordered against corresponding calls to |OnSnapshotTaken()| on the
+  // client interface. This is enforced entirely by logic in
+  // |KeyValueStoreImpl::GetSnapshot()| using async flush operations.
+
+  PendingRemote<mojom::KeyValueStoreClient> client;
+  KeyValueStoreClientImpl impl(client.InitWithNewPipeAndPassReceiver());
+  key_value_store()->SetClient(std::move(client));
+
+  int num_replies = 0;
+  int num_client_calls = 0;
+
+  // Any time the client gets an |OnSnapshotTaken()| call, it should be able
+  // to rely on the corresponding |GetSnapshot()| reply having already been
+  // dispatched.
+  impl.set_snapshot_taken_callback(base::BindLambdaForTesting([&] {
+    EXPECT_EQ(num_replies, num_client_calls + 1);
+    ++num_client_calls;
+  }));
+
+  // Perform a few trial snapshots. All replies should be dispatched after any
+  // previous snapshot's client notification, but before its own corresponding
+  // client notification.
+  base::RunLoop loop;
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>&) {
+        EXPECT_EQ(0, num_replies);
+        EXPECT_EQ(0, num_client_calls);
+        ++num_replies;
+      }));
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>&) {
+        EXPECT_EQ(1, num_replies);
+        EXPECT_EQ(1, num_client_calls);
+        ++num_replies;
+      }));
+  key_value_store()->GetSnapshot(base::BindLambdaForTesting(
+      [&](const base::flat_map<std::string, std::string>&) {
+        EXPECT_EQ(2, num_replies);
+        EXPECT_EQ(2, num_client_calls);
+        ++num_replies;
+        loop.Quit();
+      }));
+  loop.Run();
+}
+
+INSTANTIATE_MOJO_BINDINGS_TEST_SUITE_P(FlushAsyncTest);
+
+}  // namespace flush_async_unittest
+}  // namespace test
+}  // namespace mojo
diff --git a/mojo/public/cpp/bindings/tests/flush_async_unittest.test-mojom b/mojo/public/cpp/bindings/tests/flush_async_unittest.test-mojom
new file mode 100644
index 0000000..c9c74e4
--- /dev/null
+++ b/mojo/public/cpp/bindings/tests/flush_async_unittest.test-mojom
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo.test.flush_async_unittest.mojom;
+
+interface Writer {
+  Put(string key, string value);
+};
+
+interface KeyValueStoreClient {
+  OnSnapshotTaken();
+};
+
+interface KeyValueStore {
+  SetClient(pending_remote<KeyValueStoreClient> client);
+  BindWriter(pending_receiver<Writer> receiver);
+  GetSnapshot() => (map<string, string> entries);
+};
+
+interface Pinger { Ping() => (); };
diff --git a/mojo/public/interfaces/bindings/pipe_control_messages.mojom b/mojo/public/interfaces/bindings/pipe_control_messages.mojom
index 74e9cc7..052e2e6d 100644
--- a/mojo/public/interfaces/bindings/pipe_control_messages.mojom
+++ b/mojo/public/interfaces/bindings/pipe_control_messages.mojom
@@ -25,6 +25,8 @@
 
 union RunOrClosePipeInput {
   PeerAssociatedEndpointClosedEvent peer_associated_endpoint_closed_event;
+  PauseUntilFlushCompletes pause_until_flush_completes;
+  FlushAsync flush_async;
 };
 
 // A user-defined reason about why the interface is disconnected.
@@ -44,3 +46,16 @@
   DisconnectReason? disconnect_reason;
 };
 
+// Sent to an endpoint to pause its message dispatch. |flush_pipe| is
+// monitored asynchronously for peer closure. Once its peer is closed, the
+// endpoint unpauses.
+struct PauseUntilFlushCompletes {
+  handle<message_pipe> flush_pipe;
+};
+
+// Sent to an endpoint so that the flush operation corresponding to
+// |flusher_pipe| is signaled by the endpoint's receipt of this message.
+struct FlushAsync {
+  handle<message_pipe> flusher_pipe;
+};
+
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn
index ca54108..f6d2e8b 100644
--- a/net/dns/BUILD.gn
+++ b/net/dns/BUILD.gn
@@ -117,9 +117,7 @@
     }
   }
 
-  deps = [
-    "//net:net_deps",
-  ]
+  deps = [ "//net:net_deps" ]
 
   public_deps = [
     ":dns_client",
@@ -208,9 +206,7 @@
     "//net:net_deps",
     "//net/dns/public",
   ]
-  public_deps = [
-    "//net:net_public_deps",
-  ]
+  public_deps = [ "//net:net_public_deps" ]
 }
 
 # Shared mostly-global handler of HostResolver requests.
@@ -256,9 +252,7 @@
     "//net:net_deps",
     "//net/dns/public",
   ]
-  public_deps = [
-    "//net:net_public_deps",
-  ]
+  public_deps = [ "//net:net_public_deps" ]
 }
 
 # DnsClient interfaces. Primarily intended as part of the implementation of the
@@ -370,9 +364,7 @@
     ":host_resolver",
     "//net:net_deps",
   ]
-  public_deps = [
-    "//net:net_public_deps",
-  ]
+  public_deps = [ "//net:net_public_deps" ]
 }
 
 source_set("tests") {
@@ -481,9 +473,7 @@
 }
 
 fuzzer_test("net_dns_hosts_parse_fuzzer") {
-  sources = [
-    "dns_hosts_parse_fuzzer.cc",
-  ]
+  sources = [ "dns_hosts_parse_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -493,9 +483,7 @@
 }
 
 fuzzer_test("net_dns_record_fuzzer") {
-  sources = [
-    "dns_record_fuzzer.cc",
-  ]
+  sources = [ "dns_record_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -505,9 +493,7 @@
 }
 
 fuzzer_test("net_dns_query_parse_fuzzer") {
-  sources = [
-    "dns_query_parse_fuzzer.cc",
-  ]
+  sources = [ "dns_query_parse_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -517,9 +503,7 @@
 }
 
 fuzzer_test("net_dns_response_fuzzer") {
-  sources = [
-    "dns_response_fuzzer.cc",
-  ]
+  sources = [ "dns_response_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -529,9 +513,7 @@
 }
 
 fuzzer_test("net_host_resolver_manager_fuzzer") {
-  sources = [
-    "host_resolver_manager_fuzzer.cc",
-  ]
+  sources = [ "host_resolver_manager_fuzzer.cc" ]
   deps = [
     "//base",
     "//net",
@@ -543,9 +525,7 @@
 
 if (is_win) {
   fuzzer_test("net_dns_parse_domain_ascii_win_fuzzer") {
-    sources = [
-      "dns_parse_domain_ascii_win_fuzzer.cc",
-    ]
+    sources = [ "dns_parse_domain_ascii_win_fuzzer.cc" ]
     deps = [
       "//base",
       "//net",
diff --git a/net/dns/public/BUILD.gn b/net/dns/public/BUILD.gn
index e1ce365..46cf709 100644
--- a/net/dns/public/BUILD.gn
+++ b/net/dns/public/BUILD.gn
@@ -23,11 +23,7 @@
     "util.h",
   ]
 
-  deps = [
-    "//net:net_deps",
-  ]
+  deps = [ "//net:net_deps" ]
 
-  public_deps = [
-    "//net:net_public_deps",
-  ]
+  public_deps = [ "//net:net_public_deps" ]
 }
diff --git a/remoting/host/chromeos/message_box.cc b/remoting/host/chromeos/message_box.cc
index df543e6..bb2ad98 100644
--- a/remoting/host/chromeos/message_box.cc
+++ b/remoting/host/chromeos/message_box.cc
@@ -42,14 +42,15 @@
   ui::ModalType GetModalType() const override;
   base::string16 GetWindowTitle() const override;
   views::View* GetContentsView() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
   void DeleteDelegate() override;
 
   // Called by MessageBox::Core when it is destroyed.
   void OnMessageBoxDestroyed();
 
  private:
+  // views::DialogDelegateView:
+  const views::Widget* GetWidgetImpl() const override;
+
   const base::string16 title_label_;
   ResultCallback result_callback_;
   MessageBox* message_box_;
@@ -120,14 +121,6 @@
   return message_box_view_;
 }
 
-views::Widget* MessageBox::Core::GetWidget() {
-  return message_box_view_->GetWidget();
-}
-
-const views::Widget* MessageBox::Core::GetWidget() const {
-  return message_box_view_->GetWidget();
-}
-
 void MessageBox::Core::DeleteDelegate() {
   if (message_box_) {
     message_box_->core_ = nullptr;
@@ -142,6 +135,10 @@
   result_callback_.Reset();
 }
 
+const views::Widget* MessageBox::Core::GetWidgetImpl() const {
+  return message_box_view_->GetWidget();
+}
+
 MessageBox::MessageBox(const base::string16& title_label,
                        const base::string16& message_label,
                        const base::string16& ok_label,
diff --git a/rlz/BUILD.gn b/rlz/BUILD.gn
index 8f8531a9..e408b17b 100644
--- a/rlz/BUILD.gn
+++ b/rlz/BUILD.gn
@@ -27,13 +27,9 @@
     "lib/string_utils.h",
   ]
 
-  public_deps = [
-    "//base",
-  ]
+  public_deps = [ "//base" ]
 
-  deps = [
-    "//third_party/zlib",
-  ]
+  deps = [ "//third_party/zlib" ]
 }
 
 if (!is_android) {
@@ -159,9 +155,7 @@
       "//base/test:test_support",
       "//testing/gtest",
     ]
-    deps = [
-      ":rlz_lib",
-    ]
+    deps = [ ":rlz_lib" ]
     if (is_chromeos) {
       public_deps += [ "//chromeos/system" ]
     }
@@ -206,9 +200,7 @@
 
 if (!is_ios && !is_android) {
   executable("rlz_id") {
-    sources = [
-      "examples/rlz_id.cc",
-    ]
+    sources = [ "examples/rlz_id.cc" ]
     deps = [
       ":rlz_lib",
       "//build/win:default_exe_manifest",
diff --git a/sandbox/BUILD.gn b/sandbox/BUILD.gn
index 81e7aff..9de38b4a 100644
--- a/sandbox/BUILD.gn
+++ b/sandbox/BUILD.gn
@@ -9,23 +9,17 @@
 # Several targets want to include this header file. We separate it out
 # here so multiple targets can depend on it.
 source_set("sandbox_export") {
-  sources = [
-    "sandbox_export.h",
-  ]
+  sources = [ "sandbox_export.h" ]
 }
 
 source_set("common") {
-  sources = [
-    "constants.h",
-  ]
+  sources = [ "constants.h" ]
 }
 
 # Meta-target that forwards to the proper platform one.
 group("sandbox") {
   if (is_win) {
-    public_deps = [
-      "//sandbox/win:sandbox",
-    ]
+    public_deps = [ "//sandbox/win:sandbox" ]
   } else if (is_mac) {
     public_deps = [
       "//sandbox/mac:seatbelt",
@@ -34,9 +28,7 @@
       "//sandbox/mac/mojom",
     ]
   } else if (is_linux || is_android) {
-    public_deps = [
-      "//sandbox/linux:sandbox",
-    ]
+    public_deps = [ "//sandbox/linux:sandbox" ]
   }
 }
 
@@ -61,9 +53,7 @@
   if (!is_win) {
     defines = [ "SANDBOX_FUZZ_TARGET" ]
   }
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
   dict = "ipc.dict"
   libfuzzer_options = [ "max_len=1024" ]
 }
diff --git a/sandbox/features.gni b/sandbox/features.gni
index 89693c5..09280d3 100644
--- a/sandbox/features.gni
+++ b/sandbox/features.gni
@@ -8,10 +8,9 @@
 # currently.
 # Do not disable seccomp_bpf anywhere without talking to
 # security@chromium.org!
-use_seccomp_bpf =
-    (is_linux || is_android) &&
-    (current_cpu == "x86" || current_cpu == "x64" || current_cpu == "arm" ||
-     current_cpu == "arm64" || current_cpu == "mipsel" ||
-     current_cpu == "mips64el")
+use_seccomp_bpf = (is_linux || is_android) &&
+                  (current_cpu == "x86" || current_cpu == "x64" ||
+                   current_cpu == "arm" || current_cpu == "arm64" ||
+                   current_cpu == "mipsel" || current_cpu == "mips64el")
 
 use_seccomp_bpf = use_seccomp_bpf || is_nacl_nonsfi
diff --git a/services/device/power_monitor/BUILD.gn b/services/device/power_monitor/BUILD.gn
index b21f645..244e137 100644
--- a/services/device/power_monitor/BUILD.gn
+++ b/services/device/power_monitor/BUILD.gn
@@ -17,7 +17,5 @@
     "//mojo/public/cpp/bindings",
   ]
 
-  public_deps = [
-    "//services/device/public/mojom",
-  ]
+  public_deps = [ "//services/device/public/mojom" ]
 }
diff --git a/services/device/time_zone_monitor/BUILD.gn b/services/device/time_zone_monitor/BUILD.gn
index 0240580..440344d3 100644
--- a/services/device/time_zone_monitor/BUILD.gn
+++ b/services/device/time_zone_monitor/BUILD.gn
@@ -29,9 +29,7 @@
     "//third_party/icu",
   ]
 
-  public_deps = [
-    "//services/device/public/mojom",
-  ]
+  public_deps = [ "//services/device/public/mojom" ]
 
   if (is_android) {
     deps += [ ":time_zone_monitor_jni_headers" ]
@@ -57,9 +55,7 @@
 if (is_android) {
   generate_jni("time_zone_monitor_jni_headers") {
     visibility = [ ":time_zone_monitor" ]
-    sources = [
-      "android/java/src/org/chromium/device/time_zone_monitor/TimeZoneMonitor.java",
-    ]
+    sources = [ "android/java/src/org/chromium/device/time_zone_monitor/TimeZoneMonitor.java" ]
   }
 
   android_library("java") {
@@ -67,9 +63,7 @@
     # However, various generated targets also need to see this target as a
     # result of //services/device:java depending on it.
     visibility = [ "//services/device:*" ]
-    sources = [
-      "android/java/src/org/chromium/device/time_zone_monitor/TimeZoneMonitor.java",
-    ]
+    sources = [ "android/java/src/org/chromium/device/time_zone_monitor/TimeZoneMonitor.java" ]
     deps = [
       "//base:base_java",
       "//base:jni_java",
diff --git a/services/device/usb/BUILD.gn b/services/device/usb/BUILD.gn
index e92d6cde..fc390a0b 100644
--- a/services/device/usb/BUILD.gn
+++ b/services/device/usb/BUILD.gn
@@ -145,15 +145,11 @@
     "//testing/gtest",
   ]
 
-  public_deps = [
-    "//testing/gmock",
-  ]
+  public_deps = [ "//testing/gmock" ]
 }
 
 fuzzer_test("webusb_descriptors_fuzzer") {
-  sources = [
-    "webusb_descriptors_fuzzer.cc",
-  ]
+  sources = [ "webusb_descriptors_fuzzer.cc" ]
   deps = [
     ":test_support",
     ":usb",
@@ -165,9 +161,7 @@
 }
 
 fuzzer_test("usb_descriptors_fuzzer") {
-  sources = [
-    "usb_descriptors_fuzzer.cc",
-  ]
+  sources = [ "usb_descriptors_fuzzer.cc" ]
   deps = [
     ":usb",
     "//mojo/public/cpp/bindings",
@@ -179,9 +173,7 @@
 }
 
 fuzzer_test("usb_string_read_fuzzer") {
-  sources = [
-    "usb_string_read_fuzzer.cc",
-  ]
+  sources = [ "usb_string_read_fuzzer.cc" ]
   deps = [
     ":test_support",
     ":usb",
diff --git a/services/preferences/public/cpp/tracked/BUILD.gn b/services/preferences/public/cpp/tracked/BUILD.gn
index 8385447..3b249c3a 100644
--- a/services/preferences/public/cpp/tracked/BUILD.gn
+++ b/services/preferences/public/cpp/tracked/BUILD.gn
@@ -11,12 +11,8 @@
     "tracked_preference_histogram_names.cc",
     "tracked_preference_histogram_names.h",
   ]
-  public_deps = [
-    "//services/preferences/public/mojom",
-  ]
-  deps = [
-    "//base",
-  ]
+  public_deps = [ "//services/preferences/public/mojom" ]
+  deps = [ "//base" ]
 }
 
 static_library("test_support") {
diff --git a/services/service_manager/sandbox/mac/BUILD.gn b/services/service_manager/sandbox/mac/BUILD.gn
index c8e2fe8..0ebb1c0 100644
--- a/services/service_manager/sandbox/mac/BUILD.gn
+++ b/services/service_manager/sandbox/mac/BUILD.gn
@@ -30,7 +30,5 @@
 source_set("packaged_sb_files") {
   sources = get_target_outputs(":package_sb_files")
   defines = [ "SERVICE_MANAGER_SANDBOX_IMPL" ]
-  deps = [
-    ":package_sb_files",
-  ]
+  deps = [ ":package_sb_files" ]
 }
diff --git a/testing/buildbot/filters/e2e.sync_integration_tests.filter b/testing/buildbot/filters/e2e.sync_integration_tests.filter
index 07d129eb..4dbaf62 100644
--- a/testing/buildbot/filters/e2e.sync_integration_tests.filter
+++ b/testing/buildbot/filters/e2e.sync_integration_tests.filter
@@ -1,13 +1,5 @@
 # TODO(crbug.com/1010568): Enable all sync e2e tests.

 -TwoClientDictionarySyncTest.RemoveOnAAddOnB_E2ETest

--TwoClientExtensionAppsSyncTest*

--TwoClientExtensionsSyncTest.UpdateEnableDisableExtension_E2ETest

--TwoClientExtensionsSyncTest.UpdateIncognitoEnableDisable_E2ETest

--TwoClientExtensionsSyncTest.InstallDifferentExtensions_E2ETest

--TwoClientExtensionsSyncTest.StartWithDifferentExtensions_E2ETest

--TwoClientExtensionsSyncTest.StartWithSameExtensions_E2ETest

--TwoClientExtensionsSyncTest.UninstallPreinstalledExtensions_E2ETest

--TwoClientExtensionsSyncTest.Uninstall_E2ETest

 -USS/TwoClientPasswordsSyncTest*

 -TwoClientSearchEnginesSyncTest.DeleteSyncedDefault_E2ETest

 -TwoClientSearchEnginesSyncTest.Delete_E2ETest

diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 13d1704..edd48c8 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4700,7 +4700,7 @@
 Node* Element::InsertAdjacent(const String& where,
                               Node* new_child,
                               ExceptionState& exception_state) {
-  if (DeprecatedEqualIgnoringCase(where, "beforeBegin")) {
+  if (EqualIgnoringASCIICase(where, "beforeBegin")) {
     if (ContainerNode* parent = parentNode()) {
       parent->InsertBefore(new_child, this, exception_state);
       if (!exception_state.HadException())
@@ -4709,17 +4709,17 @@
     return nullptr;
   }
 
-  if (DeprecatedEqualIgnoringCase(where, "afterBegin")) {
+  if (EqualIgnoringASCIICase(where, "afterBegin")) {
     InsertBefore(new_child, firstChild(), exception_state);
     return exception_state.HadException() ? nullptr : new_child;
   }
 
-  if (DeprecatedEqualIgnoringCase(where, "beforeEnd")) {
+  if (EqualIgnoringASCIICase(where, "beforeEnd")) {
     AppendChild(new_child, exception_state);
     return exception_state.HadException() ? nullptr : new_child;
   }
 
-  if (DeprecatedEqualIgnoringCase(where, "afterEnd")) {
+  if (EqualIgnoringASCIICase(where, "afterEnd")) {
     if (ContainerNode* parent = parentNode()) {
       parent->InsertBefore(new_child, nextSibling(), exception_state);
       if (!exception_state.HadException())
diff --git a/third_party/blink/renderer/modules/background_fetch/BUILD.gn b/third_party/blink/renderer/modules/background_fetch/BUILD.gn
index b186dbf..27e1392c 100644
--- a/third_party/blink/renderer/modules/background_fetch/BUILD.gn
+++ b/third_party/blink/renderer/modules/background_fetch/BUILD.gn
@@ -27,7 +27,5 @@
     "service_worker_registration_background_fetch.h",
   ]
 
-  public_deps = [
-    "//third_party/blink/renderer/modules/service_worker",
-  ]
+  public_deps = [ "//third_party/blink/renderer/modules/service_worker" ]
 }
diff --git a/third_party/blink/renderer/modules/device_orientation/BUILD.gn b/third_party/blink/renderer/modules/device_orientation/BUILD.gn
index 3a8e13d..667b4328 100644
--- a/third_party/blink/renderer/modules/device_orientation/BUILD.gn
+++ b/third_party/blink/renderer/modules/device_orientation/BUILD.gn
@@ -37,7 +37,5 @@
     "dom_window_device_motion.h",
     "dom_window_device_orientation.h",
   ]
-  deps = [
-    "//services/device/public/mojom:generic_sensor",
-  ]
+  deps = [ "//services/device/public/mojom:generic_sensor" ]
 }
diff --git a/third_party/blink/renderer/modules/notifications/BUILD.gn b/third_party/blink/renderer/modules/notifications/BUILD.gn
index 51776ed..97145af 100644
--- a/third_party/blink/renderer/modules/notifications/BUILD.gn
+++ b/third_party/blink/renderer/modules/notifications/BUILD.gn
@@ -22,7 +22,6 @@
     "timestamp_trigger.cc",
     "timestamp_trigger.h",
   ]
-  deps = [
-    "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
-  ]
+  deps =
+      [ "//services/resource_coordinator/public/cpp:resource_coordinator_cpp" ]
 }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index 70abbde..0680de7 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -29,12 +29,15 @@
 #include <utility>
 
 #include "base/location.h"
+#include "base/numerics/checked_math.h"
 #include "base/rand_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/timer/elapsed_timer.h"
+#include "cc/base/region.h"
 #include "cc/layers/texture_layer.h"
 #include "components/viz/common/resources/transferable_resource.h"
 #include "gpu/command_buffer/client/raster_interface.h"
+#include "ui/gfx/geometry/size.h"
 
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -56,6 +59,52 @@
 
 namespace blink {
 
+namespace {
+// Canvas with an area less than 256 pixel by 256 pixel are considered too small
+// for partial repaint instead of full repaint.
+constexpr int kMinAreaForComputingDirtyRegion = 256 * 256;
+
+// Returns true if the area defined by |width| and |height| are dirty; false
+// otherwise.
+bool GatherDirtyRect(const cc::PaintOpBuffer* buffer,
+                     cc::InvalidationRegion* dirty_region,
+                     SkNoDrawCanvas* canvas,
+                     SkScalar width,
+                     SkScalar height) {
+  // Prevent PaintOpBuffers from having side effects back into the canvas.
+  SkAutoCanvasRestore save_restore(canvas, true);
+
+  cc::PlaybackParams params(nullptr, canvas->getTotalMatrix());
+  for (auto* op : cc::PaintOpBuffer::Iterator(buffer)) {
+    // Note that the dirty from SaveLayer will not computed until the next draw
+    // op. Since there is alawys a draw op between SaveLayer and Restore, this
+    // approach does the computation correctly.
+    if (!op->IsDrawOp()) {
+      op->Raster(canvas, params);
+      continue;
+    }
+    if (static_cast<cc::PaintOpType>(op->type) == cc::PaintOpType::DrawRecord) {
+      sk_sp<const PaintRecord> paint_record =
+          static_cast<cc::DrawRecordOp*>(op)->record;
+      if (GatherDirtyRect(paint_record.get(), dirty_region, canvas, width,
+                          height))
+        return true;
+    } else {
+      const SkRect& clip_rect = SkRect::Make(canvas->getDeviceClipBounds());
+      const SkMatrix& ctm = canvas->getTotalMatrix();
+      gfx::Rect rect = cc::PaintOp::ComputePaintRect(op, clip_rect, ctm);
+      dirty_region->Union(rect);
+      // If one draw op takes the entire canvas, stop compute for the dirty
+      // rect from the remaining draw ops.
+      if (rect.width() >= width && rect.height() >= height)
+        return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace
+
 Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
                                          AccelerationMode acceleration_mode,
                                          const CanvasColorParams& color_params)
@@ -471,6 +520,45 @@
     rate_limiter_->Reset();
 }
 
+void Canvas2DLayerBridge::CalculateDirtyRegion(int canvas_width,
+                                               int canvas_height) {
+  base::CheckedNumeric<int> area(canvas_width);
+  area *= canvas_height;
+  if (!area.IsValid() || area.ValueOrDie() < kMinAreaForComputingDirtyRegion)
+    return;
+  SkNoDrawCanvas no_draw_canvas(canvas_width, canvas_height);
+  dirty_invalidate_region_.Clear();
+
+  // If GatherDirtyRect returns true, the entire canvas is dirty. Record the
+  // percentage of dirty area in the canvas to 100 and skip the calculation.
+  if (GatherDirtyRect(last_recording_.get(), &dirty_invalidate_region_,
+                      &no_draw_canvas, canvas_width, canvas_height)) {
+    UMA_HISTOGRAM_PERCENTAGE("Canvas.Repaint.Region.Percentage", 100);
+    UMA_HISTOGRAM_PERCENTAGE("Canvas.Repaint.Bounds.Percentage", 100);
+  } else {
+    int valid_area = area.ValueOrDie();
+    base::CheckedNumeric<int> used_total = 0;
+    cc::Region dirty_region;
+    dirty_invalidate_region_.Swap(&dirty_region);
+    gfx::Rect bounds;
+    for (const gfx::Rect& rect : dirty_region) {
+      bounds.Union(rect);
+      used_total += rect.size().GetCheckedArea();
+    }
+    int ratio_region =
+        (static_cast<float>(used_total.ValueOrDefault(valid_area)) /
+         valid_area) *
+        100;
+    int ratio_rect =
+        (static_cast<float>(
+             bounds.size().GetCheckedArea().ValueOrDefault(valid_area)) /
+         valid_area) *
+        100;
+    UMA_HISTOGRAM_PERCENTAGE("Canvas.Repaint.Region.Percentage", ratio_region);
+    UMA_HISTOGRAM_PERCENTAGE("Canvas.Repaint.Bounds.Percentage", ratio_rect);
+  }
+}
+
 void Canvas2DLayerBridge::ClearPendingRasterTimers() {
   gpu::raster::RasterInterface* raster_interface = nullptr;
   if (IsAccelerated() && SharedGpuContext::ContextProviderWrapper() &&
@@ -567,10 +655,15 @@
     }
     timer.emplace();
   }
-
   {  // Make a new scope so that PaintRecord gets deleted and that gets timed
     cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
     last_recording_ = recorder_->finishRecordingAsPicture();
+    SkScalar canvas_width = canvas->getLocalClipBounds().width();
+    SkScalar canvas_height = canvas->getLocalClipBounds().height();
+    DCHECK_GE(canvas_width, size_.Width());
+    DCHECK_GE(canvas_height, size_.Height());
+    CalculateDirtyRegion(canvas_width, canvas_height);
+
     canvas->drawPicture(last_recording_);
     last_record_tainted_by_write_pixels_ = false;
     if (!clear_frame_ || !resource_host_ || !resource_host_->IsPrinting()) {
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
index d7f3344..16f73aa 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -35,6 +35,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/numerics/checked_math.h"
 #include "build/build_config.h"
+#include "cc/base/invalidation_region.h"
 #include "cc/layers/texture_layer_client.h"
 #include "components/viz/common/resources/transferable_resource.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -202,6 +203,7 @@
   void SkipQueuedDrawCommands();
 
   bool ShouldAccelerate(AccelerationHint) const;
+  void CalculateDirtyRegion(int canvas_width, int canvas_height);
 
   std::unique_ptr<PaintRecorder> recorder_;
   sk_sp<SkImage> hibernation_image_;
@@ -254,6 +256,7 @@
   Deque<RasterTimer> pending_raster_timers_;
 
   sk_sp<cc::PaintRecord> last_recording_;
+  cc::InvalidationRegion dirty_invalidate_region_;
 
   void SetNeedsFlush();
   base::RepeatingClosure set_needs_flush_callback_;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index 39bb6d1..0cf4a99 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -31,6 +31,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
 #include "cc/layers/texture_layer.h"
 #include "cc/test/skia_common.h"
@@ -1155,4 +1156,200 @@
   EXPECT_FALSE(bridge->HasRateLimiterForTesting());
 }
 
+// Test if we skip dirty rect calculation for canvas smaller than 256x256.
+TEST_F(Canvas2DLayerBridgeTest, SkipDirtyRectForSmallCanvas) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(100, 100), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->drawRect(SkRect::MakeWH(100, 100), flags);
+  DrawSomething(bridge.get());
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 0);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 0);
+}
+
+// Test if we can correctly calculate dirty rect for region with complexity 1.
+TEST_F(Canvas2DLayerBridgeTest, SmallDirtyRectCalculation) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->drawRect(SkRect::MakeWH(100, 100), flags);
+  DrawSomething(bridge.get());
+  // Dirty rect: (-1, -1, 102x102) & canvas size: 302x302. Dirty percentage:
+  // (102x102)/(302x302) = 11. (1 pixel is added around the rect for anti-alias
+  // effect.)
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 11,
+                                      1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 11,
+                                      1);
+}
+
+TEST_F(Canvas2DLayerBridgeTest, BigDirtyRectCalculation) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->drawRect(SkRect::MakeWH(300, 300), flags);
+  DrawSomething(bridge.get());
+  // Dirty rect: (-1, -1, 302x302) & canvas size: 302x302. Dirty percentage:
+  // (302x302)/(302x302) = 100. (1 pixel is added around the rect for anti-alias
+  // effect.)
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 100,
+                                      1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 100,
+                                      1);
+}
+
+// Test if we can correctly calculate dirty rect for region with complexity 2;
+// where dirty bounds and dirty region have different areas.
+TEST_F(Canvas2DLayerBridgeTest, TwoRegionDirtyRectCalculation) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->drawRect(SkRect::MakeWH(300, 30), flags);
+  canvas->drawRect(SkRect::MakeWH(30, 300), flags);
+  DrawSomething(bridge.get());
+  // Dirty region: (-1, -1, 302x32) Union (-1, 31, 32x270) & canvas size:
+  // 302x302. Dirty percentage: (302x31)/(31x271) = 20. (1 pixel is added
+  // around the rect for anti-alias effect.)
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 20,
+                                      1);
+  // Dirty region: (-1, -1, 302x32) Union (-1, 31, 32x270) = (-1, -1, 302x302)
+  // & canvas size: 302x302. Dirty percentage: (302x302)/(302x302) = 100. (1
+  // pixel is added around the rect for anti-alias effect.)
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 100,
+                                      1);
+}
+
+// Test dirty rect calculation for canvas with scale transforms.
+TEST_F(Canvas2DLayerBridgeTest, TransformedCanvasDirtyRect) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(500, 500), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->scale(0.5f, 0.5f);
+  canvas->drawRect(SkRect::MakeWH(500, 500), flags);
+  DrawSomething(bridge.get());
+  // Dirty region: 252x252 (scale transform reduces the height and width by
+  // half) & canvas size: 502x502, Dirty percentage: (252x252)/(502x502) = 25.
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 25,
+                                      1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 25,
+                                      1);
+}
+
+// Test dirty rect calculation for canvas with rotation transforms.
+TEST_F(Canvas2DLayerBridgeTest, RotationCanvasDirtyRect) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(200, 600), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->rotate(90);
+  SkRect dirty_rect;
+  dirty_rect.setXYWH(50, -100, 60, 60);
+  canvas->drawRect(dirty_rect, flags);
+  DrawSomething(bridge.get());
+  // After rotation, the canvas is at (-600, 0, 600x200) at 90
+  // degree. Dirty Region: 62x62 & Canvas size: 202x602, dirty percentage:
+  // (62x62)/(202x602) = 3.
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 3, 1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 3, 1);
+}
+
+// Test dirty rect calculation for canvas with translation transforms.
+TEST_F(Canvas2DLayerBridgeTest, TranslationCanvasDirtyRect) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(500, 500), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->translate(20, 50);
+  SkRect dirty_rect;
+  dirty_rect.setXYWH(50, 70, 60, 60);
+  canvas->drawRect(dirty_rect, flags);
+  DrawSomething(bridge.get());
+  // After translation, the canvas is at (20, 50, 500x500). Dirty
+  // Region: 62x62 & Canvas size: 502x502, dirty percentage:
+  // (62x62)/(502x502)=1.
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 1, 1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 1, 1);
+}
+
+// Test dirty rect calculation for canvas with clip rect.
+TEST_F(Canvas2DLayerBridgeTest, ClipRectCanvasDirtyRect) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(500, 500), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  canvas->clipRect(SkRect::MakeWH(100, 100));
+  canvas->drawRect(SkRect::MakeWH(200, 200), flags);
+  DrawSomething(bridge.get());
+  // Dirty region: 102x102 (clip rect restrict the dirty to be in 102x202) &
+  // canvas size: 502x502, dirty percentage:
+  // (102x102)/(502x502) = 4.
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 4, 1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 4, 1);
+}
+
+// Test if we can correctly calculate dirty rect for canvas with paintrecord;
+TEST_F(Canvas2DLayerBridgeTest, PaintRecordDirtyRect) {
+  PaintFlags flags;
+  std::unique_ptr<Canvas2DLayerBridge> bridge =
+      MakeBridge(IntSize(500, 500), Canvas2DLayerBridge::kEnableAcceleration,
+                 CanvasColorParams());
+  bridge->FinalizeFrame();
+  base::HistogramTester histogram_tester;
+  cc::PaintCanvas* canvas = bridge->DrawingCanvas();
+  PaintRecorder recorder;
+  recorder.beginRecording(SkRect::MakeWH(50, 50))
+      ->drawRect(SkRect::MakeWH(50, 50), flags);
+  canvas->drawPicture(recorder.finishRecordingAsPicture());
+  DrawSomething(bridge.get());
+  // Dirty region: 52x52 &
+  // canvas size: 502x502, dirty percentage: (52x52)/(502x502) = 1.
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Region.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Region.Percentage", 1, 1);
+  histogram_tester.ExpectTotalCount("Canvas.Repaint.Bounds.Percentage", 1);
+  histogram_tester.ExpectUniqueSample("Canvas.Repaint.Bounds.Percentage", 1, 1);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn
index 9c0e024e..383f96e3 100644
--- a/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -94,6 +94,7 @@
   ]
 
   deps = [
+    ":blink_heap_buildflags",
     "//testing/gtest",
     "//third_party/blink/public/mojom:mojom_platform_blink_headers",
     "//third_party/blink/renderer/platform:bindings_buildflags",
@@ -101,9 +102,7 @@
 }
 
 test("blink_heap_unittests") {
-  deps = [
-    ":blink_heap_unittests_sources",
-  ]
+  deps = [ ":blink_heap_unittests_sources" ]
   if (is_android) {
     deps += [
       "//base:base_java",
diff --git a/third_party/expat/BUILD.gn b/third_party/expat/BUILD.gn
index a606e26d..4a4cab2f 100644
--- a/third_party/expat/BUILD.gn
+++ b/third_party/expat/BUILD.gn
@@ -53,12 +53,8 @@
 }
 
 fuzzer_test("expat_xml_parse_fuzzer") {
-  sources = [
-    "fuzz/expat_xml_parse_fuzzer.cc",
-  ]
-  deps = [
-    ":expat",
-  ]
+  sources = [ "fuzz/expat_xml_parse_fuzzer.cc" ]
+  deps = [ ":expat" ]
   dict = "//third_party/libxml/fuzz/xml.dict"
   seed_corpus = "//third_party/libxml/fuzz/seed_corpus"
 }
diff --git a/third_party/libaom/BUILD.gn b/third_party/libaom/BUILD.gn
index 69969507..7a06da4 100644
--- a/third_party/libaom/BUILD.gn
+++ b/third_party/libaom/BUILD.gn
@@ -163,9 +163,8 @@
       configs += [ ":libaom_config" ]
 
       # https://bugs.chromium.org/p/aomedia/issues/detail?id=2294
-      sources = [
-        "//third_party/libaom/source/libaom/aom_ports/arm_cpudetect.c",
-      ]
+      sources =
+          [ "//third_party/libaom/source/libaom/aom_ports/arm_cpudetect.c" ]
       sources += aom_av1_common_intrin_neon
       sources += aom_dsp_common_intrin_neon
     }
diff --git a/third_party/libpng/BUILD.gn b/third_party/libpng/BUILD.gn
index 2b1b0da..79f4791 100644
--- a/third_party/libpng/BUILD.gn
+++ b/third_party/libpng/BUILD.gn
@@ -103,24 +103,18 @@
 
   public_configs = [ ":libpng_config" ]
 
-  public_deps = [
-    "//third_party/zlib",
-  ]
+  public_deps = [ "//third_party/zlib" ]
 
   configs += [ ":clang_warnings" ]
 }
 
 if (is_win) {
   component("libpng") {
-    public_deps = [
-      ":libpng_sources",
-    ]
+    public_deps = [ ":libpng_sources" ]
   }
 } else {
   group("libpng") {
-    public_deps = [
-      ":libpng_sources",
-    ]
+    public_deps = [ ":libpng_sources" ]
   }
 }
 
@@ -131,12 +125,8 @@
 ]
 
 fuzzer_test("libpng_read_fuzzer") {
-  sources = [
-    "contrib/oss-fuzz/libpng_read_fuzzer.cc",
-  ]
-  deps = [
-    ":libpng",
-  ]
+  sources = [ "contrib/oss-fuzz/libpng_read_fuzzer.cc" ]
+  deps = [ ":libpng" ]
   dict = "contrib/oss-fuzz/png.dict"
   seed_corpuses = libpng_ossfuzz_seed_corpuses
 }
diff --git a/third_party/test_fonts/BUILD.gn b/third_party/test_fonts/BUILD.gn
index a0b69d22..22ae1bec 100644
--- a/third_party/test_fonts/BUILD.gn
+++ b/third_party/test_fonts/BUILD.gn
@@ -35,7 +35,5 @@
     "test_fonts/Tinos-Regular.ttf",
   ]
 
-  outputs = [
-    "$root_out_dir/test_fonts/{{source_file_part}}",
-  ]
+  outputs = [ "$root_out_dir/test_fonts/{{source_file_part}}" ]
 }
diff --git a/tools/android/BUILD.gn b/tools/android/BUILD.gn
index 9ad5bb3..7e62f2a4 100644
--- a/tools/android/BUILD.gn
+++ b/tools/android/BUILD.gn
@@ -24,33 +24,23 @@
 }
 
 group("fincore") {
-  deps = [
-    "//tools/android/fincore",
-  ]
+  deps = [ "//tools/android/fincore" ]
 }
 
 group("memdump") {
-  deps = [
-    "//tools/android/memdump",
-  ]
+  deps = [ "//tools/android/memdump" ]
 }
 
 group("memconsumer") {
-  deps = [
-    "//tools/android/memconsumer:memconsumer_apk",
-  ]
+  deps = [ "//tools/android/memconsumer:memconsumer_apk" ]
 }
 
 group("memtrack_helper") {
-  deps = [
-    "//tools/android/memtrack_helper",
-  ]
+  deps = [ "//tools/android/memtrack_helper" ]
 }
 
 group("ps_ext") {
-  deps = [
-    "//tools/android/ps_ext",
-  ]
+  deps = [ "//tools/android/ps_ext" ]
 }
 
 group("spnego_authenticator") {
@@ -61,28 +51,21 @@
 }
 
 group("customtabs_benchmark") {
-  deps = [
-    "//tools/android/customtabs_benchmark:customtabs_benchmark_apk",
-  ]
+  deps = [ "//tools/android/customtabs_benchmark:customtabs_benchmark_apk" ]
 }
 
 group("audio_focus_grabber") {
   testonly = true
-  deps = [
-    "//tools/android/audio_focus_grabber:audio_focus_grabber_apk",
-  ]
+  deps = [ "//tools/android/audio_focus_grabber:audio_focus_grabber_apk" ]
 }
 
 group("push_apps_to_background") {
   testonly = true
-  deps = [
-    "//tools/android/push_apps_to_background:push_apps_to_background_apk",
-  ]
+  deps =
+      [ "//tools/android/push_apps_to_background:push_apps_to_background_apk" ]
 }
 
 group("io_benchmark") {
-  deps = [
-    "//tools/android/io_benchmark",
-  ]
+  deps = [ "//tools/android/io_benchmark" ]
   testonly = true
 }
diff --git a/tools/android/adb_reboot/BUILD.gn b/tools/android/adb_reboot/BUILD.gn
index 9c59f949..6a14094 100644
--- a/tools/android/adb_reboot/BUILD.gn
+++ b/tools/android/adb_reboot/BUILD.gn
@@ -3,7 +3,5 @@
 # found in the LICENSE file.
 
 executable("adb_reboot") {
-  sources = [
-    "adb_reboot.c",
-  ]
+  sources = [ "adb_reboot.c" ]
 }
diff --git a/tools/android/common/BUILD.gn b/tools/android/common/BUILD.gn
index 40d0b426..b51c3bc 100644
--- a/tools/android/common/BUILD.gn
+++ b/tools/android/common/BUILD.gn
@@ -12,7 +12,5 @@
     "net.h",
   ]
 
-  deps = [
-    "//base",
-  ]
+  deps = [ "//base" ]
 }
diff --git a/tools/android/fincore/BUILD.gn b/tools/android/fincore/BUILD.gn
index b6f3d37..8de8463 100644
--- a/tools/android/fincore/BUILD.gn
+++ b/tools/android/fincore/BUILD.gn
@@ -3,7 +3,5 @@
 # found in the LICENSE file.
 
 executable("fincore") {
-  sources = [
-    "fincore.cc",
-  ]
+  sources = [ "fincore.cc" ]
 }
diff --git a/tools/android/forwarder2/BUILD.gn b/tools/android/forwarder2/BUILD.gn
index 594646f..2a5bba92 100644
--- a/tools/android/forwarder2/BUILD.gn
+++ b/tools/android/forwarder2/BUILD.gn
@@ -45,17 +45,13 @@
       "//base",
       "//tools/android/common",
     ]
-    data_deps = [
-      "//build/android/pylib/device/commands",
-    ]
+    data_deps = [ "//build/android/pylib/device/commands" ]
   }
 
   create_native_executable_dist("device_forwarder_prepare_dist") {
     dist_dir = "$root_build_dir/forwarder_dist"
     binary = "$root_build_dir/device_forwarder"
-    deps = [
-      ":device_forwarder",
-    ]
+    deps = [ ":device_forwarder" ]
   }
 }
 
@@ -90,9 +86,7 @@
   }
 
   executable("host_forwarder") {
-    sources = [
-      "host_forwarder_main.cc",
-    ]
+    sources = [ "host_forwarder_main.cc" ]
     deps = [
       ":host_forwarder_source_set",
       "//base",
@@ -101,9 +95,7 @@
 
   test("host_forwarder_unittests") {
     testonly = true
-    sources = [
-      "host_controllers_manager_unittest.cc",
-    ]
+    sources = [ "host_controllers_manager_unittest.cc" ]
     deps = [
       ":host_forwarder_source_set",
       "//base",
diff --git a/tools/android/md5sum/BUILD.gn b/tools/android/md5sum/BUILD.gn
index e7c370e..26715f0 100644
--- a/tools/android/md5sum/BUILD.gn
+++ b/tools/android/md5sum/BUILD.gn
@@ -16,12 +16,8 @@
 }
 
 executable("md5sum_bin") {
-  sources = [
-    "md5sum.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "md5sum.cc" ]
+  deps = [ "//base" ]
 }
 
 if (current_toolchain == default_toolchain) {
@@ -30,9 +26,7 @@
   create_native_executable_dist("md5sum_prepare_dist") {
     dist_dir = "$root_build_dir/md5sum_dist"
     binary = "$root_build_dir/md5sum_bin"
-    deps = [
-      ":md5sum_bin",
-    ]
+    deps = [ ":md5sum_bin" ]
   }
 
   binary_symlink("md5sum_bin_host") {
diff --git a/tools/android/memconsumer/BUILD.gn b/tools/android/memconsumer/BUILD.gn
index 1f7a8c9b..d8cd386 100644
--- a/tools/android/memconsumer/BUILD.gn
+++ b/tools/android/memconsumer/BUILD.gn
@@ -28,9 +28,7 @@
 
 shared_library("libmemconsumer") {
   output_name = "memconsumer"
-  sources = [
-    "memconsumer_hook.cc",
-  ]
+  sources = [ "memconsumer_hook.cc" ]
   libs = [ "log" ]
   configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
 
diff --git a/tools/android/memdump/BUILD.gn b/tools/android/memdump/BUILD.gn
index dafc7ec..78a9033 100644
--- a/tools/android/memdump/BUILD.gn
+++ b/tools/android/memdump/BUILD.gn
@@ -3,10 +3,6 @@
 # found in the LICENSE file.
 
 executable("memdump") {
-  sources = [
-    "memdump.cc",
-  ]
-  deps = [
-    "//base",
-  ]
+  sources = [ "memdump.cc" ]
+  deps = [ "//base" ]
 }
diff --git a/tools/android/ps_ext/BUILD.gn b/tools/android/ps_ext/BUILD.gn
index 6fbba19..b521754c 100644
--- a/tools/android/ps_ext/BUILD.gn
+++ b/tools/android/ps_ext/BUILD.gn
@@ -3,7 +3,5 @@
 # found in the LICENSE file.
 
 executable("ps_ext") {
-  sources = [
-    "ps_ext.c",
-  ]
+  sources = [ "ps_ext.c" ]
 }
diff --git a/tools/android/push_apps_to_background/BUILD.gn b/tools/android/push_apps_to_background/BUILD.gn
index d030e543..991e574 100644
--- a/tools/android/push_apps_to_background/BUILD.gn
+++ b/tools/android/push_apps_to_background/BUILD.gn
@@ -10,13 +10,9 @@
 
 android_apk("push_apps_to_background_apk") {
   apk_name = "PushAppsToBackground"
-  sources = [
-    "src/org/chromium/push_apps_to_background/PushAppsToBackgroundActivity.java",
-  ]
+  sources = [ "src/org/chromium/push_apps_to_background/PushAppsToBackgroundActivity.java" ]
   android_manifest = "AndroidManifest.xml"
-  deps = [
-    ":push_apps_to_background_apk_resources",
-  ]
+  deps = [ ":push_apps_to_background_apk_resources" ]
 }
 
 android_resources("push_apps_to_background_apk_resources") {
diff --git a/tools/generate_library_loader/generate_library_loader.gni b/tools/generate_library_loader/generate_library_loader.gni
index 8d025a1..8d2061e 100644
--- a/tools/generate_library_loader/generate_library_loader.gni
+++ b/tools/generate_library_loader/generate_library_loader.gni
@@ -60,8 +60,6 @@
       output_cc,
       output_h,
     ]
-    public_deps = [
-      ":${target_name}_loader",
-    ]
+    public_deps = [ ":${target_name}_loader" ]
   }
 }
diff --git a/tools/metrics/BUILD.gn b/tools/metrics/BUILD.gn
index 7f7d0171..a97538c 100644
--- a/tools/metrics/BUILD.gn
+++ b/tools/metrics/BUILD.gn
@@ -9,9 +9,7 @@
     "histograms/histograms.xml",
   ]
   output = "$root_out_dir/histograms.xml"
-  outputs = [
-    output,
-  ]
+  outputs = [ output ]
   args = rebase_path(sources, root_build_dir) + [
            "--output",
            rebase_path(output, root_build_dir),
@@ -19,30 +17,18 @@
 }
 
 copy("actions_xml") {
-  sources = [
-    "actions/actions.xml",
-  ]
-  outputs = [
-    "$root_out_dir/actions.xml",
-  ]
+  sources = [ "actions/actions.xml" ]
+  outputs = [ "$root_out_dir/actions.xml" ]
 }
 
 copy("rappor_xml") {
-  sources = [
-    "rappor/rappor.xml",
-  ]
-  outputs = [
-    "$root_out_dir/rappor.xml",
-  ]
+  sources = [ "rappor/rappor.xml" ]
+  outputs = [ "$root_out_dir/rappor.xml" ]
 }
 
 copy("ukm_xml") {
-  sources = [
-    "ukm/ukm.xml",
-  ]
-  outputs = [
-    "$root_out_dir/ukm.xml",
-  ]
+  sources = [ "ukm/ukm.xml" ]
+  outputs = [ "$root_out_dir/ukm.xml" ]
 }
 
 group("metrics_metadata") {
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 7e4575f..69ef8e3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -20939,6 +20939,28 @@
   </summary>
 </histogram>
 
+<histogram name="Canvas.Repaint.Bounds.Percentage" units="%"
+    expires_after="M82">
+  <owner>yiyix@google.com</owner>
+  <owner>fserb@google.com</owner>
+  <summary>
+    measure the percentage of Canvas is dirty before each repaint by using
+    cc::Rect. Note that we record this metrics for all canvas that has an area
+    of more than 65k pixel^2 (256x256).
+  </summary>
+</histogram>
+
+<histogram name="Canvas.Repaint.Region.Percentage" units="%"
+    expires_after="M82">
+  <owner>yiyix@google.com</owner>
+  <owner>fserb@google.com</owner>
+  <summary>
+    measure the percentage of Canvas is dirty before each repaint by using
+    cc::Region. Note that we record this metrics for all canvas that has an area
+    of more than 65k pixel^2 (256x256).
+  </summary>
+</histogram>
+
 <histogram name="Canvas.RequestedImageMimeTypes" enum="RequestedImageMimeType"
     expires_after="2018-11-01">
   <obsolete>
@@ -105725,6 +105747,9 @@
 
 <histogram name="PageLoad.Experimental.NavigationToInteractive" units="ms"
     expires_after="2020-05-24">
+  <obsolete>
+    Removed 1/2020.
+  </obsolete>
   <owner>dproy@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
   <summary>
@@ -106105,6 +106130,9 @@
 
 <histogram name="PageLoad.Experimental.TimeToInteractiveStatus"
     enum="TimeToInteractiveStatus" expires_after="2020-05-24">
+  <obsolete>
+    Removed 1/2020.
+  </obsolete>
   <owner>tdresser@chromium.org</owner>
   <owner>dproy@chromium.org</owner>
   <summary>
@@ -106780,6 +106808,9 @@
 
 <histogram name="PageLoad.Internal.InteractiveToInteractiveDetection"
     units="ms" expires_after="M77">
+  <obsolete>
+    Removed 1/2020.
+  </obsolete>
   <owner>dproy@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
   <summary>
@@ -112132,6 +112163,22 @@
   </summary>
 </histogram>
 
+<histogram name="Permissions.CrowdDeny.DidHoldbackQuietUi" enum="Boolean"
+    expires_after="2020-12-01">
+  <owner>andypaicu@chromium.org</owner>
+  <owner>engedy@chromium.org</owner>
+  <owner>hkamila@chromium.org</owner>
+  <summary>
+    Whenever a notification permission prompt is to be displayed, crowd deny
+    might trigger based on site reputation which will result in a quiet
+    permission prompt UI to be used. Whenever this happens, there is a small
+    chance that the normal UI will still be used. This records, when a quiet UI
+    is supposed to be shown, whether it has been randomly selected into the
+    hold-back group. In this case the normal UI will be displayed unless
+    overriden by the user Prefences.
+  </summary>
+</histogram>
+
 <histogram name="Permissions.CrowdDeny.PreloadData.NotificationUxQuality"
     enum="CrowdDenyNotificationUxQuality" expires_after="2020-12-01">
   <owner>andypaicu@chromium.org</owner>
diff --git a/tools/perf/benchmarks/rendering.py b/tools/perf/benchmarks/rendering.py
index 110e9e8..1e05db4 100644
--- a/tools/perf/benchmarks/rendering.py
+++ b/tools/perf/benchmarks/rendering.py
@@ -13,6 +13,7 @@
 
 
 RENDERING_BENCHMARK_UMA = [
+    'Compositing.Display.DrawToSwapUs',
     'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
     'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
     'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
diff --git a/tools/resources/generate_resource_whitelist.gni b/tools/resources/generate_resource_whitelist.gni
index 7c8a1e4c..8a79e602 100644
--- a/tools/resources/generate_resource_whitelist.gni
+++ b/tools/resources/generate_resource_whitelist.gni
@@ -27,9 +27,7 @@
 
     script = "//tools/resources/generate_resource_whitelist.py"
 
-    outputs = [
-      invoker.output,
-    ]
+    outputs = [ invoker.output ]
 
     args = [
       "-o",
diff --git a/ui/accelerated_widget_mac/BUILD.gn b/ui/accelerated_widget_mac/BUILD.gn
index 8ae3e48..eba5b33f 100644
--- a/ui/accelerated_widget_mac/BUILD.gn
+++ b/ui/accelerated_widget_mac/BUILD.gn
@@ -52,9 +52,7 @@
 
 test("accelerated_widget_mac_unittests") {
   configs += [ "//build/config:precompiled_headers" ]
-  sources = [
-    "ca_layer_tree_unittest_mac.mm",
-  ]
+  sources = [ "ca_layer_tree_unittest_mac.mm" ]
   deps = [
     ":accelerated_widget_mac",
     "//base",
diff --git a/ui/base/cursor/cursor_loader_x11.cc b/ui/base/cursor/cursor_loader_x11.cc
index 52ab54aa..454cfd2 100644
--- a/ui/base/cursor/cursor_loader_x11.cc
+++ b/ui/base/cursor/cursor_loader_x11.cc
@@ -20,50 +20,138 @@
 #include "ui/gfx/skbitmap_operations.h"
 #include "ui/gfx/skia_util.h"
 
+namespace ui {
+
 namespace {
 
-static const struct {
-  const char* css_name;
-  const char* fallback_name;
-  int fallback_shape;
-} kCursorFallbacks[] = {
-    // clang-format off
-    { "pointer",     "hand",            XC_hand2 },
-    { "progress",    "left_ptr_watch",  XC_watch },
-    { "wait",        nullptr,           XC_watch },
-    { "cell",        nullptr,           XC_plus },
-    { "all-scroll",  nullptr,           XC_fleur},
-    { "v-scroll",    "all-scroll",      XC_fleur},
-    { "h-scroll",    "all-scroll",      XC_fleur},
-    { "crosshair",   nullptr,           XC_cross },
-    { "text",        nullptr,           XC_xterm },
-    { "not-allowed", "crossed_circle",  x11::None },
-    { "grabbing",    nullptr,           XC_hand2 },
-    { "col-resize",  nullptr,           XC_sb_h_double_arrow },
-    { "row-resize",  nullptr,           XC_sb_v_double_arrow},
-    { "n-resize",    nullptr,           XC_top_side},
-    { "e-resize",    nullptr,           XC_right_side},
-    { "s-resize",    nullptr,           XC_bottom_side},
-    { "w-resize",    nullptr,           XC_left_side},
-    { "ne-resize",   nullptr,           XC_top_right_corner},
-    { "nw-resize",   nullptr,           XC_top_left_corner},
-    { "se-resize",   nullptr,           XC_bottom_right_corner},
-    { "sw-resize",   nullptr,           XC_bottom_left_corner},
-    { "ew-resize",   nullptr,           XC_sb_h_double_arrow},
-    { "ns-resize",   nullptr,           XC_sb_v_double_arrow},
-    { "nesw-resize", "fd_double_arrow", x11::None},
-    { "nwse-resize", "bd_double_arrow", x11::None},
-    { "dnd-none",    "grabbing",        XC_hand2 },
-    { "dnd-move",    "grabbing",        XC_hand2 },
-    { "dnd-copy",    "grabbing",        XC_hand2 },
-    { "dnd-link",    "grabbing",        XC_hand2 },
-    // clang-format on
-};
+// Load a cursor with a list of css names or shapes in order of decreasing
+// priority.
+::Cursor LoadFontCursor() {
+  return x11::None;
+}
+
+template <typename... Ts>
+::Cursor LoadFontCursor(int shape, Ts... ts);
+
+template <typename... Ts>
+::Cursor LoadFontCursor(const char* name, Ts... ts) {
+  ::Cursor cursor = XcursorLibraryLoadCursor(gfx::GetXDisplay(), name);
+  if (cursor != x11::None)
+    return cursor;
+  return LoadFontCursor(ts...);
+}
+
+template <typename... Ts>
+::Cursor LoadFontCursor(int shape, Ts... ts) {
+  ::Cursor cursor = XCreateFontCursor(gfx::GetXDisplay(), shape);
+  if (cursor != x11::None)
+    return cursor;
+  return LoadFontCursor(ts...);
+}
+
+::Cursor LoadFontCursorForCursorType(CursorType id) {
+  switch (id) {
+    case CursorType::kMiddlePanning:
+      return LoadFontCursor("all-scroll", XC_fleur);
+    case CursorType::kMiddlePanningVertical:
+      return LoadFontCursor("v-scroll");
+    case CursorType::kMiddlePanningHorizontal:
+      return LoadFontCursor("h-scroll");
+    case CursorType::kNone:
+      return LoadFontCursor("none");
+    case CursorType::kGrab:
+      return LoadFontCursor("openhand", "grab");
+    case CursorType::kGrabbing:
+      return LoadFontCursor("closedhand", "grabbing", XC_hand2);
+    case CursorType::kNull:
+    case CursorType::kPointer:
+      return LoadFontCursor("left_ptr", XC_left_ptr);
+    case CursorType::kMove:
+      return LoadFontCursor("move", XC_fleur);
+    case CursorType::kCross:
+      return LoadFontCursor("crosshair", XC_cross);
+    case CursorType::kHand:
+      return LoadFontCursor("pointer", "hand", XC_hand2);
+    case CursorType::kIBeam:
+      return LoadFontCursor("text", XC_xterm);
+    case CursorType::kProgress:
+      return LoadFontCursor("progress", "left_ptr_watch", XC_watch);
+    case CursorType::kWait:
+      return LoadFontCursor("wait", XC_watch);
+    case CursorType::kHelp:
+      return LoadFontCursor("help");
+    case CursorType::kEastResize:
+    case CursorType::kEastPanning:
+      return LoadFontCursor("e-resize", XC_right_side);
+    case CursorType::kNorthResize:
+    case CursorType::kNorthPanning:
+      return LoadFontCursor("n-resize", XC_top_side);
+    case CursorType::kNorthEastResize:
+    case CursorType::kNorthEastPanning:
+      return LoadFontCursor("ne-resize", XC_top_right_corner);
+    case CursorType::kNorthWestResize:
+    case CursorType::kNorthWestPanning:
+      return LoadFontCursor("nw-resize", XC_top_left_corner);
+    case CursorType::kSouthResize:
+    case CursorType::kSouthPanning:
+      return LoadFontCursor("s-resize", XC_bottom_side);
+    case CursorType::kSouthEastResize:
+    case CursorType::kSouthEastPanning:
+      return LoadFontCursor("se-resize", XC_bottom_right_corner);
+    case CursorType::kSouthWestResize:
+    case CursorType::kSouthWestPanning:
+      return LoadFontCursor("sw-resize", XC_bottom_left_corner);
+    case CursorType::kWestResize:
+    case CursorType::kWestPanning:
+      return LoadFontCursor("w-resize", XC_right_side);
+    case CursorType::kNorthSouthResize:
+      return LoadFontCursor(XC_sb_v_double_arrow, "ns-resize");
+    case CursorType::kEastWestResize:
+      return LoadFontCursor(XC_sb_h_double_arrow, "ew-resize");
+    case CursorType::kColumnResize:
+      return LoadFontCursor("col-resize", XC_sb_h_double_arrow);
+    case CursorType::kRowResize:
+      return LoadFontCursor("row-resize", XC_sb_v_double_arrow);
+    case CursorType::kNorthEastSouthWestResize:
+      return LoadFontCursor("size_bdiag", "nesw-resize", "fd_double_arrow");
+    case CursorType::kNorthWestSouthEastResize:
+      return LoadFontCursor("size_fdiag", "nwse-resize", "bd_double_arrow");
+    case CursorType::kVerticalText:
+      return LoadFontCursor("vertical-text");
+    case CursorType::kZoomIn:
+      return LoadFontCursor("zoom-in");
+    case CursorType::kZoomOut:
+      return LoadFontCursor("zoom-out");
+    case CursorType::kCell:
+      return LoadFontCursor("cell", XC_plus);
+    case CursorType::kContextMenu:
+      return LoadFontCursor("context-menu");
+    case CursorType::kAlias:
+      return LoadFontCursor("alias");
+    case CursorType::kNoDrop:
+      return LoadFontCursor("no-drop");
+    case CursorType::kCopy:
+      return LoadFontCursor("copy");
+    case CursorType::kNotAllowed:
+      return LoadFontCursor("not-allowed", "crossed_circle");
+    case CursorType::kDndNone:
+      return LoadFontCursor("dnd-none", XC_hand2);
+    case CursorType::kDndMove:
+      return LoadFontCursor("dnd-move", XC_hand2);
+    case CursorType::kDndCopy:
+      return LoadFontCursor("dnd-copy", XC_hand2);
+    case CursorType::kDndLink:
+      return LoadFontCursor("dnd-link", XC_hand2);
+    case CursorType::kCustom:
+      NOTREACHED();
+      return LoadFontCursor();
+  }
+  NOTREACHED() << "Case not handled for " << static_cast<int>(id);
+  return LoadFontCursor();
+}
 
 }  // namespace
 
-namespace ui {
-
 CursorLoader* CursorLoader::Create() {
   return new CursorLoaderX11;
 }
@@ -187,19 +275,7 @@
   }
 
   // First try to load the cursor directly.
-  const char* css_name = CursorCssNameFromId(id);
-  ::Cursor cursor = XcursorLibraryLoadCursor(display_, css_name);
-  if (cursor == x11::None) {
-    // Try a similar cursor supplied by the native cursor theme.
-    for (const auto& mapping : kCursorFallbacks) {
-      if (strcmp(mapping.css_name, css_name) == 0) {
-        if (mapping.fallback_name)
-          cursor = XcursorLibraryLoadCursor(display_, mapping.fallback_name);
-        if (cursor == x11::None && mapping.fallback_shape)
-          cursor = XCreateFontCursor(display_, mapping.fallback_shape);
-      }
-    }
-  }
+  ::Cursor cursor = LoadFontCursorForCursorType(id);
   if (cursor != x11::None) {
     font_cursors_[id] = cursor;
     return cursor;
diff --git a/ui/chromeos/search_box/search_box_view_base.cc b/ui/chromeos/search_box/search_box_view_base.cc
index 80af3b4..160c2db 100644
--- a/ui/chromeos/search_box/search_box_view_base.cc
+++ b/ui/chromeos/search_box/search_box_view_base.cc
@@ -294,7 +294,13 @@
   content_container_->AddChildView(close_button_);
 }
 
-SearchBoxViewBase::~SearchBoxViewBase() = default;
+SearchBoxViewBase::~SearchBoxViewBase() {
+  // |search_box_| tries to call methods on us, and so must be destroyed before
+  // we are.  Remove it from the tree first, which will blur it; it must be
+  // blurred before being deleted.
+  content_container_->RemoveChildView(search_box_);
+  delete search_box_;
+}
 
 void SearchBoxViewBase::Init() {
   SetPaintToLayer();
diff --git a/ui/events/keycodes/BUILD.gn b/ui/events/keycodes/BUILD.gn
index 97e5fd4..772d0ef 100644
--- a/ui/events/keycodes/BUILD.gn
+++ b/ui/events/keycodes/BUILD.gn
@@ -14,9 +14,7 @@
     "xkb_keysym.h",
   ]
 
-  public_deps = [
-    "//ui/base:buildflags",
-  ]
+  public_deps = [ "//ui/base:buildflags" ]
 
   deps = [
     "//base",
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 8300d2f5..bb3e57f3 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -261,6 +261,7 @@
     "widget/widget.h",
     "widget/widget_delegate.h",
     "widget/widget_deletion_observer.h",
+    "widget/widget_getter.h",
     "widget/widget_observer.h",
     "widget/widget_removals_observer.h",
     "widget/widget_utils.h",
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index 80fef27..e195d527 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -56,8 +56,6 @@
   ~TestBubbleFrameViewWidgetDelegate() override = default;
 
   // WidgetDelegate:
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
   View* GetContentsView() override {
     if (!contents_view_) {
       StaticSizedView* contents_view =
@@ -75,6 +73,9 @@
   }
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* const widget_;
   View* contents_view_ = nullptr;  // Owned by |widget_|.
   bool should_show_close_ = false;
@@ -114,12 +115,6 @@
   }
 
   // BubbleFrameView:
-  Widget* GetWidget() override { return widget_.get(); }
-
-  const Widget* GetWidget() const override {
-    return widget_.get();
-  }
-
   gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) const override {
     return available_bounds_;
   }
@@ -133,6 +128,9 @@
   }
 
  private:
+  // BubbleFrameView:
+  const Widget* GetWidgetImpl() const override { return widget_.get(); }
+
   const gfx::Rect available_bounds_ = gfx::Rect(0, 0, 1000, 1000);
   gfx::Rect available_anchor_window_bounds_;
 
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc
index 901c12f37..a39dd48 100644
--- a/ui/views/controls/table/table_view_unittest.cc
+++ b/ui/views/controls/table/table_view_unittest.cc
@@ -1590,12 +1590,13 @@
 
   // WidgetDelegate:
   void DeleteDelegate() override;
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
 
   void SetFocusChangeListener(FocusChangeListener* listener);
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* widget_;
   FocusChangeListener* listener_;
 
diff --git a/ui/views/controls/webview/web_dialog_view.cc b/ui/views/controls/webview/web_dialog_view.cc
index ff9d5cf..7ab9be8 100644
--- a/ui/views/controls/webview/web_dialog_view.cc
+++ b/ui/views/controls/webview/web_dialog_view.cc
@@ -230,14 +230,6 @@
   return ShouldShowDialogTitle();
 }
 
-views::Widget* WebDialogView::GetWidget() {
-  return View::GetWidget();
-}
-
-const views::Widget* WebDialogView::GetWidget() const {
-  return View::GetWidget();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // WebDialogDelegate implementation:
 
diff --git a/ui/views/controls/webview/web_dialog_view.h b/ui/views/controls/webview/web_dialog_view.h
index 513f8fa..b3df2a9 100644
--- a/ui/views/controls/webview/web_dialog_view.h
+++ b/ui/views/controls/webview/web_dialog_view.h
@@ -106,8 +106,6 @@
   View* GetInitiallyFocusedView() override;
   bool ShouldShowWindowTitle() const override;
   bool ShouldShowCloseButton() const override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
 
   // ui::WebDialogDelegate:
   ui::ModalType GetDialogModalType() const override;
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc
index d61ead2..9e5f911b 100644
--- a/ui/views/focus/focus_manager_unittest.cc
+++ b/ui/views/focus/focus_manager_unittest.cc
@@ -862,10 +862,11 @@
   bool ShouldAdvanceFocusToTopLevelWidget() const override {
     return should_advance_focus_to_parent_;
   }
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* widget_;
   bool should_advance_focus_to_parent_;
 
diff --git a/ui/views/test/focus_manager_test.cc b/ui/views/test/focus_manager_test.cc
index cd3f21b..5b402aff 100644
--- a/ui/views/test/focus_manager_test.cc
+++ b/ui/views/test/focus_manager_test.cc
@@ -53,14 +53,6 @@
   return contents_view_;
 }
 
-Widget* FocusManagerTest::GetWidget() {
-  return contents_view_->GetWidget();
-}
-
-const Widget* FocusManagerTest::GetWidget() const {
-  return contents_view_->GetWidget();
-}
-
 void FocusManagerTest::GetAccessiblePanes(std::vector<View*>* panes) {
   std::copy(accessible_panes_.begin(), accessible_panes_.end(),
             std::back_inserter(*panes));
@@ -86,6 +78,10 @@
   accessible_panes_ = panes;
 }
 
+const Widget* FocusManagerTest::GetWidgetImpl() const {
+  return contents_view_->GetWidget();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // TestFocusChangeListener
 
diff --git a/ui/views/test/focus_manager_test.h b/ui/views/test/focus_manager_test.h
index 51c427ce..2520b59 100644
--- a/ui/views/test/focus_manager_test.h
+++ b/ui/views/test/focus_manager_test.h
@@ -31,8 +31,6 @@
 
   // WidgetDelegate:
   View* GetContentsView() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   void GetAccessiblePanes(std::vector<View*>* panes) override;
 
  protected:
@@ -47,6 +45,9 @@
   void SetAccessiblePanes(const std::vector<View*>& panes);
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override;
+
   View* contents_view_;
   FocusChangeListener* focus_change_listener_ = nullptr;
   WidgetFocusChangeListener* widget_focus_change_listener_ = nullptr;
diff --git a/ui/views/test/widget_test.cc b/ui/views/test/widget_test.cc
index 296b508..a30ee29 100644
--- a/ui/views/test/widget_test.cc
+++ b/ui/views/test/widget_test.cc
@@ -111,14 +111,6 @@
   widget_ = nullptr;
 }
 
-Widget* TestDesktopWidgetDelegate::GetWidget() {
-  return widget_;
-}
-
-const Widget* TestDesktopWidgetDelegate::GetWidget() const {
-  return widget_;
-}
-
 View* TestDesktopWidgetDelegate::GetContentsView() {
   return contents_view_ ? contents_view_ : WidgetDelegate::GetContentsView();
 }
@@ -133,6 +125,10 @@
   return can_close_;
 }
 
+const Widget* TestDesktopWidgetDelegate::GetWidgetImpl() const {
+  return widget_;
+}
+
 TestInitialFocusWidgetDelegate::TestInitialFocusWidgetDelegate(
     gfx::NativeWindow context)
     : view_(new View) {
diff --git a/ui/views/test/widget_test.h b/ui/views/test/widget_test.h
index 83fa858c..5475b3a 100644
--- a/ui/views/test/widget_test.h
+++ b/ui/views/test/widget_test.h
@@ -166,13 +166,14 @@
 
   // WidgetDelegate:
   void WindowClosing() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   View* GetContentsView() override;
   bool ShouldAdvanceFocusToTopLevelWidget() const override;
   bool OnCloseRequested(Widget::ClosedReason close_reason) override;
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override;
+
   Widget* widget_;
   View* contents_view_ = nullptr;
   int window_closing_count_ = 0;
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 453074ba..ed18694 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -154,15 +154,11 @@
 
 // Tree operations -------------------------------------------------------------
 
-const Widget* View::GetWidget() const {
+const Widget* View::GetWidgetImpl() const {
   // The root view holds a reference to this view hierarchy's Widget.
   return parent_ ? parent_->GetWidget() : nullptr;
 }
 
-Widget* View::GetWidget() {
-  return const_cast<Widget*>(const_cast<const View*>(this)->GetWidget());
-}
-
 void View::ReorderChildView(View* view, int index) {
   DCHECK_EQ(view->parent_, this);
   const auto i = std::find(children_.begin(), children_.end(), view);
diff --git a/ui/views/view.h b/ui/views/view.h
index e5cbab8..be4814a 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -49,6 +49,7 @@
 #include "ui/views/paint_info.h"
 #include "ui/views/view_targeter.h"
 #include "ui/views/views_export.h"
+#include "ui/views/widget/widget_getter.h"
 
 using ui::OSExchangeData;
 
@@ -271,7 +272,8 @@
                           public ui::EventTarget,
                           public ui::EventHandler,
                           public ui::PropertyHandler,
-                          public views::metadata::MetaDataProvider {
+                          public metadata::MetaDataProvider,
+                          public virtual WidgetGetter {
  public:
   using Views = std::vector<View*>;
 
@@ -390,9 +392,7 @@
 
   // Tree operations -----------------------------------------------------------
 
-  // Get the Widget that hosts this View, if any.
-  virtual const Widget* GetWidget() const;
-  virtual Widget* GetWidget();
+  const Widget* GetWidgetImpl() const override;
 
   // Adds |view| as a child of this view, optionally at |index|.
   // Returns the raw pointer for callers which want to hold a pointer to the
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 609ae12b..289f8742 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -614,14 +614,6 @@
   UpdateWindowTransparency();
 }
 
-Widget* DesktopNativeWidgetAura::GetWidget() {
-  return native_widget_delegate_->AsWidget();
-}
-
-const Widget* DesktopNativeWidgetAura::GetWidget() const {
-  return native_widget_delegate_->AsWidget();
-}
-
 gfx::NativeView DesktopNativeWidgetAura::GetNativeView() const {
   return content_window_;
 }
@@ -1282,4 +1274,8 @@
   }
 }
 
+const Widget* DesktopNativeWidgetAura::GetWidgetImpl() const {
+  return native_widget_delegate_->AsWidget();
+}
+
 }  // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 6cc7456..a5f1dac 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -114,8 +114,6 @@
   bool ShouldUseNativeFrame() const override;
   bool ShouldWindowContentsBeTransparent() const override;
   void FrameTypeChanged() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   gfx::NativeView GetNativeView() const override;
   Widget* GetTopLevelWidget() override;
   const ui::Compositor* GetCompositor() const override;
@@ -261,6 +259,9 @@
   // Notify the root view of our widget of a native accessibility event.
   void NotifyAccessibilityEvent(ax::mojom::Event event_type);
 
+  // internal::NativeWidgetPrivate
+  const Widget* GetWidgetImpl() const override;
+
   std::unique_ptr<aura::WindowTreeHost> host_;
   DesktopWindowTreeHost* desktop_window_tree_host_;
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
index 0b2ab7e..19e765d 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
@@ -129,8 +129,6 @@
 
   // WidgetDelegate:
   bool CanResize() const override { return can_resize_; }
-  Widget* GetWidget() override { return widget_; }
-  Widget* GetWidget() const override { return widget_; }
   NonClientFrameView* CreateNonClientFrameView(Widget* widget) override {
     DCHECK(widget_ == widget);
     if (!frame_view_)
@@ -140,6 +138,9 @@
   void DeleteDelegate() override { delete this; }
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* const widget_;
   HitTestNonClientFrameView* frame_view_ = nullptr;
   bool can_resize_ = false;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 74fb824..3066064 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -289,14 +289,6 @@
   GetWidget()->GetRootView()->SchedulePaint();
 }
 
-Widget* NativeWidgetAura::GetWidget() {
-  return delegate_->AsWidget();
-}
-
-const Widget* NativeWidgetAura::GetWidget() const {
-  return delegate_->AsWidget();
-}
-
 gfx::NativeView NativeWidgetAura::GetNativeView() const {
   return window_;
 }
@@ -1065,6 +1057,10 @@
     window_->Focus();
 }
 
+const Widget* NativeWidgetAura::GetWidgetImpl() const {
+  return delegate_->AsWidget();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Widget, public:
 
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index d7c140f..a71b6e12 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -74,8 +74,6 @@
   bool ShouldUseNativeFrame() const override;
   bool ShouldWindowContentsBeTransparent() const override;
   void FrameTypeChanged() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   gfx::NativeView GetNativeView() const override;
   gfx::NativeWindow GetNativeWindow() const override;
   Widget* GetTopLevelWidget() override;
@@ -222,6 +220,9 @@
  private:
   void SetInitialFocus(ui::WindowShowState show_state);
 
+  // internal::NativeWidgetPrivate:
+  const Widget* GetWidgetImpl() const override;
+
   internal::NativeWidgetDelegate* delegate_;
 
   // WARNING: set to NULL when destroyed. As the Widget is not necessarily
diff --git a/ui/views/widget/native_widget_aura_unittest.cc b/ui/views/widget/native_widget_aura_unittest.cc
index 69a71e2..b043944 100644
--- a/ui/views/widget/native_widget_aura_unittest.cc
+++ b/ui/views/widget/native_widget_aura_unittest.cc
@@ -332,8 +332,7 @@
   bool CanMinimize() const override { return true; }
   bool CanResize() const override { return true; }
   void DeleteDelegate() override { delete this; }
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
+  const Widget* GetWidgetImpl() const override { return widget_; }
 
   Widget* widget_;
   DISALLOW_COPY_AND_ASSIGN(PropertyTestWidgetDelegate);
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index 7c2db18..9ae05a6 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -94,8 +94,6 @@
   bool ShouldUseNativeFrame() const override;
   bool ShouldWindowContentsBeTransparent() const override;
   void FrameTypeChanged() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   gfx::NativeView GetNativeView() const override;
   gfx::NativeWindow GetNativeWindow() const override;
   Widget* GetTopLevelWidget() override;
@@ -247,6 +245,9 @@
   friend class views::test::WidgetTest;
   class ZoomFocusMonitor;
 
+  // internal::NativeWidgetPrivate:
+  const Widget* GetWidgetImpl() const override;
+
   internal::NativeWidgetDelegate* delegate_;
   std::unique_ptr<NativeWidgetMacNSWindowHost> ns_window_host_;
 
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index b32f8c6..522c162f 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -250,14 +250,6 @@
   GetWidget()->GetRootView()->SchedulePaint();
 }
 
-Widget* NativeWidgetMac::GetWidget() {
-  return delegate_->AsWidget();
-}
-
-const Widget* NativeWidgetMac::GetWidget() const {
-  return delegate_->AsWidget();
-}
-
 gfx::NativeView NativeWidgetMac::GetNativeView() const {
   // Returns a BridgedContentView, unless there is no views::RootView set.
   return [GetNativeWindow().GetNativeNSWindow() contentView];
@@ -876,6 +868,10 @@
   return ui::EventDispatchDetails();
 }
 
+const Widget* NativeWidgetMac::GetWidgetImpl() const {
+  return delegate_->AsWidget();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Widget:
 
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm
index 6735f70..83ec6f6d5 100644
--- a/ui/views/widget/native_widget_mac_unittest.mm
+++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -1799,10 +1799,11 @@
   // WidgetDelegate:
   base::string16 GetWindowTitle() const override { return title_; }
   bool ShouldShowWindowTitle() const override { return should_show_title_; }
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* widget_;
   base::string16 title_;
   bool should_show_title_;
diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h
index 7055294..b8de310 100644
--- a/ui/views/widget/native_widget_private.h
+++ b/ui/views/widget/native_widget_private.h
@@ -13,6 +13,7 @@
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/widget/native_widget.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_getter.h"
 
 namespace gfx {
 class ImageSkia;
@@ -43,7 +44,8 @@
 //             NativeWidget implementations. This file should not be included
 //             in code that does not fall into one of these use cases.
 //
-class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
+class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget,
+                                         public virtual WidgetGetter {
  public:
   ~NativeWidgetPrivate() override = default;
 
@@ -92,11 +94,6 @@
   virtual bool ShouldWindowContentsBeTransparent() const = 0;
   virtual void FrameTypeChanged() = 0;
 
-  // Returns the Widget associated with this NativeWidget. This function is
-  // guaranteed to return non-NULL for the lifetime of the NativeWidget.
-  virtual Widget* GetWidget() = 0;
-  virtual const Widget* GetWidget() const = 0;
-
   // Returns the NativeView/Window associated with this NativeWidget.
   virtual gfx::NativeView GetNativeView() const = 0;
   virtual gfx::NativeWindow GetNativeWindow() const = 0;
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc
index 8beaf2c..e10baf0 100644
--- a/ui/views/widget/root_view.cc
+++ b/ui/views/widget/root_view.cc
@@ -354,14 +354,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // RootView, View overrides:
 
-const Widget* RootView::GetWidget() const {
-  return widget_;
-}
-
-Widget* RootView::GetWidget() {
-  return const_cast<Widget*>(const_cast<const RootView*>(this)->GetWidget());
-}
-
 bool RootView::IsDrawn() const {
   return GetVisible();
 }
@@ -810,6 +802,10 @@
   return details;
 }
 
+const Widget* RootView::GetWidgetImpl() const {
+  return widget_;
+}
+
 BEGIN_METADATA(RootView)
 METADATA_PARENT_CLASS(View)
 END_METADATA()
diff --git a/ui/views/widget/root_view.h b/ui/views/widget/root_view.h
index 3103c624..576ddbd 100644
--- a/ui/views/widget/root_view.h
+++ b/ui/views/widget/root_view.h
@@ -110,8 +110,6 @@
   void OnEventProcessingFinished(ui::Event* event) override;
 
   // View:
-  const Widget* GetWidget() const override;
-  Widget* GetWidget() override;
   bool IsDrawn() const override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
   bool OnMouseDragged(const ui::MouseEvent& event) override;
@@ -175,6 +173,9 @@
   //////////////////////////////////////////////////////////////////////////////
   // Tree operations -----------------------------------------------------------
 
+  // View:
+  const Widget* GetWidgetImpl() const override;
+
   // The host Widget
   Widget* widget_;
 
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 409024eb..7bffabb 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -98,8 +98,6 @@
 
   // WidgetDelegate:
   void DeleteDelegate() override { delete this; }
-  Widget* GetWidget() override { return widget_; }
-  const Widget* GetWidget() const override { return widget_; }
   bool ShouldAdvanceFocusToTopLevelWidget() const override {
     // In most situations where a Widget is used without a delegate the Widget
     // is used as a container, so that we want focus to advance to the top-level
@@ -108,6 +106,9 @@
   }
 
  private:
+  // WidgetDelegate:
+  const Widget* GetWidgetImpl() const override { return widget_; }
+
   Widget* widget_;
 
   DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate);
diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc
index 1ffec62..bacc4b79 100644
--- a/ui/views/widget/widget_delegate.cc
+++ b/ui/views/widget/widget_delegate.cc
@@ -205,14 +205,6 @@
   delete this;
 }
 
-Widget* WidgetDelegateView::GetWidget() {
-  return View::GetWidget();
-}
-
-const Widget* WidgetDelegateView::GetWidget() const {
-  return View::GetWidget();
-}
-
 views::View* WidgetDelegateView::GetContentsView() {
   return this;
 }
diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h
index 82ad156..66cc515 100644
--- a/ui/views/widget/widget_delegate.h
+++ b/ui/views/widget/widget_delegate.h
@@ -13,6 +13,7 @@
 #include "ui/base/ui_base_types.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_getter.h"
 
 namespace gfx {
 class ImageSkia;
@@ -27,7 +28,7 @@
 class View;
 
 // Handles events on Widgets in context-specific ways.
-class VIEWS_EXPORT WidgetDelegate {
+class VIEWS_EXPORT WidgetDelegate : public virtual WidgetGetter {
  public:
   WidgetDelegate();
 
@@ -149,10 +150,6 @@
   virtual void OnWindowBeginUserBoundsChange() {}
   virtual void OnWindowEndUserBoundsChange() {}
 
-  // Returns the Widget associated with this delegate.
-  virtual Widget* GetWidget() = 0;
-  virtual const Widget* GetWidget() const = 0;
-
   // Returns the View that is contained within this Widget.
   virtual View* GetContentsView();
 
@@ -212,10 +209,9 @@
   DISALLOW_COPY_AND_ASSIGN(WidgetDelegate);
 };
 
-// A WidgetDelegate implementation that is-a View. Used to override GetWidget()
-// to call View's GetWidget() for the common case where a WidgetDelegate
-// implementation is-a View. Note that WidgetDelegateView is not owned by
-// view's hierarchy and is expected to be deleted on DeleteDelegate call.
+// A WidgetDelegate implementation that is-a View. Note that WidgetDelegateView
+// is not owned by view's hierarchy and is expected to be deleted on
+// DeleteDelegate call.
 class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
  public:
   METADATA_HEADER(WidgetDelegateView);
@@ -225,8 +221,6 @@
 
   // WidgetDelegate:
   void DeleteDelegate() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   views::View* GetContentsView() override;
 
  private:
diff --git a/ui/views/widget/widget_getter.h b/ui/views/widget/widget_getter.h
new file mode 100644
index 0000000..1e5b5f6
--- /dev/null
+++ b/ui/views/widget/widget_getter.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_WIDGET_GETTER_H_
+#define UI_VIEWS_WIDGET_WIDGET_GETTER_H_
+
+namespace views {
+class Widget;
+
+// Make this class a virtual base of any base class which needs to expose a
+// GetWidget() method, then override GetWidgetImpl() as appropriate.
+//
+// Having GetWidgetImpl() be the override, not GetWidget() directly, avoids the
+// need for subclasses to either override both GetWidget() methods or risk
+// obscure compilation or name-hiding errors from only overriding one.  Using
+// this as a virtual base avoids the need to explicitly qualify GetWidget()
+// calls with a base class name when multiple bases expose it, as in e.g.
+// View + WidgetDelegate.
+class WidgetGetter {
+ public:
+  Widget* GetWidget() {
+    return const_cast<Widget*>(
+        static_cast<const WidgetGetter*>(this)->GetWidget());
+  }
+  const Widget* GetWidget() const { return GetWidgetImpl(); }
+
+ private:
+  virtual const Widget* GetWidgetImpl() const = 0;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_WIDGET_WIDGET_GETTER_H_
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc
index 7386af9..f3a5cba 100644
--- a/ui/views/window/dialog_delegate.cc
+++ b/ui/views/window/dialog_delegate.cc
@@ -344,14 +344,6 @@
   delete this;
 }
 
-Widget* DialogDelegateView::GetWidget() {
-  return View::GetWidget();
-}
-
-const Widget* DialogDelegateView::GetWidget() const {
-  return View::GetWidget();
-}
-
 View* DialogDelegateView::GetContentsView() {
   return this;
 }
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h
index 4379778..976589a 100644
--- a/ui/views/window/dialog_delegate.h
+++ b/ui/views/window/dialog_delegate.h
@@ -284,10 +284,9 @@
   DISALLOW_COPY_AND_ASSIGN(DialogDelegate);
 };
 
-// A DialogDelegate implementation that is-a View. Used to override GetWidget()
-// to call View's GetWidget() for the common case where a DialogDelegate
-// implementation is-a View. Note that DialogDelegateView is not owned by
-// view's hierarchy and is expected to be deleted on DeleteDelegate call.
+// A DialogDelegate implementation that is-a View. Note that DialogDelegateView
+// is not owned by view's hierarchy and is expected to be deleted on
+// DeleteDelegate call.
 class VIEWS_EXPORT DialogDelegateView : public DialogDelegate,
                                         public View {
  public:
@@ -296,8 +295,6 @@
 
   // DialogDelegate:
   void DeleteDelegate() override;
-  Widget* GetWidget() override;
-  const Widget* GetWidget() const override;
   View* GetContentsView() override;
 
   // View:
diff --git a/ui/webui/resources/js/ios/BUILD.gn b/ui/webui/resources/js/ios/BUILD.gn
index e427df89..3115cf4 100644
--- a/ui/webui/resources/js/ios/BUILD.gn
+++ b/ui/webui/resources/js/ios/BUILD.gn
@@ -5,9 +5,7 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_library("web_ui") {
-  deps = [
-    ":mojo_api",
-  ]
+  deps = [ ":mojo_api" ]
 }
 
 js_library("mojo_api") {