diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..803a49a0
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,5 @@
+# Disable include-cleaner checks, as Chromium doesn't enforce them and they
+# just create noise when working with clangd.
+Diagnostics:
+  UnusedIncludes: None
+  MissingIncludes: None
diff --git a/.gitignore b/.gitignore
index 22417f2..be45bbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,7 +73,6 @@
 vs-chromium-project.txt
 # Store android emulator artifacts, used by //tools/android/avd/avd.py
 /.android_emulator/
-/.clangd
 /.clangd/
 /.clangd-index/
 # Settings directories for eclipse
diff --git a/DEPS b/DEPS
index e10d77e..1289524 100644
--- a/DEPS
+++ b/DEPS
@@ -306,7 +306,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': '7c6b9495b415e59d866df8d10f930b1d34654887',
+  'skia_revision': '5c037eed36a24d282a03bd1f03d2dff74ff69410',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -397,7 +397,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': '189c44f9a96357461a594e16e6bf1d187174a3c4',
+  'devtools_frontend_revision': 'd52a3791eb93361fa24825670284e7bcfb520403',
   # 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.
@@ -421,7 +421,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'b268f525fc231d4f545ae9a40f002b46276bdd17',
+  'dawn_revision': '9ffc1d92cb4b6a599dc8803a9d84f28821c5b27d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -465,7 +465,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'cros_components_revision': 'a16ac80e606d001002ec77dfe847528a1cc5947b',
+  'cros_components_revision': '5a6632957c5dc1b7b34d3099c33eafa1c356e40b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -821,7 +821,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'bd44c4cb90445bd38f361c33924f84a375e17f6f',
+    '3e758b938a904b48f4618173377ce9ad2c6ba408',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1221,7 +1221,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '831ddb26c27ea70c10a67d34ddf4bd41276e667f',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'beef3c68361522775e89249acd82afb5e576b8c4',
     'condition': 'checkout_src_internal',
   },
 
@@ -1994,7 +1994,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'C2OtPysCbdQzrD5sPsG1pmOCxVEF4X0lY_a5DxsHzRIC',
+        'version': 'iYDpKW1V7qCcIDM-19HsAVehP8VCdeCclhd5HSpiRqkC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -2005,7 +2005,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'uCWInBZeShewO9ae6l-kt9I2thnc1yytoKUmv1J2gJ0C',
+        'version': 'GbUGdEjHrnH1y6Yh9D-Kz5B3TUPpbN5PGfl7nM3JXk0C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4028,7 +4028,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'c55e94d4564fb697d3d83fe9fcbafaffce2e139e',
+        'df56fdc8c9370dae4b8e7fc0f07d8c8b5a74d6b5',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/OWNERS b/OWNERS
index 59d1951..38fdbda 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,6 +7,7 @@
 
 per-file .clang-format=thakis@chromium.org
 per-file .clang-tidy=file://styleguide/c++/OWNERS
+per-file .clangd=file://styleguide/c++/OWNERS
 per-file .eslintrc.js=file://tools/web_dev_style/OWNERS
 per-file .gitattributes=*
 per-file .gitignore=*
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 7412ed18..145184d0 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1236,6 +1236,8 @@
     "style/harmonized_colors.h",
     "style/icon_button.cc",
     "style/icon_button.h",
+    "style/keyboard_shortcut_view.cc",
+    "style/keyboard_shortcut_view.h",
     "style/option_button_base.cc",
     "style/option_button_base.h",
     "style/option_button_group.cc",
diff --git a/ash/app_list/views/search_result_inline_icon_view.cc b/ash/app_list/views/search_result_inline_icon_view.cc
index 83d8e6f..a741fcf 100644
--- a/ash/app_list/views/search_result_inline_icon_view.cc
+++ b/ash/app_list/views/search_result_inline_icon_view.cc
@@ -40,10 +40,13 @@
 }  // namespace
 
 SearchResultInlineIconView::SearchResultInlineIconView(
-    bool use_modified_styling)
+    bool use_modified_styling,
+    bool is_first_key)
     : use_modified_styling_(use_modified_styling) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
-  SetProperty(views::kMarginsKey, gfx::Insets::TLBR(0, 6, 0, 6));
+  SetProperty(views::kMarginsKey,
+              gfx::Insets::TLBR(0, is_first_key ? 0 : kLeftRightMargin, 0,
+                                kLeftRightMargin));
 }
 
 SearchResultInlineIconView::~SearchResultInlineIconView() = default;
diff --git a/ash/app_list/views/search_result_inline_icon_view.h b/ash/app_list/views/search_result_inline_icon_view.h
index 3ce1359..ae4d1a8 100644
--- a/ash/app_list/views/search_result_inline_icon_view.h
+++ b/ash/app_list/views/search_result_inline_icon_view.h
@@ -21,11 +21,16 @@
 namespace ash {
 
 // Displays a rounded rect bubble containing styled text xor a vector icon.
+// Setting `use_modified_styling` to `true` changes the style of iconified text
+// for modifier keys like 'ctrl' and 'alt'. Setting `is_first_key` to `true`
+// changes the left margin of the view to 0 so it can be left-aligned with other
+// elements.
 class ASH_EXPORT SearchResultInlineIconView : public views::View {
   METADATA_HEADER(SearchResultInlineIconView, views::View)
 
  public:
-  explicit SearchResultInlineIconView(bool use_modified_styling);
+  SearchResultInlineIconView(bool use_modified_styling,
+                             bool is_first_key = false);
   SearchResultInlineIconView(const SearchResultInlineIconView&) = delete;
   SearchResultInlineIconView& operator=(const SearchResultInlineIconView&) =
       delete;
@@ -39,12 +44,12 @@
  private:
   class SizedLabel;
 
-  // Style iconified text for modifier keys like 'ctrl' and 'alt' differently.
-  const bool use_modified_styling_;
-
   // views::View:
   void OnPaint(gfx::Canvas* canvas) override;
 
+  // Style iconified text for modifier keys like 'ctrl' and 'alt' differently.
+  const bool use_modified_styling_;
+
   // Cached icon used to recolor icon_image_ when OnThemeChanged() is called.
   raw_ptr<const gfx::VectorIcon, ExperimentalAsh> icon_ = nullptr;
 
diff --git a/ash/capture_mode/capture_mode_education_controller.cc b/ash/capture_mode/capture_mode_education_controller.cc
index c97bcb8..b8b92b82 100644
--- a/ash/capture_mode/capture_mode_education_controller.cc
+++ b/ash/capture_mode/capture_mode_education_controller.cc
@@ -15,6 +15,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
 
 namespace ash {
 
@@ -27,12 +28,12 @@
 
 constexpr char kCaptureModeNudgeId[] = "kCaptureModeNudge";
 
-// Clock that can be overridden for testing.
-base::Clock* g_clock_override = nullptr;
-
 // Nudge styling values.
 constexpr int kShortcutIconSize = 60;
 
+// Clock that can be overridden for testing.
+base::Clock* g_clock_override = nullptr;
+
 PrefService* GetPrefService() {
   return Shell::Get()->session_controller()->GetActivePrefService();
 }
@@ -129,6 +130,8 @@
 
   nudge_data.image_model = ui::ImageModel::FromVectorIcon(
       kCaptureModeIcon, kColorAshIconColorPrimary, kShortcutIconSize);
+  nudge_data.keyboard_codes = {ui::VKEY_CONTROL, ui::VKEY_SHIFT,
+                               ui::VKEY_MEDIA_LAUNCH_APP1};
 
   // TODO(b/302368860): Add a new view to display keyboard shortcuts in the same
   // style as the launcher and the new keyboard shortcut app.
diff --git a/ash/capture_mode/capture_mode_education_controller_unittest.cc b/ash/capture_mode/capture_mode_education_controller_unittest.cc
index 1a6505f..e07a501 100644
--- a/ash/capture_mode/capture_mode_education_controller_unittest.cc
+++ b/ash/capture_mode/capture_mode_education_controller_unittest.cc
@@ -9,7 +9,9 @@
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/constants/notifier_catalogs.h"
+#include "ash/public/cpp/ash_view_ids.h"
 #include "ash/shell.h"
+#include "ash/style/keyboard_shortcut_view.h"
 #include "ash/system/toast/anchored_nudge.h"
 #include "ash/system/toast/anchored_nudge_manager_impl.h"
 #include "ash/test/ash_test_base.h"
@@ -131,6 +133,34 @@
   ~CaptureModeEducationShortcutNudgeTest() override = default;
 };
 
+TEST_F(CaptureModeEducationShortcutNudgeTest, CorrectStyling) {
+  base::SimpleTestClock test_clock;
+  CaptureModeEducationControllerTest::SetOverrideClock(&test_clock);
+
+  // Advance clock so we aren't at zero time.
+  test_clock.Advance(base::Hours(25));
+
+  // Attempt to use the Windows Snipping Tool (capture bar) shortcut.
+  PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN);
+
+  // Get the list of visible nudges from the nudge manager and make sure our
+  // education nudge is in the list and visible.
+  AnchoredNudge* nudge =
+      Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown(
+          kCaptureModeNudgeId);
+  ASSERT_TRUE(nudge);
+  EXPECT_TRUE(nudge->GetVisible());
+
+  // The keyboard shortcut view should be visible.
+  auto* shortcut_view = views::AsViewClass<KeyboardShortcutView>(
+      nudge->GetContentsView()->GetViewByID(
+          VIEW_ID_SYSTEM_NUDGE_SHORTCUT_VIEW));
+  ASSERT_TRUE(shortcut_view);
+  EXPECT_TRUE(shortcut_view->GetVisible());
+
+  CaptureModeEducationControllerTest::SetOverrideClock(nullptr);
+}
+
 TEST_F(CaptureModeEducationShortcutNudgeTest, EducationPreferencesShowLimit) {
   base::SimpleTestClock test_clock;
   CaptureModeEducationControllerTest::SetOverrideClock(&test_clock);
diff --git a/ash/components/arc/metrics/arc_wm_metrics.cc b/ash/components/arc/metrics/arc_wm_metrics.cc
index f4f66efa..942cbcb 100644
--- a/ash/components/arc/metrics/arc_wm_metrics.cc
+++ b/ash/components/arc/metrics/arc_wm_metrics.cc
@@ -118,7 +118,7 @@
             ArcWmMetrics::GetWindowEnterTabletModeTimeHistogramName(app_type),
             window_operation_elapsed_timer_.Elapsed(),
             /*minimum=*/base::Milliseconds(1),
-            /*maximum=*/base::Seconds(5), 100);
+            /*maximum=*/base::Seconds(2), 100);
       }
     } else {
       if (state->IsMaximized()) {
@@ -126,7 +126,7 @@
             ArcWmMetrics::GetWindowMaximizedTimeHistogramName(app_type),
             window_operation_elapsed_timer_.Elapsed(),
             /*minimum=*/base::Milliseconds(1),
-            /*maximum=*/base::Seconds(3), 100);
+            /*maximum=*/base::Seconds(2), 100);
       } else if (state->IsMinimized()) {
         base::UmaHistogramCustomTimes(
             ArcWmMetrics::GetWindowMinimizedTimeHistogramName(app_type),
@@ -138,7 +138,7 @@
             ArcWmMetrics::GetWindowExitTabletModeTimeHistogramName(app_type),
             window_operation_elapsed_timer_.Elapsed(),
             /*minimum=*/base::Milliseconds(1),
-            /*maximum=*/base::Seconds(5), 100);
+            /*maximum=*/base::Seconds(2), 100);
       }
     }
   }
@@ -181,7 +181,7 @@
         ArcWmMetrics::GetArcWindowClosedTimeHistogramName(),
         window_close_elapsed_timer_.Elapsed(),
         /*minimum=*/base::Milliseconds(1),
-        /*maximum=*/base::Seconds(3), 100);
+        /*maximum=*/base::Seconds(2), 100);
   }
 
   // Tracks the elapsed time from the window closing operation happens until the
diff --git a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
index 8fd124c6..57ca172 100644
--- a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
+++ b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -284,7 +284,8 @@
   // Note that dynamic bitrate mode changes are not allowed. Attempting to
   // change the bitrate mode at runtime will result in the |accelerator_|
   // reporting an error through NotifyError.
-  accelerator_->RequestEncodingParametersChange(bitrate, framerate);
+  accelerator_->RequestEncodingParametersChange(bitrate, framerate,
+                                                absl::nullopt);
 }
 
 void GpuArcVideoEncodeAccelerator::RequestEncodingParametersChangeDeprecated(
@@ -296,7 +297,7 @@
     return;
   }
   accelerator_->RequestEncodingParametersChange(
-      media::Bitrate::ConstantBitrate(bitrate), framerate);
+      media::Bitrate::ConstantBitrate(bitrate), framerate, absl::nullopt);
 }
 
 void GpuArcVideoEncodeAccelerator::Flush(FlushCallback callback) {
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc
index 4f7acf9..efd280b 100644
--- a/ash/host/ash_window_tree_host_platform.cc
+++ b/ash/host/ash_window_tree_host_platform.cc
@@ -200,6 +200,13 @@
       input_controller_);
 }
 
+void AshWindowTreeHostPlatform::OnDamageRect(const gfx::Rect& damage_rect) {
+  if (ignore_platform_damage_rect_for_test_) {
+    return;
+  }
+  return aura::WindowTreeHostPlatform::OnDamageRect(damage_rect);
+}
+
 void AshWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
   TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
   if (event->IsLocatedEvent())
diff --git a/ash/host/ash_window_tree_host_platform.h b/ash/host/ash_window_tree_host_platform.h
index fed34e9..332a16c 100644
--- a/ash/host/ash_window_tree_host_platform.h
+++ b/ash/host/ash_window_tree_host_platform.h
@@ -38,6 +38,10 @@
 
   ~AshWindowTreeHostPlatform() override;
 
+  void set_ignore_platform_damage_rect_for_test(bool ignore) {
+    ignore_platform_damage_rect_for_test_ = ignore;
+  }
+
  protected:
   friend ExtendedMouseWarpControllerTest;
   FRIEND_TEST_ALL_PREFIXES(ExtendedMouseWarpControllerTest,
@@ -70,6 +74,7 @@
       const gfx::Size& host_size_in_pixels) const override;
   void OnCursorVisibilityChangedNative(bool show) override;
   void SetBoundsInPixels(const gfx::Rect& bounds) override;
+  void OnDamageRect(const gfx::Rect& damage_rect) override;
   void DispatchEvent(ui::Event* event) override;
   std::unique_ptr<aura::ScopedEnableUnadjustedMouseEvents>
   RequestUnadjustedMovement() override;
@@ -90,6 +95,8 @@
       input_controller_ = nullptr;
 
   gfx::Rect last_cursor_confine_bounds_in_pixels_;
+
+  bool ignore_platform_damage_rect_for_test_ = false;
 };
 
 }  // namespace ash
diff --git a/ash/metrics/login_unlock_throughput_recorder_unittest.cc b/ash/metrics/login_unlock_throughput_recorder_unittest.cc
index a36b08f0..ebd4520 100644
--- a/ash/metrics/login_unlock_throughput_recorder_unittest.cc
+++ b/ash/metrics/login_unlock_throughput_recorder_unittest.cc
@@ -20,6 +20,7 @@
 #include "chromeos/ash/components/login/login_state/login_state.h"
 #include "components/app_constants/constants.h"
 #include "ui/aura/window_tree_host.h"
+#include "ui/compositor/test/begin_main_frame_waiter.h"
 #include "ui/compositor/test/draw_waiter_for_test.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
@@ -117,39 +118,6 @@
   const raw_ptr<ui::Compositor> compositor_;
 };
 
-class BeginMainFrameWaiter : public ui::CompositorObserver {
- public:
-  explicit BeginMainFrameWaiter(ui::Compositor* compositor)
-      : compositor_(compositor) {
-    compositor->AddObserver(this);
-  }
-
-  ~BeginMainFrameWaiter() override { compositor_->RemoveObserver(this); }
-
-  // ui::CompositorObserver
-  void OnDidBeginMainFrame(ui::Compositor* compositor) override {
-    DCHECK_EQ(compositor_, compositor);
-    done_ = true;
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  void Wait() {
-    if (done_)
-      return;
-
-    run_loop_ = std::make_unique<base::RunLoop>(
-        base::RunLoop::Type::kNestableTasksAllowed);
-    run_loop_->Run();
-    run_loop_.reset();
-  }
-
- private:
-  const raw_ptr<ui::Compositor> compositor_;
-  bool done_ = false;
-  std::unique_ptr<base::RunLoop> run_loop_;
-};
-
 class FirstNonAnimatedFrameStartedWaiter : public ui::CompositorObserver {
  public:
   explicit FirstNonAnimatedFrameStartedWaiter(ui::Compositor* compositor)
@@ -307,7 +275,7 @@
     ui::Compositor* compositor =
         Shell::GetPrimaryRootWindow()->GetHost()->compositor();
     TestObserver observer(compositor);
-    BeginMainFrameWaiter(compositor).Wait();
+    ui::BeginMainFrameWaiter(compositor).Wait();
     FirstNonAnimatedFrameStartedWaiter(compositor).Wait();
     ui::DrawWaiterForTest::WaitForCompositingEnded(compositor);
   }
diff --git a/ash/public/cpp/ash_view_ids.h b/ash/public/cpp/ash_view_ids.h
index 7b1c3d4..8abad4c1 100644
--- a/ash/public/cpp/ash_view_ids.h
+++ b/ash/public/cpp/ash_view_ids.h
@@ -109,6 +109,7 @@
   VIEW_ID_SYSTEM_NUDGE_IMAGE_VIEW,
   VIEW_ID_SYSTEM_NUDGE_TITLE_LABEL,
   VIEW_ID_SYSTEM_NUDGE_BODY_LABEL,
+  VIEW_ID_SYSTEM_NUDGE_SHORTCUT_VIEW,
   VIEW_ID_SYSTEM_NUDGE_PRIMARY_BUTTON,
   VIEW_ID_SYSTEM_NUDGE_SECONDARY_BUTTON,
   VIEW_ID_SYSTEM_NUDGE_CLOSE_BUTTON,
diff --git a/ash/public/cpp/system/anchored_nudge_data.h b/ash/public/cpp/system/anchored_nudge_data.h
index 09505a9..204fbaf 100644
--- a/ash/public/cpp/system/anchored_nudge_data.h
+++ b/ash/public/cpp/system/anchored_nudge_data.h
@@ -13,6 +13,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/functional/callback_helpers.h"
 #include "base/time/time.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_border.h"
 #include "ui/views/view_tracker.h"
@@ -73,10 +74,11 @@
   NudgeCatalogName catalog_name;
   std::u16string body_text;
 
-  // Optional system nudge view elements. If not empty, a leading image or nudge
-  // title will be created.
+  // Optional system nudge view elements. If not empty, a leading image, nudge
+  // title, or keyboard shortcut view will be created.
   ui::ImageModel image_model;
   std::u16string title_text;
+  std::vector<ui::KeyboardCode> keyboard_codes;
 
   // Callback for close button pressed.
   base::RepeatingClosure close_button_callback;
diff --git a/ash/shelf/assistant_overlay.cc b/ash/shelf/assistant_overlay.cc
index 6d33509..05a1977 100644
--- a/ash/shelf/assistant_overlay.cc
+++ b/ash/shelf/assistant_overlay.cc
@@ -18,7 +18,6 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_id.h"
 #include "ash/system/tray/tray_popup_utils.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/command_line.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index f40c835..1345213 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -28,7 +28,6 @@
 #include "ash/style/ash_color_provider.h"
 #include "ash/style/typography.h"
 #include "ash/user_education/user_education_class_properties.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/check_op.h"
 #include "base/i18n/rtl.h"
 #include "base/memory/raw_ptr.h"
@@ -432,7 +431,7 @@
 void HomeButton::ButtonPressed(views::Button* sender,
                                const ui::Event& event,
                                views::InkDrop* ink_drop) {
-  if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+  if (display::Screen::GetScreen()->InTabletMode()) {
     base::RecordAction(
         base::UserMetricsAction("AppList_HomeButtonPressedTablet"));
   } else {
diff --git a/ash/shelf/home_button_controller.cc b/ash/shelf/home_button_controller.cc
index 62396b9d..877e784 100644
--- a/ash/shelf/home_button_controller.cc
+++ b/ash/shelf/home_button_controller.cc
@@ -12,7 +12,6 @@
 #include "ash/shelf/home_button.h"
 #include "ash/shelf/shelf_button.h"
 #include "ash/shell.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "base/metrics/histogram_macros.h"
@@ -21,6 +20,7 @@
 #include "chromeos/constants/chromeos_features.h"
 #include "components/account_id/account_id.h"
 #include "ui/display/screen.h"
+#include "ui/display/tablet_state.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_state.h"
 #include "ui/views/widget/widget.h"
@@ -47,7 +47,6 @@
 
   Shell* shell = Shell::Get();
   shell->app_list_controller()->AddObserver(this);
-  shell->tablet_mode_controller()->AddObserver(this);
   AssistantUiController::Get()->GetModel()->AddObserver(this);
   AssistantState::Get()->AddObserver(this);
 }
@@ -55,14 +54,12 @@
 HomeButtonController::~HomeButtonController() {
   Shell* shell = Shell::Get();
 
-  // AppListController and TabletModeController are destroyed early when Shell
-  // is being destroyed, so they may not exist.
+  // AppListController are destroyed early when Shel is being destroyed, so they
+  // may not exist.
   if (AssistantUiController::Get())
     AssistantUiController::Get()->GetModel()->RemoveObserver(this);
   if (shell->app_list_controller())
     shell->app_list_controller()->RemoveObserver(this);
-  if (shell->tablet_mode_controller())
-    shell->tablet_mode_controller()->RemoveObserver(this);
   if (AssistantState::Get())
     AssistantState::Get()->RemoveObserver(this);
 }
@@ -154,7 +151,12 @@
     OnAppListDismissed();
 }
 
-void HomeButtonController::OnTabletModeStarted() {
+void HomeButtonController::OnDisplayTabletStateChanged(
+    display::TabletState state) {
+  if (state != display::TabletState::kInTabletMode) {
+    return;
+  }
+
   if (!chromeos::features::IsJellyEnabled()) {
     views::InkDrop::Get(button_)->AnimateToState(
         views::InkDropState::DEACTIVATED, nullptr);
diff --git a/ash/shelf/home_button_controller.h b/ash/shelf/home_button_controller.h
index dfee48a..cffcc10 100644
--- a/ash/shelf/home_button_controller.h
+++ b/ash/shelf/home_button_controller.h
@@ -10,8 +10,12 @@
 #include "ash/assistant/model/assistant_ui_model_observer.h"
 #include "ash/public/cpp/app_list/app_list_controller_observer.h"
 #include "ash/public/cpp/assistant/assistant_state.h"
-#include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/memory/raw_ptr.h"
+#include "ui/display/display_observer.h"
+
+namespace display {
+enum class TabletState;
+}  // namespace display
 
 namespace ui {
 class GestureEvent;
@@ -26,7 +30,7 @@
 // action (for Assistant).
 // Behavior is tested indirectly in HomeButtonTest and ShelfViewInkDropTest.
 class HomeButtonController : public AppListControllerObserver,
-                             public TabletModeObserver,
+                             public display::DisplayObserver,
                              public AssistantStateObserver,
                              public AssistantUiModelObserver {
  public:
@@ -52,8 +56,8 @@
   // AppListControllerObserver:
   void OnAppListVisibilityWillChange(bool shown, int64_t display_id) override;
 
-  // TabletModeObserver:
-  void OnTabletModeStarted() override;
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
 
   // AssistantStateObserver:
   void OnAssistantFeatureAllowedChanged(
@@ -81,6 +85,8 @@
   // Owned by the button's view hierarchy.
   raw_ptr<AssistantOverlay, ExperimentalAsh> assistant_overlay_ = nullptr;
   std::unique_ptr<base::OneShotTimer> assistant_animation_delay_timer_;
+
+  display::ScopedDisplayObserver display_observer_{this};
 };
 
 }  // namespace ash
diff --git a/ash/shelf/hotseat_transition_animator.cc b/ash/shelf/hotseat_transition_animator.cc
index 4a79154..684bb01 100644
--- a/ash/shelf/hotseat_transition_animator.cc
+++ b/ash/shelf/hotseat_transition_animator.cc
@@ -10,7 +10,6 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/metrics/histogram_macros.h"
@@ -18,6 +17,7 @@
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/display/screen.h"
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -165,7 +165,7 @@
           old_state == HotseatState::kShownHomeLauncher) &&
          !(new_state == HotseatState::kShownClamshell ||
            old_state == HotseatState::kShownClamshell) &&
-         Shell::Get()->tablet_mode_controller()->InTabletMode();
+         display::Screen::GetScreen()->InTabletMode();
 }
 
 void HotseatTransitionAnimator::NotifyHotseatTransitionAnimationEnded(
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc
index 4bacf205f..ad39a87 100644
--- a/ash/shelf/hotseat_widget.cc
+++ b/ash/shelf/hotseat_widget.cc
@@ -24,7 +24,6 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_observer.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/i18n/rtl.h"
@@ -36,6 +35,7 @@
 #include "ui/compositor/animation_throughput_reporter.h"
 #include "ui/compositor/layer_animation_sequence.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/display/screen.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/views/background.h"
 #include "ui/views/highlight_border.h"
@@ -752,8 +752,7 @@
 }
 
 bool HotseatWidget::ShouldShowHotseatBackground() {
-  return Shell::Get()->tablet_mode_controller() &&
-         Shell::Get()->tablet_mode_controller()->InTabletMode();
+  return display::Screen::GetScreen()->InTabletMode();
 }
 
 void HotseatWidget::Initialize(aura::Window* container, Shelf* shelf) {
diff --git a/ash/shelf/hotseat_widget_unittest.cc b/ash/shelf/hotseat_widget_unittest.cc
index 112d558..1d39e503 100644
--- a/ash/shelf/hotseat_widget_unittest.cc
+++ b/ash/shelf/hotseat_widget_unittest.cc
@@ -55,6 +55,7 @@
 #include "ui/compositor/presentation_time_recorder.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/display/screen.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/views/test/widget_animation_waiter.h"
@@ -135,7 +136,7 @@
     // If the launcher button is not expected to be shown, show the assistant UI
     // directly; otherwise, simulate the long press on the home button,
     if (!navigation_buttons_shown_in_tablet_mode_ &&
-        Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+        display::Screen::GetScreen()->InTabletMode()) {
       AssistantUiController::Get()->ShowUi(
           assistant::AssistantEntryPoint::kLongPressLauncher);
       return;
@@ -161,7 +162,7 @@
     // If the launcher button is not expected to be shown, go home directly;
     // otherwise, simulate tap on the home button,
     if (!navigation_buttons_shown_in_tablet_mode_ &&
-        Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+        display::Screen::GetScreen()->InTabletMode()) {
       Shell::Get()->app_list_controller()->GoHome(GetPrimaryDisplay().id());
       return;
     }
@@ -182,7 +183,7 @@
     // directly; otherwise, simulate tap on the overview button, which should
     // toggle overview.
     if (!navigation_buttons_shown_in_tablet_mode_ &&
-        Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+        display::Screen::GetScreen()->InTabletMode()) {
       EnterOverview();
       return;
     }
@@ -202,7 +203,7 @@
     // directly; otherwise, simulate tap on the overview button, which should
     // toggle overview.
     if (!navigation_buttons_shown_in_tablet_mode_ &&
-        Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+        display::Screen::GetScreen()->InTabletMode()) {
       ExitOverview();
       return;
     }
diff --git a/ash/shelf/launcher_nudge_controller.cc b/ash/shelf/launcher_nudge_controller.cc
index 576a9ae..d2bd8f5c 100644
--- a/ash/shelf/launcher_nudge_controller.cc
+++ b/ash/shelf/launcher_nudge_controller.cc
@@ -26,6 +26,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/display/tablet_state.h"
 
 namespace ash {
 namespace {
@@ -83,13 +84,11 @@
 LauncherNudgeController::LauncherNudgeController()
     : show_nudge_timer_(std::make_unique<base::WallClockTimer>()) {
   Shell::Get()->app_list_controller()->AddObserver(this);
-  tablet_mode_observation_.Observe(Shell::Get()->tablet_mode_controller());
 }
 
 LauncherNudgeController::~LauncherNudgeController() {
   if (Shell::Get()->app_list_controller())
     Shell::Get()->app_list_controller()->RemoveObserver(this);
-  tablet_mode_observation_.Reset();
 }
 
 // static
@@ -297,7 +296,12 @@
   }
 }
 
-void LauncherNudgeController::OnTabletModeEnded() {
+void LauncherNudgeController::OnDisplayTabletStateChanged(
+    display::TabletState state) {
+  if (state != display::TabletState::kInClamshellMode) {
+    return;
+  }
+
   // If a nudge event became available while the device was in tablet mode, it
   // would have been ignored. Recheck whether the nudge can be shown again. Note
   // that the nudge is designed to be shown after
@@ -307,10 +311,6 @@
   MaybeShowNudge();
 }
 
-void LauncherNudgeController::OnTabletControllerDestroyed() {
-  tablet_mode_observation_.Reset();
-}
-
 base::Time LauncherNudgeController::GetNow() const {
   if (clock_for_test_)
     return clock_for_test_->Now();
@@ -318,4 +318,4 @@
   return base::Time::Now();
 }
 
-}  // namespace ash
\ No newline at end of file
+}  // namespace ash
diff --git a/ash/shelf/launcher_nudge_controller.h b/ash/shelf/launcher_nudge_controller.h
index b89a1fe..0a7a30e 100644
--- a/ash/shelf/launcher_nudge_controller.h
+++ b/ash/shelf/launcher_nudge_controller.h
@@ -10,12 +10,11 @@
 #include "ash/ash_export.h"
 #include "ash/public/cpp/app_list/app_list_controller_observer.h"
 #include "ash/public/cpp/session/session_observer.h"
-#include "ash/public/cpp/tablet_mode_observer.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
+#include "ui/display/display_observer.h"
 
 namespace base {
 class Clock;
@@ -23,6 +22,10 @@
 class WallClockTimer;
 }  // namespace base
 
+namespace display {
+enum class TabletState;
+}  // namespace display
+
 class PrefRegistrySimple;
 class PrefService;
 
@@ -34,7 +37,7 @@
 // open the launcher. The animation is implemented in HomeButton class.
 class ASH_EXPORT LauncherNudgeController : public SessionObserver,
                                            public AppListControllerObserver,
-                                           public TabletModeObserver {
+                                           public display::DisplayObserver {
  public:
   // Maximum number of times that the nudge will be shown to the users.
   static constexpr int kMaxShownCount = 3;
@@ -96,9 +99,8 @@
   // AppListControllerObserver:
   void OnAppListVisibilityChanged(bool shown, int64_t display_id) override;
 
-  // TabletModeObserver:
-  void OnTabletModeEnded() override;
-  void OnTabletControllerDestroyed() override;
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
 
   // Returns the current time. The clock may be overridden for testing.
   base::Time GetNow() const;
@@ -113,8 +115,7 @@
   base::Time earliest_available_time_;
 
   ScopedSessionObserver session_observer_{this};
-  base::ScopedObservation<TabletModeController, TabletModeObserver>
-      tablet_mode_observation_{this};
+  display::ScopedDisplayObserver display_observer_{this};
 
   base::WeakPtrFactory<LauncherNudgeController> weak_ptr_factory_{this};
 };
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index 794ad22..b6d3f3a 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -19,7 +19,6 @@
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/wm/desks/desk_button/desk_button.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_forward.h"
 #include "base/i18n/rtl.h"
@@ -2045,7 +2044,7 @@
 
 gfx::Insets ScrollableShelfView::CalculateRipplePaddingInsets() const {
   // Indicates whether it is in tablet mode with hotseat enabled.
-  const bool in_tablet_mode = Shell::Get()->IsInTabletMode();
+  const bool in_tablet_mode = display::Screen::GetScreen()->InTabletMode();
 
   const int ripple_padding =
       ShelfConfig::Get()->scrollable_shelf_ripple_padding();
@@ -2064,16 +2063,9 @@
 
 gfx::RoundedCornersF
 ScrollableShelfView::CalculateShelfContainerRoundedCorners() const {
-  // This function may access TabletModeController during destruction of
-  // Hotseat. However, TabletModeController is destructed before Hotseat. So
-  // check the pointer explicitly here.
-  // TODO(https://crbug.com/1067490): reorder the destruction order in
-  // Shell::~Shell then remove the explicit check.
-  const bool is_in_tablet_mode =
-      Shell::Get()->tablet_mode_controller() && Shell::Get()->IsInTabletMode();
-
-  if (!is_in_tablet_mode)
+  if (!display::Screen::GetScreen()->InTabletMode()) {
     return gfx::RoundedCornersF();
+  }
 
   const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment();
   const float radius = (is_horizontal_alignment ? height() : width()) / 2.f;
@@ -2257,12 +2249,9 @@
   // Only enable shelf rounded corners in tablet mode. Note that we allow
   // disabling rounded corners in clamshell. Because when switching to clamshell
   // from tablet, this method may be called after tablet mode ends.
-  // TODO(https://crbug.com/1067490): reorder the destruction order in
-  // Shell::~Shell then remove the explicit check.
-  const bool is_in_tablet_mode =
-      Shell::Get()->tablet_mode_controller() && Shell::Get()->IsInTabletMode();
-  if (enable && !is_in_tablet_mode)
+  if (enable && !display::Screen::GetScreen()->InTabletMode()) {
     return;
+  }
 
   ui::Layer* layer = shelf_container_view_->layer();
 
@@ -2310,14 +2299,10 @@
   if (layout_strategy_ != LayoutStrategy::kNotShowArrowButtons)
     return true;
 
-  // TODO(https://crbug.com/1067490): reorder the destruction order in
-  // Shell::~Shell then remove the explicit check.
-  const bool is_in_tablet_mode =
-      Shell::Get()->tablet_mode_controller() && Shell::Get()->IsInTabletMode();
-
   // In clamshell, only use layer clip in overflow mode.
-  if (!is_in_tablet_mode)
+  if (!display::Screen::GetScreen()->InTabletMode()) {
     return false;
+  }
 
   // In tablet mode, whether using layer clip in non-overflow mode depends on
   // |layer_clip_in_non_overflow_|.
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
index 19bb708c..f5258ce 100644
--- a/ash/shelf/shelf_app_button.cc
+++ b/ash/shelf/shelf_app_button.cc
@@ -21,7 +21,6 @@
 #include "ash/style/style_util.h"
 #include "ash/system/progress_indicator/progress_indicator.h"
 #include "ash/wm/desks/desks_controller.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_util.h"
 #include "base/debug/stack_trace.h"
 #include "base/functional/bind.h"
@@ -39,6 +38,7 @@
 #include "ui/color/color_id.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/display/screen.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/throb_animation.h"
 #include "ui/gfx/canvas.h"
@@ -856,7 +856,7 @@
   // Add padding to the ink drop for the left-most and right-most app buttons in
   // the shelf when there is a non-zero padding between the app icon and the
   // end of scrollable shelf.
-  if (TabletModeController::Get()->InTabletMode() && padding > 0) {
+  if (display::Screen::GetScreen()->InTabletMode() && padding > 0) {
     // Note that `current_index` may be nullopt while the button is fading out
     // after it's been removed from the model - for example, see
     // https://crbug.com/1355561.
diff --git a/ash/shelf/shelf_background_animator.cc b/ash/shelf/shelf_background_animator.cc
index c6572b0..bb6af85 100644
--- a/ash/shelf/shelf_background_animator.cc
+++ b/ash/shelf/shelf_background_animator.cc
@@ -16,7 +16,6 @@
 #include "ash/shell.h"
 #include "ash/style/ash_color_id.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/time/time.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/gfx/animation/slide_animation.h"
@@ -228,7 +227,7 @@
       break;
     case ShelfBackgroundType::kOverview:
       shelf_target_color =
-          Shell::Get()->tablet_mode_controller()->InTabletMode()
+          display::Screen::GetScreen()->InTabletMode()
               ? ShelfConfig::Get()->GetMaximizedShelfColor(shelf_widget)
               : ShelfConfig::Get()->GetDefaultShelfColor(shelf_widget);
       break;
diff --git a/ash/shelf/shelf_config_unittest.cc b/ash/shelf/shelf_config_unittest.cc
index b10d4886..7913748b 100644
--- a/ash/shelf/shelf_config_unittest.cc
+++ b/ash/shelf/shelf_config_unittest.cc
@@ -11,6 +11,7 @@
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/command_line.h"
+#include "ui/display/screen.h"
 #include "ui/views/widget/widget.h"
 
 namespace ash {
@@ -23,9 +24,7 @@
  protected:
   bool is_dense() { return ShelfConfig::Get()->is_dense_; }
 
-  bool IsTabletMode() {
-    return Shell::Get()->tablet_mode_controller()->InTabletMode();
-  }
+  bool IsTabletMode() { return display::Screen::GetScreen()->InTabletMode(); }
 
   void SetTabletMode(bool is_tablet_mode) {
     Shell::Get()->tablet_mode_controller()->SetEnabledForTest(is_tablet_mode);
diff --git a/ash/shelf/shelf_context_menu_model.cc b/ash/shelf/shelf_context_menu_model.cc
index b3be4976..0ca3318 100644
--- a/ash/shelf/shelf_context_menu_model.cc
+++ b/ash/shelf/shelf_context_menu_model.cc
@@ -27,7 +27,6 @@
 #include "ash/shelf/shelf_metrics.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/user_metrics.h"
 #include "base/numerics/safe_conversions.h"
@@ -96,7 +95,7 @@
     return;
 
   // Clamshell mode only options should not activate in tablet mode.
-  const bool is_tablet_mode = shell->tablet_mode_controller()->InTabletMode();
+  const bool is_tablet_mode = display::Screen::GetScreen()->InTabletMode();
   switch (command_id) {
     case MENU_AUTO_HIDE:
       SetShelfAutoHideBehaviorPref(
@@ -191,8 +190,7 @@
   // (regular or Family Link user). In tablet mode, the shelf alignment option
   // is not shown.
   LoginStatus status = Shell::Get()->session_controller()->login_status();
-  const bool in_tablet_mode =
-      Shell::Get()->tablet_mode_controller()->InTabletMode();
+  const bool in_tablet_mode = display::Screen::GetScreen()->InTabletMode();
   if ((status == LoginStatus::USER || status == LoginStatus::CHILD) &&
       !in_tablet_mode &&
       prefs->FindPreference(prefs::kShelfAlignmentLocal)->IsUserModifiable()) {
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc
index a97b635c..3e97732 100644
--- a/ash/shelf/shelf_control_button.cc
+++ b/ash/shelf/shelf_control_button.cc
@@ -9,7 +9,6 @@
 #include "ash/shelf/shelf_button_delegate.h"
 #include "ash/shell.h"
 #include "ash/style/style_util.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/ash/shelf/shelf_controller.cc b/ash/shelf/shelf_controller.cc
index edae988..24aceac 100644
--- a/ash/shelf/shelf_controller.cc
+++ b/ash/shelf/shelf_controller.cc
@@ -18,7 +18,6 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
@@ -30,6 +29,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/display/tablet_state.h"
 
 namespace ash {
 
@@ -77,7 +77,7 @@
 
   // Tablet mode uses bottom aligned shelf, don't override it if the shelf
   // prefs change.
-  if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+  if (display::Screen::GetScreen()->InTabletMode()) {
     return;
   }
 
@@ -109,7 +109,7 @@
 
   // The shelf should always be bottom-aligned in tablet mode; alignment is
   // assigned from prefs when tablet mode is exited.
-  if (Shell::Get()->tablet_mode_controller()->InTabletMode()) {
+  if (display::Screen::GetScreen()->InTabletMode()) {
     return;
   }
 
@@ -122,7 +122,6 @@
   ShelfModel::SetInstance(&model_);
 
   Shell::Get()->session_controller()->AddObserver(this);
-  Shell::Get()->tablet_mode_controller()->AddObserver(this);
   Shell::Get()->window_tree_host_manager()->AddObserver(this);
   model_.AddObserver(this);
 }
@@ -138,7 +137,6 @@
 void ShelfController::Shutdown() {
   model_.RemoveObserver(this);
   Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
-  Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
   Shell::Get()->session_controller()->RemoveObserver(this);
 }
 
@@ -224,30 +222,34 @@
   UpdateAppNotificationBadging();
 }
 
-void ShelfController::OnTabletModeStarted() {
+void ShelfController::OnDisplayTabletStateChanged(display::TabletState state) {
   // Do nothing when running in app mode.
   if (Shell::Get()->session_controller()->IsRunningInAppMode())
     return;
 
-  if (base::FeatureList::IsEnabled(features::kShelfAutoHideSeparation)) {
-    SetShelfAutoHideFromPrefs();
+  switch (state) {
+    case display::TabletState::kEnteringTabletMode:
+    case display::TabletState::kExitingTabletMode:
+      // Do nothing when the tablet state is in the process of transition.
+      break;
+    case display::TabletState::kInTabletMode:
+      if (base::FeatureList::IsEnabled(features::kShelfAutoHideSeparation)) {
+        SetShelfAutoHideFromPrefs();
+      }
+
+      // Force the shelf to be bottom aligned in tablet mode; the prefs are
+      // restored on exit.
+      for (const auto& display :
+           display::Screen::GetScreen()->GetAllDisplays()) {
+        if (Shelf* shelf = GetShelfForDisplay(display.id())) {
+          shelf->SetAlignment(ShelfAlignment::kBottom);
+        }
+      }
+      break;
+    case display::TabletState::kInClamshellMode:
+      SetShelfBehaviorsFromPrefs();
+      break;
   }
-
-  // Force the shelf to be bottom aligned in tablet mode; the prefs are restored
-  // on exit.
-  for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
-    if (Shelf* shelf = GetShelfForDisplay(display.id())) {
-      shelf->SetAlignment(ShelfAlignment::kBottom);
-    }
-  }
-}
-
-void ShelfController::OnTabletModeEnded() {
-  // Do nothing when running in app mode.
-  if (Shell::Get()->session_controller()->IsRunningInAppMode())
-    return;
-
-  SetShelfBehaviorsFromPrefs();
 }
 
 void ShelfController::OnDisplayConfigurationChanged() {
diff --git a/ash/shelf/shelf_controller.h b/ash/shelf/shelf_controller.h
index b6f7a351..fc4bfd5 100644
--- a/ash/shelf/shelf_controller.h
+++ b/ash/shelf/shelf_controller.h
@@ -13,15 +13,19 @@
 #include "ash/public/cpp/session/session_observer.h"
 #include "ash/public/cpp/shelf_model.h"
 #include "ash/public/cpp/shelf_model_observer.h"
-#include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/memory/raw_ptr.h"
 #include "base/scoped_observation.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_update.h"
+#include "ui/display/display_observer.h"
 
 class PrefChangeRegistrar;
 class PrefRegistrySimple;
 
+namespace display {
+enum class TabletState;
+}  // namespace display
+
 namespace ash {
 
 class LauncherNudgeController;
@@ -29,7 +33,7 @@
 // ShelfController owns the ShelfModel and manages shelf preferences.
 // ChromeShelfController and related classes largely manage the ShelfModel.
 class ASH_EXPORT ShelfController : public SessionObserver,
-                                   public TabletModeObserver,
+                                   public display::DisplayObserver,
                                    public WindowTreeHostManager::Observer,
                                    public apps::AppRegistryCache::Observer,
                                    public ShelfModelObserver {
@@ -60,9 +64,8 @@
   // SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
 
-  // TabletModeObserver:
-  void OnTabletModeStarted() override;
-  void OnTabletModeEnded() override;
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
 
   // WindowTreeHostManager::Observer:
   void OnDisplayConfigurationChanged() override;
@@ -99,6 +102,8 @@
   base::ScopedObservation<apps::AppRegistryCache,
                           apps::AppRegistryCache::Observer>
       app_registry_cache_observer_{this};
+
+  display::ScopedDisplayObserver display_observer_{this};
 };
 
 }  // namespace ash
diff --git a/ash/shelf/shelf_navigation_widget.cc b/ash/shelf/shelf_navigation_widget.cc
index 5166c06..258d5c6 100644
--- a/ash/shelf/shelf_navigation_widget.cc
+++ b/ash/shelf/shelf_navigation_widget.cc
@@ -18,7 +18,6 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/status_area_widget.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/functional/bind.h"
 #include "base/i18n/rtl.h"
 #include "base/memory/raw_ptr.h"
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index a043e343..37ece6f 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -45,7 +45,6 @@
 #include "ash/user_education/user_education_class_properties.h"
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/mru_window_tracker.h"
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_util.h"
 #include "base/auto_reset.h"
 #include "base/check_op.h"
@@ -135,12 +134,6 @@
 constexpr char kShelfIconFadeOutAnimationHistogram[] =
     "Ash.ShelfIcon.AnimationSmoothness.FadeOut";
 
-// Helper to check if tablet mode is enabled.
-bool IsTabletModeEnabled() {
-  return Shell::Get()->tablet_mode_controller() &&
-         Shell::Get()->tablet_mode_controller()->InTabletMode();
-}
-
 // A class to temporarily disable a given bounds animator.
 class BoundsAnimatorDisabler {
  public:
@@ -362,7 +355,6 @@
       shelf_button_delegate_(shelf_button_delegate) {
   DCHECK(model_);
   DCHECK(shelf_);
-  Shell::Get()->tablet_mode_controller()->AddObserver(this);
   Shell::Get()->AddShellObserver(this);
   shelf_->AddObserver(this);
   bounds_animator_->AddObserver(this);
@@ -384,9 +376,6 @@
 }
 
 ShelfView::~ShelfView() {
-  // Shell destroys the TabletModeController before destroying all root windows.
-  if (Shell::Get()->tablet_mode_controller())
-    Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
   shelf_->RemoveObserver(this);
   Shell::Get()->RemoveShellObserver(this);
   bounds_animator_->RemoveObserver(this);
@@ -862,18 +851,18 @@
       display_id, context_menu_callback_.callback());
 }
 
-void ShelfView::OnTabletModeStarted() {
-  // Close all menus when tablet mode starts to ensure that the clamshell only
-  // context menu options are not available in tablet mode.
-  if (shelf_menu_model_adapter_)
-    shelf_menu_model_adapter_->Cancel();
-}
+void ShelfView::OnDisplayTabletStateChanged(display::TabletState state) {
+  if (state != display::TabletState::kInClamshellMode &&
+      state != display::TabletState::kInTabletMode) {
+    return;
+  }
 
-void ShelfView::OnTabletModeEnded() {
-  // Close all menus when tablet mode ends so that menu options are kept
-  // consistent with device state.
-  if (shelf_menu_model_adapter_)
+  // Close all menus when tablet mode starts or ends so that menu options are
+  // kept consistent with device state and not show the clamshell / tablet only
+  // context menu options while they are unavailable.
+  if (shelf_menu_model_adapter_) {
     shelf_menu_model_adapter_->Cancel();
+  }
 }
 
 void ShelfView::OnShelfConfigUpdated() {
@@ -2043,7 +2032,8 @@
     return source.GetBoundsInScreen();
 
   gfx::Rect shelf_bounds_in_screen;
-  if (ShelfConfig::Get()->is_in_app() && IsTabletModeEnabled()) {
+  if (ShelfConfig::Get()->is_in_app() &&
+      display::Screen::GetScreen()->InTabletMode()) {
     // Use the shelf widget background as the menu anchor point in tablet mode
     // and in app.
     ShelfWidget* shelf_widget = shelf_->shelf_widget();
@@ -2674,7 +2664,7 @@
       source_type,
       base::BindOnce(&ShelfView::OnMenuClosed, base::Unretained(this),
                      base::UnsafeDanglingUntriaged(source)),
-      IsTabletModeEnabled(),
+      display::Screen::GetScreen()->InTabletMode(),
       /*for_application_menu_items*/ !context_menu);
   shelf_menu_model_adapter_->Run(
       GetMenuAnchorRect(*source, click_point, context_menu),
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index af33b659..8e815a3 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -16,7 +16,6 @@
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/public/cpp/shelf_item_delegate.h"
 #include "ash/public/cpp/shelf_model_observer.h"
-#include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_button_delegate.h"
 #include "ash/shelf/shelf_button_pressed_metric_tracker.h"
@@ -33,6 +32,7 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/compositor/throughput_tracker.h"
+#include "ui/display/display_observer.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/animation/bounds_animator_observer.h"
@@ -50,7 +50,8 @@
 
 namespace display {
 class ScopedDisplayForNewWindows;
-}
+enum class TabletState;
+}  // namespace display
 
 namespace views {
 class BoundsAnimator;
@@ -86,7 +87,7 @@
                              public views::BoundsAnimatorObserver,
                              public ApplicationDragAndDropHost,
                              public ShelfTooltipDelegate,
-                             public TabletModeObserver {
+                             public display::DisplayObserver {
  public:
   METADATA_HEADER(ShelfView);
   // Used to communicate with the container class ScrollableShelfView.
@@ -205,9 +206,8 @@
                                   const gfx::Point& point,
                                   ui::MenuSourceType source_type) override;
 
-  // ash::TabletModeObserver:
-  void OnTabletModeStarted() override;
-  void OnTabletModeEnded() override;
+  // display::DisplayObserver:
+  void OnDisplayTabletStateChanged(display::TabletState state) override;
 
   // Called from ScrollableShelfView when shelf config is updated.
   void OnShelfConfigUpdated();
@@ -823,6 +823,8 @@
   // the promise app icon image.
   PendingPromiseAppsMap pending_promise_apps_removals_;
 
+  display::ScopedDisplayObserver display_observer_{this};
+
   base::WeakPtrFactory<ShelfView> weak_factory_{this};
 };
 
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index 44135e50..b7593b3 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -83,6 +83,7 @@
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/display/tablet_state.h"
 #include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event.h"
 #include "ui/events/event_constants.h"
@@ -1798,7 +1799,7 @@
   generator->PressRightButton();
 
   // Start tablet mode, which should close the menu.
-  shelf_view_->OnTabletModeStarted();
+  shelf_view_->OnDisplayTabletStateChanged(display::TabletState::kInTabletMode);
 
   // Attempt to close the menu, which should already be closed.
   EXPECT_FALSE(test_api_->CloseMenu());
@@ -1808,7 +1809,8 @@
   generator->PressRightButton();
 
   // End tablet mode, which should close the menu.
-  shelf_view_->OnTabletModeEnded();
+  shelf_view_->OnDisplayTabletStateChanged(
+      display::TabletState::kInClamshellMode);
 
   // Attempt to close the menu, which should already be closed.
   EXPECT_FALSE(test_api_->CloseMenu());
diff --git a/ash/shell.cc b/ash/shell.cc
index d752095..9f470434 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -512,7 +512,7 @@
 }
 
 bool Shell::IsInTabletMode() const {
-  return tablet_mode_controller()->InTabletMode();
+  return display::Screen::GetScreen()->InTabletMode();
 }
 
 bool Shell::ShouldSaveDisplaySettings() {
diff --git a/ash/shell.h b/ash/shell.h
index 52a73784..f34323d 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -385,9 +385,10 @@
   // Called when dictation is ended.
   void OnDictationEnded();
 
-  // Returns whether the device is currently in tablet mode. If the tablet
-  // mode controller isn't available, we assume the device is not in
-  // tablet mode.
+  // DEPRECATED. Use display::Screen::GetScreen()->InTabletMode() instead.
+  // TODO(crbug.com/1502114): Remove this.
+  //
+  // Returns whether the device is currently in tablet mode.
   bool IsInTabletMode() const;
 
   // Tests if TabletModeWindowManager is not enabled, and if
diff --git a/ash/shell_tab_handler.cc b/ash/shell_tab_handler.cc
index 9ed3a2e1..19ed4c7 100644
--- a/ash/shell_tab_handler.cc
+++ b/ash/shell_tab_handler.cc
@@ -12,6 +12,7 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_util.h"
+#include "ui/display/screen.h"
 #include "ui/events/event.h"
 #include "ui/wm/public/activation_client.h"
 
@@ -24,7 +25,7 @@
       key_event->type() != ui::EventType::ET_KEY_PRESSED ||
       key_event->IsAltDown() || key_event->IsControlDown() ||
       key_event->IsCommandDown() ||
-      shell_->tablet_mode_controller()->InTabletMode()) {
+      display::Screen::GetScreen()->InTabletMode()) {
     return;
   }
 
diff --git a/ash/style/keyboard_shortcut_view.cc b/ash/style/keyboard_shortcut_view.cc
new file mode 100644
index 0000000..5fa535e
--- /dev/null
+++ b/ash/style/keyboard_shortcut_view.cc
@@ -0,0 +1,55 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/style/keyboard_shortcut_view.h"
+
+#include "ash/accelerators/keyboard_code_util.h"
+#include "ash/app_list/views/search_result_inline_icon_view.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "ui/gfx/vector_icon_types.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/layout/flex_layout_view.h"
+
+namespace ash {
+
+KeyboardShortcutView::KeyboardShortcutView(
+    const std::vector<ui::KeyboardCode>& keyboard_codes) {
+  // Set up a `SearchResultInlineIconView` to represent each key in the
+  // combination.
+  for (size_t i = 0; i < keyboard_codes.size(); i++) {
+    // Get the string for the given keyboard code.
+    const auto key_code = keyboard_codes[i];
+
+    // TODO(b/305968013): Save the strings separately to use for accessibility
+    // purposes like screen readers.
+
+    auto icon_view = std::make_unique<SearchResultInlineIconView>(
+        /*use_modified_styling=*/true, /*is_first_key=*/i == 0);
+    icon_view->SetCanProcessEventsWithinSubtree(false);
+    icon_view->GetViewAccessibility().OverrideIsIgnored(true);
+    icon_view->SetProperty(
+        views::kFlexBehaviorKey,
+        views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
+                                 views::MaximumFlexSizeRule::kPreferred));
+
+    // If there is an icon associated with the key (e.g. Search), then set it in
+    // the rect. Otherwise, set the associated text (e.g., Shift).
+    if (const gfx::VectorIcon* vector_icon =
+            GetVectorIconForKeyboardCode(key_code)) {
+      icon_view->SetIcon(*vector_icon);
+    } else {
+      icon_view->SetText(GetStringForKeyboardCode(key_code));
+    }
+
+    AddChildView(std::move(icon_view));
+  }
+}
+
+KeyboardShortcutView::~KeyboardShortcutView() = default;
+
+BEGIN_METADATA(KeyboardShortcutView, views::FlexLayoutView)
+END_METADATA
+
+}  // namespace ash
diff --git a/ash/style/keyboard_shortcut_view.h b/ash/style/keyboard_shortcut_view.h
new file mode 100644
index 0000000..08cba2b8
--- /dev/null
+++ b/ash/style/keyboard_shortcut_view.h
@@ -0,0 +1,29 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_STYLE_KEYBOARD_SHORTCUT_VIEW_H_
+#define ASH_STYLE_KEYBOARD_SHORTCUT_VIEW_H_
+
+#include "ash/ash_export.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/layout/flex_layout_view.h"
+
+namespace ash {
+
+// A view used to represent a keyboard shortcut/accelerator as a series of
+// bordered text or icon keys.
+class ASH_EXPORT KeyboardShortcutView : public views::FlexLayoutView {
+ public:
+  METADATA_HEADER(KeyboardShortcutView);
+
+  explicit KeyboardShortcutView(
+      const std::vector<ui::KeyboardCode>& keyboard_codes);
+  KeyboardShortcutView(const KeyboardShortcutView&) = delete;
+  KeyboardShortcutView& operator=(const KeyboardShortcutView&) = delete;
+  ~KeyboardShortcutView() override;
+};
+
+}  // namespace ash
+
+#endif  // ASH_STYLE_KEYBOARD_SHORTCUT_VIEW_H_
diff --git a/ash/style/pill_button.cc b/ash/style/pill_button.cc
index 1f707af..3b1fd49 100644
--- a/ash/style/pill_button.cc
+++ b/ash/style/pill_button.cc
@@ -437,9 +437,9 @@
   // If custom icon color is set, use it to set icon color.
   if (IsAssignedColorVariant(icon_color_)) {
     if (absl::holds_alternative<SkColor>(icon_color_)) {
-      SetImage(views::Button::STATE_NORMAL,
-               gfx::CreateVectorIcon(*icon_, kIconSize,
-                                     absl::get<SkColor>(icon_color_)));
+      SetImageModel(views::Button::STATE_NORMAL,
+                    ui::ImageModel::FromVectorIcon(
+                        *icon_, absl::get<SkColor>(icon_color_), kIconSize));
     } else {
       SetImageModel(
           views::Button::STATE_NORMAL,
diff --git a/ash/system/phonehub/app_stream_launcher_list_item.cc b/ash/system/phonehub/app_stream_launcher_list_item.cc
index 7fc8320..cbe168f 100644
--- a/ash/system/phonehub/app_stream_launcher_list_item.cc
+++ b/ash/system/phonehub/app_stream_launcher_list_item.cc
@@ -38,11 +38,12 @@
           skia::ImageOperations::RESIZE_BEST,
           gfx::Size(kEcheAppLIstItemIconSize, kEcheAppLIstItemIconSize));
 
-  SetImage(STATE_NORMAL, resized_app_icon);
+  SetImageModel(STATE_NORMAL, ui::ImageModel::FromImageSkia(resized_app_icon));
   // Fade the image in order to make it look like grayed out.
-  SetImage(views::Button::ButtonState::STATE_DISABLED,
-           gfx::ImageSkiaOperations::CreateTransparentImage(
-               resized_app_icon, kAlphaValueForInhibitedIconOpacity));
+  SetImageModel(views::Button::ButtonState::STATE_DISABLED,
+                ui::ImageModel::FromImageSkia(
+                    gfx::ImageSkiaOperations::CreateTransparentImage(
+                        resized_app_icon, kAlphaValueForInhibitedIconOpacity)));
 
   if (chromeos::features::IsJellyrollEnabled()) {
     ash::StyleUtil::SetUpInkDropForButton(this, gfx::Insets(),
diff --git a/ash/system/session/logout_button_tray.cc b/ash/system/session/logout_button_tray.cc
index bbdc73bb..8359c386 100644
--- a/ash/system/session/logout_button_tray.cc
+++ b/ash/system/session/logout_button_tray.cc
@@ -140,14 +140,14 @@
       user::GetLocalizedSignOutStringForStatus(login_status, false);
   if (shelf()->IsHorizontalAlignment()) {
     button_->SetText(title);
-    button_->SetImage(views::Button::STATE_NORMAL, gfx::ImageSkia());
+    button_->SetImageModel(views::Button::STATE_NORMAL, ui::ImageModel());
     button_->SetMinSize(gfx::Size(0, kTrayItemSize));
   } else {
     button_->SetText(std::u16string());
     button_->SetAccessibleName(title);
-    button_->SetImage(
+    button_->SetImageModel(
         views::Button::STATE_NORMAL,
-        gfx::CreateVectorIcon(
+        ui::ImageModel::FromVectorIcon(
             kShelfLogoutIcon,
             AshColorProvider::Get()->GetContentLayerColor(
                 AshColorProvider::ContentLayerType::kIconColorPrimary)));
diff --git a/ash/system/toast/system_nudge_view.cc b/ash/system/toast/system_nudge_view.cc
index 535a166..446b72c8 100644
--- a/ash/system/toast/system_nudge_view.cc
+++ b/ash/system/toast/system_nudge_view.cc
@@ -14,6 +14,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_id.h"
+#include "ash/style/keyboard_shortcut_view.h"
 #include "ash/style/pill_button.h"
 #include "ash/style/system_shadow.h"
 #include "ash/style/typography.h"
@@ -104,7 +105,8 @@
 
   const bool nudge_is_text_only = nudge_data.image_model.IsEmpty() &&
                                   nudge_data.title_text.empty() &&
-                                  nudge_data.primary_button_text.empty();
+                                  nudge_data.primary_button_text.empty() &&
+                                  nudge_data.keyboard_codes.empty();
 
   // Nudges without an anchor view that are not text-only will have a close
   // button that is visible on view hovered.
@@ -215,6 +217,15 @@
 
   // TODO(b/302368860): Add support for a view to display keyboard shortcuts in
   // the same style as the launcher and the new keyboard shortcut app.
+  if (!nudge_data.keyboard_codes.empty()) {
+    AddPaddingView(text_container, image_and_text_container->width(),
+                   kTitleBottomPadding);
+
+    text_container
+        ->AddChildView(
+            std::make_unique<KeyboardShortcutView>(nudge_data.keyboard_codes))
+        ->SetID(VIEW_ID_SYSTEM_NUDGE_SHORTCUT_VIEW);
+  }
 
   // Return early if there are no buttons.
   if (nudge_data.primary_button_text.empty()) {
diff --git a/ash/system/toast/system_nudge_view_unittest.cc b/ash/system/toast/system_nudge_view_unittest.cc
index 0b9546a..0c3c301 100644
--- a/ash/system/toast/system_nudge_view_unittest.cc
+++ b/ash/system/toast/system_nudge_view_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/ash_view_ids.h"
 #include "ash/public/cpp/system/anchored_nudge_data.h"
+#include "ash/style/keyboard_shortcut_view.h"
 #include "ash/system/toast/nudge_constants.h"
 #include "ash/test/ash_test_base.h"
 #include "base/test/scoped_feature_list.h"
@@ -16,6 +17,7 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/layout/flex_layout_view.h"
 #include "ui/views/test/views_test_utils.h"
 #include "ui/views/view_utils.h"
 #include "ui/views/widget/widget.h"
@@ -55,6 +57,11 @@
       nudge_view->GetViewByID(VIEW_ID_SYSTEM_NUDGE_BODY_LABEL));
 }
 
+KeyboardShortcutView* GetShortcutView(views::View* nudge_view) {
+  return views::AsViewClass<KeyboardShortcutView>(
+      nudge_view->GetViewByID(VIEW_ID_SYSTEM_NUDGE_SHORTCUT_VIEW));
+}
+
 views::LabelButton* GetPrimaryButton(views::View* nudge_view) {
   return views::AsViewClass<views::LabelButton>(
       nudge_view->GetViewByID(VIEW_ID_SYSTEM_NUDGE_PRIMARY_BUTTON));
@@ -194,4 +201,28 @@
   EXPECT_FALSE(GetCloseButton(widget->GetContentsView()));
 }
 
+// Test that the keyboard shortcut view is properly created in different
+// circumstances.
+TEST_F(SystemNudgeViewTest, ShortcutView) {
+  std::unique_ptr<views::Widget> widget = CreateFramelessTestWidget();
+
+  // Test that passing an empty vector of keyboard codes does not create a
+  // shortcut view, and should not have a close button.
+  auto nudge_data = CreateBaseNudgeData();
+  nudge_data.keyboard_codes = {};
+  widget->SetContentsView(std::make_unique<SystemNudgeView>(nudge_data));
+  EXPECT_FALSE(GetShortcutView(widget->GetContentsView()));
+  EXPECT_FALSE(GetCloseButton(widget->GetContentsView()));
+
+  // Test that passing a non-empty vector of keyboard codes will create a
+  // shortcut view, and will have a close button.
+  nudge_data = CreateBaseNudgeData();
+  nudge_data.keyboard_codes = {ui::VKEY_CONTROL, ui::VKEY_SHIFT,
+                               ui::VKEY_MEDIA_LAUNCH_APP1};
+  widget->SetContentsView(std::make_unique<SystemNudgeView>(nudge_data));
+  EXPECT_TRUE(GetShortcutView(widget->GetContentsView()));
+  ASSERT_TRUE(GetCloseButton(widget->GetContentsView()));
+  EXPECT_FALSE(GetCloseButton(widget->GetContentsView())->GetVisible());
+}
+
 }  // namespace ash
diff --git a/ash/utility/occlusion_tracker_pauser_unittest.cc b/ash/utility/occlusion_tracker_pauser_unittest.cc
index 1d05e339..b4bf5ed4 100644
--- a/ash/utility/occlusion_tracker_pauser_unittest.cc
+++ b/ash/utility/occlusion_tracker_pauser_unittest.cc
@@ -12,6 +12,7 @@
 #include "ui/aura/window_occlusion_tracker.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/compositor/compositor.h"
+#include "ui/compositor/test/begin_main_frame_waiter.h"
 
 namespace ash {
 namespace {
@@ -28,39 +29,6 @@
   void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
 };
 
-class BeginMainFrameWaiter : public ui::CompositorObserver {
- public:
-  explicit BeginMainFrameWaiter(ui::Compositor* compositor)
-      : compositor_(compositor) {
-    compositor->AddObserver(this);
-  }
-
-  ~BeginMainFrameWaiter() override { compositor_->RemoveObserver(this); }
-
-  // ui::CompositorObserver
-  void OnDidBeginMainFrame(ui::Compositor* compositor) override {
-    DCHECK_EQ(compositor_, compositor);
-    done_ = true;
-    if (run_loop_)
-      run_loop_->Quit();
-  }
-
-  void Wait() {
-    if (done_)
-      return;
-
-    run_loop_ = std::make_unique<base::RunLoop>(
-        base::RunLoop::Type::kNestableTasksAllowed);
-    run_loop_->Run();
-    run_loop_.reset();
-  }
-
- private:
-  raw_ptr<ui::Compositor, ExperimentalAsh> compositor_;
-  bool done_ = false;
-  std::unique_ptr<base::RunLoop> run_loop_;
-};
-
 }  // namespace
 
 class OcclusionTrackerPauserTest : public AshTestBase {
@@ -89,7 +57,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor).Wait();
+  ui::BeginMainFrameWaiter(compositor).Wait();
   EXPECT_FALSE(tracker->IsPaused());
 
   compositor->AddAnimationObserver(&observer1);
@@ -105,7 +73,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor).Wait();
+  ui::BeginMainFrameWaiter(compositor).Wait();
   EXPECT_FALSE(tracker->IsPaused());
 }
 
@@ -129,7 +97,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor1).Wait();
+  ui::BeginMainFrameWaiter(compositor1).Wait();
 
   // Tracker should still be paused.
   EXPECT_TRUE(tracker->IsPaused());
@@ -138,7 +106,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor2).Wait();
+  ui::BeginMainFrameWaiter(compositor2).Wait();
   EXPECT_FALSE(tracker->IsPaused());
 
   // Disconnect display.
@@ -151,7 +119,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor1).Wait();
+  ui::BeginMainFrameWaiter(compositor1).Wait();
   // Tracker should still be paused.
   EXPECT_TRUE(tracker->IsPaused());
 
@@ -160,7 +128,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor1).Wait();
+  ui::BeginMainFrameWaiter(compositor1).Wait();
   EXPECT_TRUE(tracker->IsPaused());
 
   UpdateDisplay("800x1000");
@@ -168,7 +136,7 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter(compositor1).Wait();
+  ui::BeginMainFrameWaiter(compositor1).Wait();
   EXPECT_FALSE(tracker->IsPaused());
 }
 
@@ -192,8 +160,8 @@
 
   // Wait for BeginFrame since compositor animation notifications happen
   // on BeginFrame.
-  BeginMainFrameWaiter waiter1(compositor1);
-  BeginMainFrameWaiter waiter2(compositor2);
+  ui::BeginMainFrameWaiter waiter1(compositor1);
+  ui::BeginMainFrameWaiter waiter2(compositor2);
   waiter1.Wait();
   waiter2.Wait();
 
diff --git a/ash/webui/camera_app_ui/resources/js/test/cca_test.ts b/ash/webui/camera_app_ui/resources/js/test/cca_test.ts
index f56f67e..d7e04eed 100644
--- a/ash/webui/camera_app_ui/resources/js/test/cca_test.ts
+++ b/ash/webui/camera_app_ui/resources/js/test/cca_test.ts
@@ -185,6 +185,23 @@
   }
 
   /**
+   * Chooses a video resolution with the specified resolution for the camera
+   * with |facing| facing. Throws an error if there is no specified resolution.
+   */
+  static chooseVideoResolution(facing: Facing, resolution: Resolution): void {
+    const {width, height} = resolution;
+    const selector =
+        `#view-video-resolution-settings .menu-item>input[data-facing="${
+            facing}"][data-width="${width}"][data-height="${height}"]`;
+    try {
+      const resolutionPicker = dom.get(selector, HTMLInputElement);
+      resolutionPicker.click();
+    } catch {
+      throw new Error(`Cannot find a resolution`);
+    }
+  }
+
+  /**
    * Returns aria-label of the focused element. Throws an error if a focused
    * element is null.
    */
diff --git a/ash/wm/desks/expanded_desks_bar_button.cc b/ash/wm/desks/expanded_desks_bar_button.cc
index 77f914d0..3257ea6 100644
--- a/ash/wm/desks/expanded_desks_bar_button.cc
+++ b/ash/wm/desks/expanded_desks_bar_button.cc
@@ -72,13 +72,13 @@
     const SkColor enabled_icon_color =
         AshColorProvider::Get()->GetContentLayerColor(
             AshColorProvider::ContentLayerType::kButtonIconColor);
-    SetImage(views::Button::STATE_NORMAL,
-             gfx::CreateVectorIcon(*outer_button_->button_icon(),
-                                   enabled_icon_color));
-    SetImage(
-        views::Button::STATE_DISABLED,
-        gfx::CreateVectorIcon(*outer_button_->button_icon(),
-                              ColorUtil::GetDisabledColor(enabled_icon_color)));
+    SetImageModel(views::Button::STATE_NORMAL,
+                  ui::ImageModel::FromVectorIcon(*outer_button_->button_icon(),
+                                                 enabled_icon_color));
+    SetImageModel(views::Button::STATE_DISABLED,
+                  ui::ImageModel::FromVectorIcon(
+                      *outer_button_->button_icon(),
+                      ColorUtil::GetDisabledColor(enabled_icon_color)));
     SetButtonState(GetEnabled());
   }
 
diff --git a/ash/wm/desks/zero_state_button.cc b/ash/wm/desks/zero_state_button.cc
index cdad768..74fa559 100644
--- a/ash/wm/desks/zero_state_button.cc
+++ b/ash/wm/desks/zero_state_button.cc
@@ -126,8 +126,8 @@
   DeskButtonBase::OnThemeChanged();
   const SkColor icon_color = AshColorProvider::Get()->GetContentLayerColor(
       AshColorProvider::ContentLayerType::kButtonIconColor);
-  SetImage(views::Button::STATE_NORMAL,
-           gfx::CreateVectorIcon(*button_icon_, icon_color));
+  SetImageModel(views::Button::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(*button_icon_, icon_color));
 }
 
 gfx::Size ZeroStateIconButton::CalculatePreferredSize() const {
diff --git a/base/allocator/partition_alloc_features.cc b/base/allocator/partition_alloc_features.cc
index 382618f9..ab0086c6 100644
--- a/base/allocator/partition_alloc_features.cc
+++ b/base/allocator/partition_alloc_features.cc
@@ -118,6 +118,10 @@
 const base::FeatureParam<int> kPartitionAllocSchedulerLoopQuarantineCapacity{
     &kPartitionAllocSchedulerLoopQuarantine,
     "PartitionAllocSchedulerLoopQuarantineCapacity", 0};
+
+BASE_FEATURE(kPartitionAllocZappingByFreeFlags,
+             "PartitionAllocZappingByFreeFlags",
+             FEATURE_DISABLED_BY_DEFAULT);
 #endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 
 BASE_FEATURE(kPartitionAllocBackupRefPtr,
diff --git a/base/allocator/partition_alloc_features.h b/base/allocator/partition_alloc_features.h
index a72d35ec..30a93af 100644
--- a/base/allocator/partition_alloc_features.h
+++ b/base/allocator/partition_alloc_features.h
@@ -74,6 +74,8 @@
 BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSchedulerLoopQuarantine);
 extern const BASE_EXPORT base::FeatureParam<int>
     kPartitionAllocSchedulerLoopQuarantineCapacity;
+
+BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags);
 #endif  // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 
 enum class BackupRefPtrEnabledProcesses {
diff --git a/base/allocator/partition_alloc_support.cc b/base/allocator/partition_alloc_support.cc
index d0e9bda..a4f9642 100644
--- a/base/allocator/partition_alloc_support.cc
+++ b/base/allocator/partition_alloc_support.cc
@@ -1104,6 +1104,8 @@
   const size_t scheduler_loop_quarantine_capacity_in_bytes =
       static_cast<size_t>(
           base::features::kPartitionAllocSchedulerLoopQuarantineCapacity.Get());
+  const bool zapping_by_free_flags = base::FeatureList::IsEnabled(
+      base::features::kPartitionAllocZappingByFreeFlags);
 
   bool enable_memory_tagging = false;
   partition_alloc::TagViolationReportingMode memory_tagging_reporting_mode =
@@ -1179,7 +1181,8 @@
       allocator_shim::UseDedicatedAlignedPartition(
           brp_config.use_dedicated_aligned_partition),
       brp_config.ref_count_size, bucket_distribution,
-      scheduler_loop_quarantine_capacity_in_bytes);
+      scheduler_loop_quarantine_capacity_in_bytes,
+      allocator_shim::ZappingByFreeFlags(zapping_by_free_flags));
 
   const uint32_t extras_size = allocator_shim::GetMainPartitionRootExtrasSize();
   // As per description, extras are optional and are expected not to
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
index 4412c9ac..82216155 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
@@ -357,6 +357,7 @@
   PartitionOptions GetCommonPartitionOptions() {
     PartitionOptions opts;
     opts.ref_count_size = GetParam().ref_count_size;
+    opts.zapping_by_free_flags = PartitionOptions::kEnabled;
     return opts;
   }
 
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
index 25160d8..ed7c7000 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
@@ -991,6 +991,8 @@
         (opts.use_configurable_pool == PartitionOptions::kAllowed) &&
         IsConfigurablePoolAvailable();
     PA_DCHECK(!settings.use_configurable_pool || IsConfigurablePoolAvailable());
+    settings.zapping_by_free_flags =
+        opts.zapping_by_free_flags == PartitionOptions::kEnabled;
 #if PA_CONFIG(HAS_MEMORY_TAGGING)
     settings.memory_tagging_enabled_ =
         opts.memory_tagging.enabled == PartitionOptions::kEnabled;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_root.h b/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
index 591ef32..df1d641 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
@@ -182,6 +182,8 @@
 
   size_t scheduler_loop_quarantine_capacity_in_bytes = 0;
 
+  EnableToggle zapping_by_free_flags = kDisabled;
+
   struct {
     EnableToggle enabled = kDisabled;
     TagViolationReportingMode reporting_mode =
@@ -272,6 +274,7 @@
 #endif  // PA_CONFIG(ENABLE_MAC11_MALLOC_SIZE_HACK)
 #endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
     bool use_configurable_pool = false;
+    bool zapping_by_free_flags = false;
 #if PA_CONFIG(HAS_MEMORY_TAGGING)
     bool memory_tagging_enabled_ = false;
     TagViolationReportingMode memory_tagging_reporting_mode_ =
@@ -1390,10 +1393,13 @@
   }
 
   if constexpr (ContainsFlags(flags, FreeFlags::kZap)) {
-    SlotSpan* slot_span = SlotSpan::FromObject(object);
-    uintptr_t slot_start = ObjectToSlotStart(object);
-    internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start),
-                           internal::kFreedByte, GetSlotUsableSize(slot_span));
+    if (settings.zapping_by_free_flags) {
+      SlotSpan* slot_span = SlotSpan::FromObject(object);
+      uintptr_t slot_start = ObjectToSlotStart(object);
+      internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start),
+                             internal::kFreedByte,
+                             GetSlotUsableSize(slot_span));
+    }
   }
   // TODO(https://crbug.com/1497380): Collecting objects for
   // `kSchedulerLoopQuarantine` here means it "delays" other checks (BRP
@@ -2304,9 +2310,8 @@
   // don't pass anything less, because it'll mess up callee's calculations.
   size_t slot_span_alignment =
       std::max(alignment, internal::PartitionPageSize());
-  // TODO(mikt): Investigate why all flags except kNoHooks are ignored here.
-  void* object = AllocInternal<flags & AllocFlags::kNoHooks>(
-      adjusted_size, slot_span_alignment, nullptr);
+  void* object =
+      AllocInternal<flags>(adjusted_size, slot_span_alignment, nullptr);
 
   // |alignment| is a power of two, but the compiler doesn't necessarily know
   // that. A regular % operation is very slow, make sure to use the equivalent,
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
index a712cfc..24b622c4 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
@@ -197,6 +197,9 @@
 using UseDedicatedAlignedPartition = partition_alloc::internal::base::
     StrongAlias<class UseDedicatedAlignedPartitionTag, bool>;
 enum class BucketDistribution : uint8_t { kNeutral, kDenser };
+using ZappingByFreeFlags =
+    partition_alloc::internal::base::StrongAlias<class ZappingByFreeFlagsTag,
+                                                 bool>;
 
 // If |thread_cache_on_non_quarantinable_partition| is specified, the
 // thread-cache will be enabled on the non-quarantinable partition. The
@@ -210,7 +213,8 @@
     UseDedicatedAlignedPartition use_dedicated_aligned_partition,
     size_t ref_count_size,
     BucketDistribution distribution,
-    size_t scheduler_loop_quarantine_capacity_in_bytes);
+    size_t scheduler_loop_quarantine_capacity_in_bytes,
+    ZappingByFreeFlags zapping_by_free_flags);
 
 // If |thread_cache_on_non_quarantinable_partition| is specified, the
 // thread-cache will be enabled on the non-quarantinable partition. The
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
index 53d64243..b2ed455 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -529,7 +529,8 @@
     UseDedicatedAlignedPartition use_dedicated_aligned_partition,
     size_t ref_count_size,
     BucketDistribution distribution,
-    size_t scheduler_loop_quarantine_capacity_in_bytes) {
+    size_t scheduler_loop_quarantine_capacity_in_bytes,
+    ZappingByFreeFlags zapping_by_free_flags) {
   // BRP cannot be enabled without splitting the main partition. Furthermore, in
   // the "before allocation" mode, it can't be enabled without further splitting
   // out the aligned partition.
@@ -583,6 +584,10 @@
             enable_brp ? partition_alloc::PartitionOptions::kEnabled
                        : partition_alloc::PartitionOptions::kDisabled;
         opts.ref_count_size = ref_count_size;
+        opts.zapping_by_free_flags =
+            zapping_by_free_flags
+                ? partition_alloc::PartitionOptions::kEnabled
+                : partition_alloc::PartitionOptions::kDisabled;
         opts.scheduler_loop_quarantine_capacity_in_bytes =
             scheduler_loop_quarantine_capacity_in_bytes;
         opts.memory_tagging = {
@@ -662,13 +667,15 @@
               ? partition_alloc::TagViolationReportingMode::kSynchronous
               : partition_alloc::TagViolationReportingMode::kDisabled;
 
-  // We don't use this feature in PDFium.
+  // We don't use these features in PDFium.
   size_t scheduler_loop_quarantine_capacity_in_bytes = 0;
+  auto zapping_by_free_flags = ZappingByFreeFlags(false);
 
-  ConfigurePartitions(
-      enable_brp, enable_memory_tagging, memory_tagging_reporting_mode,
-      split_main_partition, use_dedicated_aligned_partition, ref_count_size,
-      distribution, scheduler_loop_quarantine_capacity_in_bytes);
+  ConfigurePartitions(enable_brp, enable_memory_tagging,
+                      memory_tagging_reporting_mode, split_main_partition,
+                      use_dedicated_aligned_partition, ref_count_size,
+                      distribution, scheduler_loop_quarantine_capacity_in_bytes,
+                      zapping_by_free_flags);
 }
 
 // No synchronization provided: `PartitionRoot.flags` is only written
diff --git a/build/config/c++/libc++.natvis b/build/config/c++/libc++.natvis
index 26580dbb..bceb435 100644
--- a/build/config/c++/libc++.natvis
+++ b/build/config/c++/libc++.natvis
@@ -248,6 +248,14 @@
     </Expand>
   </Type>
 
+  <Type Name="std::__Cr::optional&lt;*&gt;">
+    <DisplayString Condition="!__engaged_">nullopt</DisplayString>
+    <DisplayString>{__val_}</DisplayString>
+    <Expand>
+      <ExpandedItem Condition="__engaged_">__val_</ExpandedItem>
+    </Expand>
+  </Type>
+
   <Type Name="std::__Cr::priority_queue&lt;*&gt;">
     <DisplayString>{c}</DisplayString>
     <Expand>
diff --git a/build/config/clang/BUILD.gn b/build/config/clang/BUILD.gn
index 46f4de0..d4de2e0c 100644
--- a/build/config/clang/BUILD.gn
+++ b/build/config/clang/BUILD.gn
@@ -42,6 +42,12 @@
       "-plugin-arg-find-bad-constructs",
       "-Xclang",
       "raw-ptr-fix-crbug-1449812",
+
+      # TODO(https://crbug.com/1504043): Remove when raw_ptr check has been enabled for the dawn repo.
+      "-Xclang",
+      "-plugin-arg-find-bad-constructs",
+      "-Xclang",
+      "raw-ptr-exclude-path=/third_party/dawn/",
     ]
 
     if (is_linux || is_chromeos || is_android || is_fuchsia) {
diff --git a/build/config/siso/linux.star b/build/config/siso/linux.star
index 27bfd82..3067516 100644
--- a/build/config/siso/linux.star
+++ b/build/config/siso/linux.star
@@ -41,47 +41,9 @@
 __handlers.update(rust.handlers)
 __handlers.update(typescript.handlers)
 
-def __disable_remote_b289968566(ctx, step_config):
-    rule = {
-        # TODO(b/289968566): they often faile with exit=137 (OOM?).
-        # We should migrate default machine type to n2-standard-2.
-        "name": "b289968566/exit-137",
-        "action_outs": [
-            "./android_clang_arm/obj/third_party/distributed_point_functions/distributed_point_functions/evaluate_prg_hwy.o",
-            "./obj/chrome/browser/ash/ash/autotest_private_api.o",
-            "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o",
-            "./obj/chrome/browser/ash/system_web_apps/browser_tests/system_web_app_manager_browsertest.o",
-            "./obj/chrome/browser/browser/browser_prefs.o",
-            "./obj/chrome/browser/browser/chrome_browser_interface_binders.o",
-            "./obj/chrome/browser/ui/ash/holding_space/browser_tests/holding_space_ui_browsertest.o",
-            "./obj/chrome/test/browser_tests/browser_non_client_frame_view_chromeos_browsertest.o",
-            "./obj/chrome/test/browser_tests/chrome_shelf_controller_browsertest.o",
-            "./obj/chrome/test/browser_tests/device_local_account_browsertest.o",
-            "./obj/chrome/test/browser_tests/file_manager_browsertest_base.o",
-            "./obj/chrome/test/browser_tests/remote_apps_manager_browsertest.o",
-            "./obj/chrome/test/browser_tests/spoken_feedback_browsertest.o",
-            "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.o",
-            "./obj/chrome/test/unit_tests/site_settings_handler_unittest.o",
-            "./obj/content/browser/browser/browser_interface_binders.o",
-            "./obj/fuchsia_web/runners/cast_runner_integration_tests__exec/cast_runner_integration_test.o",
-            "./obj/fuchsia_web/webengine/web_engine_core/frame_impl.o",
-            "./ash_clang_x64/obj/chrome/browser/ash/ash/autotest_private_api.o",
-            "./ash_clang_x64/obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o",
-            "./ash_clang_x64/obj/chrome/browser/browser/browser_prefs.o",
-            "./ash_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o",
-        ],
-        "remote": False,
-    }
-    if reproxy.enabled(ctx):
-        rule["handler"] = "strip_rewrapper"
-    step_config["rules"].insert(0, rule)
-    return step_config
-
 def __step_config(ctx, step_config):
     config.check(ctx)
 
-    step_config = __disable_remote_b289968566(ctx, step_config)
-
     if android.enabled(ctx):
         step_config = android.step_config(ctx, step_config)
 
diff --git a/build/config/siso/main.star b/build/config/siso/main.star
index 910bedd..bf0658f 100644
--- a/build/config/siso/main.star
+++ b/build/config/siso/main.star
@@ -16,6 +16,53 @@
 load("./simple.star", "simple")
 load("./windows.star", chromium_windows = "chromium")
 
+def __use_large_b289968566(ctx, step_config):
+    # TODO(b/289968566): they often faile with exit=137 (OOM?).
+    # They need to run on a machine has more memory than the default machine type n2-custom-2-3840
+    exit137_list = [
+        "./android_clang_arm/obj/third_party/distributed_point_functions/distributed_point_functions/evaluate_prg_hwy.o",
+        "./ash_clang_x64/obj/chrome/browser/ash/ash/autotest_private_api.o",
+        "./ash_clang_x64/obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o",
+        "./ash_clang_x64/obj/chrome/browser/browser/browser_prefs.o",
+        "./ash_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o",
+        "./obj/chrome/browser/ash/ash/autotest_private_api.o",
+        "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o",
+        "./obj/chrome/browser/ash/system_web_apps/browser_tests/system_web_app_manager_browsertest.o",
+        "./obj/chrome/browser/browser/browser_prefs.o",
+        "./obj/chrome/browser/browser/chrome_browser_interface_binders.o",
+        "./obj/chrome/browser/ui/ash/holding_space/browser_tests/holding_space_ui_browsertest.o",
+        "./obj/chrome/test/browser_tests/browser_non_client_frame_view_chromeos_browsertest.o",
+        "./obj/chrome/test/browser_tests/chrome_shelf_controller_browsertest.o",
+        "./obj/chrome/test/browser_tests/device_local_account_browsertest.o",
+        "./obj/chrome/test/browser_tests/file_manager_browsertest_base.o",
+        "./obj/chrome/test/browser_tests/remote_apps_manager_browsertest.o",
+        "./obj/chrome/test/browser_tests/spoken_feedback_browsertest.o",
+        "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.o",
+        "./obj/chrome/test/unit_tests/site_settings_handler_unittest.o",
+        "./obj/content/browser/browser/browser_interface_binders.o",
+        "./obj/fuchsia_web/runners/cast_runner_integration_tests__exec/cast_runner_integration_test.o",
+        "./obj/fuchsia_web/webengine/web_engine_core/frame_impl.o",
+    ]
+    if runtime.os == "windows":
+        exit137_list = [obj.removesuffix(".o") + ".obj" for obj in exit137_list if obj.startswith("./obj/")]
+
+    new_rules = []
+    for rule in step_config["rules"]:
+        if not rule["name"].endswith("/cxx"):
+            new_rules.append(rule)
+            continue
+        if "action_outs" in rule:
+            fail("unexpeced \"action_outs\" in cxx rule %s" % rule["name"])
+        r = {}
+        r.update(rule)
+        r["name"] += "/b289968566/exit-137"
+        r["action_outs"] = exit137_list
+        r["platform_ref"] = "large"
+        new_rules.append(r)
+        new_rules.append(rule)
+    step_config["rules"] = new_rules
+    return step_config
+
 def init(ctx):
     print("runtime: os:%s arch:%s run:%d" % (
         runtime.os,
@@ -76,6 +123,8 @@
             arg0 = arg0.removesuffix(".exe")
         rule["remote_command"] = arg0
 
+    step_config = __use_large_b289968566(ctx, step_config)
+
     filegroups = {}
     filegroups.update(blink_all.filegroups(ctx))
     filegroups.update(host.filegroups(ctx))
diff --git a/build/config/siso/windows.star b/build/config/siso/windows.star
index b43f677a..17fd72d 100644
--- a/build/config/siso/windows.star
+++ b/build/config/siso/windows.star
@@ -17,25 +17,8 @@
 __handlers = {}
 __handlers.update(clang.handlers)
 
-def __disable_remote_b289968566(ctx, step_config):
-    rule = {
-        # TODO(b/289968566): they often faile with exit=137 (OOM?).
-        # We should migrate default machine type to n2-standard-2.
-        "name": "b289968566/exit-137",
-        "action_outs": [
-            "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.obj",
-            "./obj/content/browser/browser/browser_interface_binders.obj",
-        ],
-        "remote": False,
-    }
-    if reproxy.enabled(ctx):
-        rule["handler"] = "strip_rewrapper"
-    step_config["rules"].insert(0, rule)
-    return step_config
-
 def __step_config(ctx, step_config):
     config.check(ctx)
-    step_config = __disable_remote_b289968566(ctx, step_config)
     step_config = clang.step_config(ctx, step_config)
     return step_config
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 378a02e9..0924428 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=121
 MINOR=0
-BUILD=6151
+BUILD=6152
 PATCH=0
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt
index 157b166..bc741af6 100644
--- a/chrome/android/profiles/arm.newest.txt
+++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-121.0.6148.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-arm-121.0.6149.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 8704f44..f1cf854 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -5307,6 +5307,7 @@
       "//chrome/browser/scalable_iph:scalable_iph_factory",
       "//chrome/browser/ui/ash/system_web_apps",
       "//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings",
+      "//chrome/browser/ui/webui/ash/app_install:mojo_bindings",
       "//chrome/browser/ui/webui/ash/audio:mojo_bindings",
       "//chrome/browser/ui/webui/ash/borealis_installer:mojo_bindings",
       "//chrome/browser/ui/webui/ash/cloud_upload:mojo_bindings",
@@ -5326,7 +5327,6 @@
       "//chrome/browser/ui/webui/ash/settings/pages/privacy/mojom",
       "//chrome/browser/ui/webui/ash/settings/search/mojom",
       "//chrome/browser/ui/webui/ash/vm:mojo_bindings",
-      "//chrome/browser/ui/webui/ash/web_app_install:mojo_bindings",
       "//chrome/browser/ui/webui/nearby_share:mojom",
       "//chrome/services/sharing/public/cpp",
       "//chrome/services/sharing/public/proto",
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index 27bfb51..d698e2c 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -66,6 +66,8 @@
     "accessibility/service/speech_recognition_impl.h",
     "accessibility/service/tts_client_impl.cc",
     "accessibility/service/tts_client_impl.h",
+    "accessibility/service/user_input_impl.cc",
+    "accessibility/service/user_input_impl.h",
     "accessibility/service/user_interface_impl.cc",
     "accessibility/service/user_interface_impl.h",
     "account_manager/account_apps_availability.cc",
diff --git a/chrome/browser/ash/accessibility/service/accessibility_service_client.cc b/chrome/browser/ash/accessibility/service/accessibility_service_client.cc
index 2392da0..2e3126f 100644
--- a/chrome/browser/ash/accessibility/service/accessibility_service_client.cc
+++ b/chrome/browser/ash/accessibility/service/accessibility_service_client.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ash/accessibility/service/automation_client_impl.h"
 #include "chrome/browser/ash/accessibility/service/speech_recognition_impl.h"
 #include "chrome/browser/ash/accessibility/service/tts_client_impl.h"
+#include "chrome/browser/ash/accessibility/service/user_input_impl.h"
 #include "chrome/browser/ash/accessibility/service/user_interface_impl.h"
 #include "chrome/common/chrome_paths.h"
 #include "content/public/browser/browser_context.h"
@@ -81,6 +82,11 @@
   tts_client_->Bind(std::move(tts_receiver));
 }
 
+void AccessibilityServiceClient::BindUserInput(
+    mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver) {
+  user_input_client_->Bind(std::move(ui_receiver));
+}
+
 void AccessibilityServiceClient::BindUserInterface(
     mojo::PendingReceiver<ax::mojom::UserInterface> ui_receiver) {
   user_interface_client_->Bind(std::move(ui_receiver));
@@ -156,9 +162,10 @@
   autoclick_client_.reset();
   file_loader_.reset();
   automation_client_.reset();
+  devtools_agent_hosts_.clear();
   speech_recognition_impl_.reset();
   tts_client_.reset();
-  devtools_agent_hosts_.clear();
+  user_input_client_.reset();
   user_interface_client_.reset();
 }
 
@@ -222,6 +229,7 @@
   automation_client_ = std::make_unique<AutomationClientImpl>();
   speech_recognition_impl_ = std::make_unique<SpeechRecognitionImpl>(profile_);
   tts_client_ = std::make_unique<TtsClientImpl>(profile_);
+  user_input_client_ = std::make_unique<UserInputImpl>();
   user_interface_client_ = std::make_unique<UserInterfaceImpl>();
 
   // Bind the AXServiceClient before enabling features.
diff --git a/chrome/browser/ash/accessibility/service/accessibility_service_client.h b/chrome/browser/ash/accessibility/service/accessibility_service_client.h
index 93620c8..051b3cf 100644
--- a/chrome/browser/ash/accessibility/service/accessibility_service_client.h
+++ b/chrome/browser/ash/accessibility/service/accessibility_service_client.h
@@ -32,6 +32,7 @@
 class AutomationClientImpl;
 class SpeechRecognitionImpl;
 class TtsClientImpl;
+class UserInputImpl;
 class UserInterfaceImpl;
 
 // The AccessibilityServiceClient in the Browser process interacts with the
@@ -58,6 +59,8 @@
   void BindSpeechRecognition(
       mojo::PendingReceiver<ax::mojom::SpeechRecognition> sr_receiver) override;
   void BindTts(mojo::PendingReceiver<ax::mojom::Tts> tts_receiver) override;
+  void BindUserInput(
+      mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver) override;
   void BindUserInterface(
       mojo::PendingReceiver<ax::mojom::UserInterface> ui_receiver) override;
   void BindAccessibilityFileLoader(
@@ -105,11 +108,12 @@
   // opened.
   void OnFileLoaded(LoadCallback callback, base::File file);
 
+  std::unique_ptr<AutoclickClientImpl> autoclick_client_;
   std::unique_ptr<AutomationClientImpl> automation_client_;
   std::unique_ptr<SpeechRecognitionImpl> speech_recognition_impl_;
   std::unique_ptr<TtsClientImpl> tts_client_;
+  std::unique_ptr<UserInputImpl> user_input_client_;
   std::unique_ptr<UserInterfaceImpl> user_interface_client_;
-  std::unique_ptr<AutoclickClientImpl> autoclick_client_;
 
   // Track the currently enabled features in case we disconnect from the service
   // and need to reconnect, for example when the profile changes.
diff --git a/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc b/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc
index 99e9e7c..d11c49cf 100644
--- a/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc
+++ b/chrome/browser/ash/accessibility/service/accessibility_service_client_browsertest.cc
@@ -9,6 +9,7 @@
 #include "ash/keyboard/keyboard_controller_impl.h"
 #include "ash/keyboard/ui/keyboard_util.h"
 #include "ash/public/cpp/accessibility_focus_ring_info.h"
+#include "ash/public/cpp/window_tree_host_lookup.h"
 #include "ash/shell.h"
 #include "base/command_line.h"
 #include "base/files/file.h"
@@ -41,9 +42,13 @@
 #include "services/accessibility/public/mojom/tts.mojom.h"
 #include "services/accessibility/public/mojom/user_interface.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/accessibility_features.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/compositor/layer.h"
+#include "ui/events/keycodes/dom/dom_code.h"
 
 using ax::mojom::AssistiveTechnologyType;
 
@@ -270,6 +275,27 @@
   std::string next_utterance_error_ = "";
 };
 
+class TestEventHandler : public ui::EventHandler {
+ public:
+  explicit TestEventHandler(base::RepeatingClosure callback)
+      : callback_(callback) {
+    Shell::Get()->AddPostTargetHandler(this);
+  }
+  ~TestEventHandler() override { Shell::Get()->RemovePostTargetHandler(this); }
+
+  // ui::EventHandler:
+  void OnKeyEvent(ui::KeyEvent* event) override {
+    // Make a copy of the event, so it's valid outside this function context.
+    key_events.push_back(std::make_unique<ui::KeyEvent>(event));
+    callback_.Run();
+  }
+
+  std::vector<std::unique_ptr<ui::KeyEvent>> key_events;
+
+ private:
+  base::RepeatingClosure callback_;
+};
+
 }  // namespace
 
 // Tests for the AccessibilityServiceClientTest using a fake service
@@ -318,6 +344,10 @@
     return accessibility_manager->accessibility_service_client_.get();
   }
 
+  UserInputImpl* UserInputClient() {
+    return Client()->user_input_client_.get();
+  }
+
   bool ServiceHasATEnabled(AssistiveTechnologyType type) {
     std::set<AssistiveTechnologyType> enabled_ATs =
         fake_service_->GetEnabledATs();
@@ -1392,4 +1422,131 @@
   loop.Run();
 }
 
+IN_PROC_BROWSER_TEST_F(AccessibilityServiceClientTest,
+                       SendSyntheticKeyEventForShortcutOrNavigation) {
+  TurnOnAccessibilityService(AssistiveTechnologyType::kSwitchAccess);
+  fake_service_->BindAnotherUserInput();
+
+  auto key_press_event = ax::mojom::SyntheticKeyEvent::New();
+  key_press_event->type = ui::mojom::EventType::KEY_PRESSED;
+  key_press_event->key_data = ui::mojom::KeyData::New();
+  key_press_event->key_data->key_code = ui::VKEY_P;
+  // TODO(b/307553499): Populate dom_code and dom_key for synthetic key events.
+  key_press_event->key_data->dom_code = 0;
+  key_press_event->key_data->dom_key = 0;
+  key_press_event->key_data->is_char = false;
+
+  auto key_release_event = ax::mojom::SyntheticKeyEvent::New();
+  key_release_event->type = ui::mojom::EventType::KEY_RELEASED;
+  key_release_event->key_data = ui::mojom::KeyData::New();
+  key_release_event->key_data->key_code = ui::VKEY_P;
+  // TODO(b/307553499): Populate dom_code and dom_key for synthetic key
+  // events.
+  key_release_event->key_data->dom_code = 0;
+  key_release_event->key_data->dom_key = 0;
+  key_release_event->key_data->is_char = false;
+
+  base::RunLoop waiter;
+
+  TestEventHandler test_event_handler(
+      base::BindLambdaForTesting([&test_event_handler, &waiter]() {
+        if (test_event_handler.key_events.size() != 2) {
+          return;
+        }
+
+        ui::KeyEvent* press_event = test_event_handler.key_events[0].get();
+        EXPECT_EQ(press_event->type(), ui::ET_KEY_PRESSED);
+        EXPECT_EQ(press_event->code(), ui::DomCode::US_P);
+        EXPECT_FALSE(press_event->IsAltDown());
+        EXPECT_FALSE(press_event->IsCommandDown());
+        EXPECT_FALSE(press_event->IsControlDown());
+        EXPECT_FALSE(press_event->IsShiftDown());
+
+        ui::KeyEvent* release_event = test_event_handler.key_events[1].get();
+        EXPECT_EQ(release_event->type(), ui::ET_KEY_RELEASED);
+        EXPECT_EQ(release_event->code(), ui::DomCode::US_P);
+        EXPECT_FALSE(release_event->IsAltDown());
+        EXPECT_FALSE(release_event->IsCommandDown());
+        EXPECT_FALSE(release_event->IsControlDown());
+        EXPECT_FALSE(release_event->IsShiftDown());
+
+        waiter.Quit();
+      }));
+
+  // Send a press.
+  fake_service_->RequestSendSyntheticKeyEventForShortcutOrNavigation(
+      std::move(key_press_event));
+  // Send a release.
+  fake_service_->RequestSendSyntheticKeyEventForShortcutOrNavigation(
+      std::move(key_release_event));
+  waiter.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    AccessibilityServiceClientTest,
+    SendSyntheticKeyEventForShortcutOrNavigationWithModifiers) {
+  TurnOnAccessibilityService(AssistiveTechnologyType::kSwitchAccess);
+  fake_service_->BindAnotherUserInput();
+
+  auto key_press_event = ax::mojom::SyntheticKeyEvent::New();
+  key_press_event->type = ui::mojom::EventType::KEY_PRESSED;
+  key_press_event->key_data = ui::mojom::KeyData::New();
+  key_press_event->key_data->key_code = ui::VKEY_S;
+  // TODO(b/307553499): Populate dom_code and dom_key for synthetic key events.
+  key_press_event->key_data->dom_code = 0;
+  key_press_event->key_data->dom_key = 0;
+  key_press_event->key_data->is_char = false;
+  key_press_event->flags =
+      ui::mojom::kEventFlagAltDown | ui::mojom::kEventFlagControlDown |
+      ui::mojom::kEventFlagCommandDown | ui::mojom::kEventFlagShiftDown;
+
+  auto key_release_event = ax::mojom::SyntheticKeyEvent::New();
+  key_release_event->type = ui::mojom::EventType::KEY_RELEASED;
+  key_release_event->key_data = ui::mojom::KeyData::New();
+  key_release_event->key_data->key_code = ui::VKEY_S;
+  // TODO(b/307553499): Populate dom_code and dom_key for synthetic key
+  // events.
+  key_release_event->key_data->dom_code = 0;
+  key_release_event->key_data->dom_key = 0;
+  key_release_event->key_data->is_char = false;
+  key_release_event->flags =
+      ui::mojom::kEventFlagAltDown | ui::mojom::kEventFlagControlDown |
+      ui::mojom::kEventFlagCommandDown | ui::mojom::kEventFlagShiftDown;
+
+  base::RunLoop waiter;
+
+  TestEventHandler test_event_handler(
+      base::BindLambdaForTesting([&test_event_handler, &waiter]() {
+        if (test_event_handler.key_events.size() != 2) {
+          return;
+        }
+
+        ui::KeyEvent* press_event = test_event_handler.key_events[0].get();
+        EXPECT_EQ(press_event->type(), ui::ET_KEY_PRESSED);
+        EXPECT_EQ(press_event->code(), ui::DomCode::US_S);
+        EXPECT_TRUE(press_event->IsAltDown());
+        EXPECT_TRUE(press_event->IsCommandDown());
+        EXPECT_TRUE(press_event->IsControlDown());
+        EXPECT_TRUE(press_event->IsShiftDown());
+
+        ui::KeyEvent* release_event = test_event_handler.key_events[1].get();
+        EXPECT_EQ(release_event->type(), ui::ET_KEY_RELEASED);
+        EXPECT_EQ(release_event->code(), ui::DomCode::US_S);
+        EXPECT_TRUE(release_event->IsAltDown());
+        EXPECT_TRUE(release_event->IsCommandDown());
+        EXPECT_TRUE(release_event->IsControlDown());
+        EXPECT_TRUE(release_event->IsShiftDown());
+
+        waiter.Quit();
+      }));
+
+  // Send a press.
+  fake_service_->RequestSendSyntheticKeyEventForShortcutOrNavigation(
+      std::move(key_press_event));
+  // Send a release.
+  fake_service_->RequestSendSyntheticKeyEventForShortcutOrNavigation(
+      std::move(key_release_event));
+  waiter.Run();
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ash/accessibility/service/fake_accessibility_service.cc b/chrome/browser/ash/accessibility/service/fake_accessibility_service.cc
index 261c64de..bde10fd 100644
--- a/chrome/browser/ash/accessibility/service/fake_accessibility_service.cc
+++ b/chrome/browser/ash/accessibility/service/fake_accessibility_service.cc
@@ -15,6 +15,7 @@
 #include "services/accessibility/public/mojom/accessibility_service.mojom.h"
 #include "services/accessibility/public/mojom/autoclick.mojom.h"
 #include "services/accessibility/public/mojom/tts.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
 #include "services/accessibility/public/mojom/user_interface.mojom.h"
 
 namespace ash {
@@ -31,6 +32,22 @@
       file_loader_remote_.BindNewPipeAndPassReceiver());
 }
 
+void FakeAccessibilityService::BindAnotherAutoclickClient() {
+  mojo::PendingReceiver<ax::mojom::AutoclickClient> autoclick_client_receiver;
+  autoclick_client_remotes_.Add(
+      autoclick_client_receiver.InitWithNewPipeAndPassRemote());
+  accessibility_service_client_remote_->BindAutoclickClient(
+      std::move(autoclick_client_receiver));
+
+  // Now connect the autoclick remote in the service back to the client in the
+  // browser by getting a PendingReceiver<Autoclick> from the browser.
+  for (auto& remote : autoclick_client_remotes_) {
+    remote->BindAutoclick(
+        base::BindOnce(&FakeAccessibilityService::OnAutoclickBoundCallback,
+                       base::Unretained(this)));
+  }
+}
+
 void FakeAccessibilityService::BindAnotherAutomation() {
   mojo::PendingAssociatedRemote<ax::mojom::Automation> automation_remote;
   automation_receivers_.Add(
@@ -57,20 +74,10 @@
   accessibility_service_client_remote_->BindTts(std::move(tts_receiver));
 }
 
-void FakeAccessibilityService::BindAnotherAutoclickClient() {
-  mojo::PendingReceiver<ax::mojom::AutoclickClient> autoclick_client_receiver;
-  autoclick_client_remotes_.Add(
-      autoclick_client_receiver.InitWithNewPipeAndPassRemote());
-  accessibility_service_client_remote_->BindAutoclickClient(
-      std::move(autoclick_client_receiver));
-
-  // Now connect the autoclick remote in the service back to the client in the
-  // browser by getting a PendingReceiver<Autoclick> from the browser.
-  for (auto& remote : autoclick_client_remotes_) {
-    remote->BindAutoclick(
-        base::BindOnce(&FakeAccessibilityService::OnAutoclickBoundCallback,
-                       base::Unretained(this)));
-  }
+void FakeAccessibilityService::BindAnotherUserInput() {
+  mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver;
+  ui_remotes_.Add(ui_receiver.InitWithNewPipeAndPassRemote());
+  accessibility_service_client_remote_->BindUserInput(std::move(ui_receiver));
 }
 
 void FakeAccessibilityService::BindAnotherUserInterface() {
@@ -260,6 +267,15 @@
   }
 }
 
+void FakeAccessibilityService::
+    RequestSendSyntheticKeyEventForShortcutOrNavigation(
+        ax::mojom::SyntheticKeyEventPtr key_event) {
+  for (auto& ui_client : ui_remotes_) {
+    ui_client->SendSyntheticKeyEventForShortcutOrNavigation(
+        mojo::Clone(key_event));
+  }
+}
+
 void FakeAccessibilityService::RequestDarkenScreen(bool darken) {
   for (auto& ux_client : ux_remotes_) {
     ux_client->DarkenScreen(darken);
diff --git a/chrome/browser/ash/accessibility/service/fake_accessibility_service.h b/chrome/browser/ash/accessibility/service/fake_accessibility_service.h
index 28060a3..f35a83ec 100644
--- a/chrome/browser/ash/accessibility/service/fake_accessibility_service.h
+++ b/chrome/browser/ash/accessibility/service/fake_accessibility_service.h
@@ -21,6 +21,7 @@
 #include "services/accessibility/public/mojom/speech_recognition.mojom-forward.h"
 #include "services/accessibility/public/mojom/speech_recognition.mojom.h"
 #include "services/accessibility/public/mojom/tts.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
 #include "services/accessibility/public/mojom/user_interface.mojom.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_event.h"
@@ -103,6 +104,7 @@
   void BindAnotherAutoclickClient();
   void BindAnotherSpeechRecognition();
   void BindAnotherTts();
+  void BindAnotherUserInput();
   void BindAnotherUserInterface();
 
   //
@@ -158,6 +160,14 @@
   void RequestTtsVoices(ax::mojom::Tts::GetVoicesCallback callback);
 
   //
+  // Methods to pretend a UserInput request came from the service.
+  //
+
+  // Sends a request to send a synthetic key event.
+  void RequestSendSyntheticKeyEventForShortcutOrNavigation(
+      ax::mojom::SyntheticKeyEventPtr key_event);
+
+  //
   // Methods to pretend a UserInterface request came from the service.
   //
 
@@ -233,6 +243,7 @@
   mojo::RemoteSet<ax::mojom::AutoclickClient> autoclick_client_remotes_;
   mojo::ReceiverSet<ax::mojom::Autoclick> autoclick_receivers_;
   mojo::RemoteSet<ax::mojom::Tts> tts_remotes_;
+  mojo::RemoteSet<ax::mojom::UserInput> ui_remotes_;
   mojo::RemoteSet<ax::mojom::UserInterface> ux_remotes_;
 
   mojo::ReceiverSet<ax::mojom::AssistiveTechnologyController>
diff --git a/chrome/browser/ash/accessibility/service/user_input_impl.cc b/chrome/browser/ash/accessibility/service/user_input_impl.cc
new file mode 100644
index 0000000..d000c9c
--- /dev/null
+++ b/chrome/browser/ash/accessibility/service/user_input_impl.cc
@@ -0,0 +1,59 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/accessibility/service/user_input_impl.h"
+
+#include "ash/public/cpp/window_tree_host_lookup.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/mojom/event_mojom_traits.h"
+#include "ui/events/types/event_type.h"
+
+namespace ash {
+
+namespace {
+
+aura::WindowTreeHost* GetHostForPrimaryDisplay() {
+  display::Screen* screen = display::Screen::GetScreen();
+  CHECK(screen);
+
+  aura::WindowTreeHost* host = ash::GetWindowTreeHostForDisplay(
+      display::Screen::GetScreen()->GetPrimaryDisplay().id());
+  CHECK(host);
+  return host;
+}
+
+}  // namespace
+
+UserInputImpl::UserInputImpl() = default;
+UserInputImpl::~UserInputImpl() = default;
+
+void UserInputImpl::Bind(
+    mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver) {
+  ui_receivers_.Add(this, std::move(ui_receiver));
+}
+
+// TODO(b/311415118): Convert to actions in the service process, instead of
+// sending full key events.
+void UserInputImpl::SendSyntheticKeyEventForShortcutOrNavigation(
+    ax::mojom::SyntheticKeyEventPtr key_event) {
+  // TODO(b/307553499): Convert SyntheticKeyEvent to use dom_code and dom_key.
+  ui::KeyboardCode key_code =
+      static_cast<ui::KeyboardCode>(key_event->key_data->key_code);
+  ui::EventType type = mojo::ConvertTo<ui::EventType>(key_event->type);
+  ui::KeyEvent synthetic_key_event(type, key_code, key_event->flags);
+
+  auto* host = GetHostForPrimaryDisplay();
+  // Skips sending to rewriters.
+  host->DeliverEventToSink(&synthetic_key_event);
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/accessibility/service/user_input_impl.h b/chrome/browser/ash/accessibility/service/user_input_impl.h
new file mode 100644
index 0000000..b4fdb91
--- /dev/null
+++ b/chrome/browser/ash/accessibility/service/user_input_impl.h
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_ACCESSIBILITY_SERVICE_USER_INPUT_IMPL_H_
+#define CHROME_BROWSER_ASH_ACCESSIBILITY_SERVICE_USER_INPUT_IMPL_H_
+
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
+
+namespace ash {
+
+// The UserInputImpl performs actions for an accessibility service, such as
+// sending synthetic events or performing an accelerator action.
+class UserInputImpl : public ax::mojom::UserInput {
+ public:
+  UserInputImpl();
+  UserInputImpl(const UserInputImpl&) = delete;
+  UserInputImpl& operator=(const UserInputImpl&) = delete;
+  ~UserInputImpl() override;
+
+  void Bind(mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver);
+
+  // ax::mojom::UserInput:
+
+  // Synthetic key events are only used for simulated keyboard navigation, and
+  // do not support internationalization. Any text entry should be done via IME.
+  void SendSyntheticKeyEventForShortcutOrNavigation(
+      ax::mojom::SyntheticKeyEventPtr key_event) override;
+
+ private:
+  mojo::ReceiverSet<ax::mojom::UserInput> ui_receivers_;
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_ACCESSIBILITY_SERVICE_USER_INPUT_IMPL_H_
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
index 01b7062..62b52c4 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
@@ -473,13 +473,13 @@
 
   if (mouse_action_ != MouseAction::NONE) {
     if (mouse_action_ == MouseAction::PRIMARY_CLICK) {
-      auto left_click_icon = gfx::CreateVectorIcon(
-          gfx::IconDescription(kMouseLeftClickViewIcon, kIconSize));
-      SetImage(views::Button::STATE_NORMAL, left_click_icon);
+      auto left_click_icon = ui::ImageModel::FromVectorIcon(
+          kMouseLeftClickViewIcon, gfx::kPlaceholderColor, kIconSize);
+      SetImageModel(views::Button::STATE_NORMAL, left_click_icon);
     } else {
-      auto right_click_icon = gfx::CreateVectorIcon(
-          gfx::IconDescription(kMouseRightClickViewIcon, kIconSize));
-      SetImage(views::Button::STATE_NORMAL, right_click_icon);
+      auto right_click_icon = ui::ImageModel::FromVectorIcon(
+          kMouseRightClickViewIcon, gfx::kPlaceholderColor, kIconSize);
+      SetImageModel(views::Button::STATE_NORMAL, right_click_icon);
     }
   }
 
@@ -510,13 +510,13 @@
 
   if (mouse_action_ != MouseAction::NONE) {
     if (mouse_action_ == MouseAction::PRIMARY_CLICK) {
-      auto left_click_icon = gfx::CreateVectorIcon(
-          gfx::IconDescription(kMouseLeftClickEditIcon, kIconSize));
-      SetImage(views::Button::STATE_NORMAL, left_click_icon);
+      auto left_click_icon = ui::ImageModel::FromVectorIcon(
+          kMouseLeftClickEditIcon, gfx::kPlaceholderColor, kIconSize);
+      SetImageModel(views::Button::STATE_NORMAL, left_click_icon);
     } else {
-      auto right_click_icon = gfx::CreateVectorIcon(
-          gfx::IconDescription(kMouseRightClickEditIcon, kIconSize));
-      SetImage(views::Button::STATE_NORMAL, right_click_icon);
+      auto right_click_icon = ui::ImageModel::FromVectorIcon(
+          kMouseRightClickEditIcon, gfx::kPlaceholderColor, kIconSize);
+      SetImageModel(views::Button::STATE_NORMAL, right_click_icon);
     }
   }
   SetToEditDefault();
diff --git a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
index 8092811..2cf8025 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
@@ -76,20 +76,21 @@
   image()->SetHorizontalAlignment(views::ImageView::Alignment::kLeading);
   switch (message_type) {
     case MessageType::kInfo:
-      SetImage(views::Button::STATE_NORMAL,
-               gfx::CreateVectorIcon(gfx::IconDescription(
-                   vector_icons::kInfoOutlineIcon, kIconSize, kInfoIconColor)));
+      SetImageModel(
+          views::Button::STATE_NORMAL,
+          ui::ImageModel::FromVectorIcon(vector_icons::kInfoOutlineIcon,
+                                         kInfoIconColor, kIconSize));
       break;
     case MessageType::kError:
-      SetImage(
+      SetImageModel(
           views::Button::STATE_NORMAL,
-          gfx::CreateVectorIcon(gfx::IconDescription(
-              vector_icons::kErrorOutlineIcon, kIconSize, kErrorIconColor)));
+          ui::ImageModel::FromVectorIcon(vector_icons::kErrorOutlineIcon,
+                                         kErrorIconColor, kIconSize));
       break;
     case MessageType::kInfoLabelFocus:
-      SetImage(views::Button::STATE_NORMAL,
-               gfx::CreateVectorIcon(gfx::IconDescription(
-                   vector_icons::kKeyboardIcon, kIconSize, kInfoIconColor)));
+      SetImageModel(views::Button::STATE_NORMAL,
+                    ui::ImageModel::FromVectorIcon(vector_icons::kKeyboardIcon,
+                                                   kInfoIconColor, kIconSize));
       break;
     default:
       NOTREACHED();
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc
index 7d49761..a0216e6 100644
--- a/chrome/browser/ash/crosapi/browser_util_unittest.cc
+++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "ash/components/arc/test/arc_util_test_support.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "base/command_line.h"
@@ -20,17 +19,13 @@
 #include "base/values.h"
 #include "chrome/browser/ash/crosapi/crosapi_util.h"
 #include "chrome/browser/ash/crosapi/environment_provider.h"
-#include "chrome/browser/ash/crosapi/idle_service_ash.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
-#include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
-#include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/standalone_browser/browser_support.h"
 #include "chromeos/ash/components/standalone_browser/lacros_availability.h"
 #include "chromeos/ash/components/standalone_browser/migrator_util.h"
 #include "chromeos/ash/components/standalone_browser/standalone_browser_features.h"
-#include "chromeos/ash/components/system/fake_statistics_provider.h"
 #include "chromeos/crosapi/mojom/crosapi.mojom.h"
 #include "components/account_id/account_id.h"
 #include "components/policy/policy_constants.h"
@@ -117,10 +112,6 @@
 
   void SetUp() override {
     fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>());
-    browser_util::RegisterLocalStatePrefs(pref_service_.registry());
-    ash::standalone_browser::migrator_util::RegisterLocalStatePrefs(
-        pref_service_.registry());
-    ash::system::StatisticsProvider::SetTestProvider(&statistics_provider_);
   }
 
   void TearDown() override {
@@ -128,13 +119,12 @@
             IsInitializedForPrimaryUser()) {
       ash::standalone_browser::BrowserSupport::Shutdown();
     }
-    ash::system::StatisticsProvider::SetTestProvider(nullptr);
     fake_user_manager_.Reset();
     ash::standalone_browser::BrowserSupport::SetCpuSupportedForTesting(
         absl::nullopt);
   }
 
-  void AddRegularUser(const std::string& email) {
+  const user_manager::User* AddRegularUser(const std::string& email) {
     AccountId account_id = AccountId::FromUserEmail(email);
     const User* user = fake_user_manager_->AddUser(account_id);
     fake_user_manager_->UserLoggedIn(account_id, user->username_hash(),
@@ -142,34 +132,26 @@
                                      /*is_child=*/false);
     ash::standalone_browser::BrowserSupport::InitializeForPrimaryUser(
         policy::PolicyMap());
-    ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
-        user, &testing_profile_);
+    return user;
   }
 
-  // The order of these members is relevant for both construction and
-  // destruction timing.
+  TestingPrefServiceSimple* local_state() { return local_state_.Get(); }
+
   content::BrowserTaskEnvironment task_environment_;
+  // Set up local_state of BrowserProcess before initializing
+  // FakeChromeUserManager, since its ctor injects local_state to the instance.
+  // This is to inject local_state to functions in browser_util, because
+  // some of them depend on local_state returned from UserManager.
+  ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()};
   user_manager::TypedScopedUserManager<ash::FakeChromeUserManager>
       fake_user_manager_;
-  TestingProfile testing_profile_;
-  TestingPrefServiceSimple pref_service_;
-  ash::system::FakeStatisticsProvider statistics_provider_;
-};
-
-// TODO(hidehiko): Replace with ScopedTestingLocalState.
-class ScopedLocalState {
- public:
-  explicit ScopedLocalState(PrefService* local_state) {
-    TestingBrowserProcess::GetGlobal()->SetLocalState(local_state);
-  }
-
-  ~ScopedLocalState() {
-    TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr);
-  }
 };
 
 TEST_F(BrowserUtilTest, LacrosEnabledByFlag) {
-  AddRegularUser("user@test.com");
+  const user_manager::User* const user = AddRegularUser("user@test.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   {
     // Lacros is initially disabled.
@@ -212,13 +194,7 @@
 }
 
 TEST_F(BrowserUtilTest, LacrosDisabledWithoutMigration) {
-  // This sets `g_browser_process->local_state()` which activates the check
-  // `IsProfileMigrationCompletedForUser()` inside `IsLacrosEnabled()`.
-  ScopedLocalState scoped_local_state(&pref_service_);
-
-  AddRegularUser("user@test.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@test.com");
 
   // Lacros is enabled only after profile migration for LacrosOnly mode.
   {
@@ -233,7 +209,7 @@
     EXPECT_FALSE(browser_util::IsLacrosEnabled());
 
     ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
-        &pref_service_, user->username_hash(),
+        local_state(), user->username_hash(),
         ash::standalone_browser::migrator_util::MigrationMode::kCopy);
 
     EXPECT_TRUE(browser_util::IsLacrosEnabled());
@@ -241,14 +217,7 @@
 }
 
 TEST_F(BrowserUtilTest, IsLacrosEnabledForMigrationBeforePolicyInit) {
-  // This sets `g_browser_process->local_state()` which activates the check
-  // `IsProfileMigrationCompletedForUser()` inside `IsLacrosEnabled()`.
-  ScopedLocalState scoped_local_state(&pref_service_);
-
-  // Add an user.
-  AddRegularUser("user@test.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@test.com");
 
   // Lacros is not enabled yet for profile migration to happen.
   EXPECT_FALSE(browser_util::IsLacrosEnabledForMigration(
@@ -266,7 +235,10 @@
 }
 
 TEST_F(BrowserUtilTest, LacrosEnabled) {
-  AddRegularUser("user@test.com");
+  const user_manager::User* const user = AddRegularUser("user@test.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   EXPECT_FALSE(browser_util::IsLacrosEnabled());
 
@@ -280,7 +252,11 @@
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       {ash::standalone_browser::features::kLacrosOnly}, {});
-  AddRegularUser("user@managedchrome.com");
+  const user_manager::User* const user =
+      AddRegularUser("user@managedchrome.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   {
     ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosDisallowed);
@@ -298,13 +274,18 @@
   fake_user_manager_->UserLoggedIn(account_id, user->username_hash(),
                                    /*browser_restart=*/false,
                                    /*is_child=*/true);
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
   EXPECT_FALSE(browser_util::IsLacrosEnabled());
 }
 
 TEST_F(BrowserUtilTest, AshWebBrowserEnabled) {
-  AddRegularUser("user@managedchrome.com");
   const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+      AddRegularUser("user@managedchrome.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   // Lacros is not allowed.
   {
@@ -355,10 +336,7 @@
 }
 
 TEST_F(BrowserUtilTest, IsAshWebBrowserEnabledForMigration) {
-  // Add an user.
-  AddRegularUser("user@test.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@test.com");
 
   // Ash browser is enabled if Lacros is not enabled.
   EXPECT_TRUE(browser_util::IsAshWebBrowserEnabledForMigration(
@@ -377,10 +355,11 @@
 }
 
 TEST_F(BrowserUtilTest, IsAshWebBrowserDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  AddRegularUser("user@managedchrome.com");
   const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+      AddRegularUser("user@managedchrome.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
   ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly);
 
   // Lacros is allowed and enabled and is the only browser by policy.
@@ -392,9 +371,10 @@
 }
 
 TEST_F(BrowserUtilTest, IsAshWebBrowserDisabledByFlags) {
-  AddRegularUser("user@test.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@test.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
   EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled());
 
   // Just enabling LacrosOnly feature is enough.
@@ -407,7 +387,10 @@
 }
 
 TEST_F(BrowserUtilTest, LacrosOnlyBrowserByFlags) {
-  AddRegularUser("user@test.com");
+  const user_manager::User* const user = AddRegularUser("user@test.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
   EXPECT_FALSE(browser_util::IsLacrosEnabled());
 
   // Just setting LacrosOnly should work.
@@ -418,10 +401,14 @@
 }
 
 TEST_F(BrowserUtilTest, LacrosDisabledForOldHardware) {
-  AddRegularUser("user@test.com");
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       {ash::standalone_browser::features::kLacrosOnly}, {});
+
+  const user_manager::User* const user = AddRegularUser("user@test.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
   EXPECT_TRUE(browser_util::IsLacrosEnabled());
 
   ash::standalone_browser::BrowserSupport::SetCpuSupportedForTesting(false);
@@ -439,7 +426,11 @@
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       {ash::standalone_browser::features::kLacrosOnly}, {});
-  AddRegularUser("user@managedchrome.com");
+  const user_manager::User* const user =
+      AddRegularUser("user@managedchrome.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   {
     ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosDisallowed);
@@ -515,8 +506,7 @@
 
 TEST_F(BrowserUtilTest, GetMissingDataVer) {
   std::string user_id_hash = "1234";
-  base::Version version =
-      browser_util::GetDataVer(&pref_service_, user_id_hash);
+  base::Version version = browser_util::GetDataVer(local_state(), user_id_hash);
   EXPECT_FALSE(version.IsValid());
 }
 
@@ -524,10 +514,9 @@
   base::Value::Dict dictionary_value;
   std::string user_id_hash = "1234";
   dictionary_value.Set(user_id_hash, "corrupted");
-  pref_service_.Set(browser_util::kDataVerPref,
-                    base::Value(std::move(dictionary_value)));
-  base::Version version =
-      browser_util::GetDataVer(&pref_service_, user_id_hash);
+  local_state()->Set(browser_util::kDataVerPref,
+                     base::Value(std::move(dictionary_value)));
+  base::Version version = browser_util::GetDataVer(local_state(), user_id_hash);
   EXPECT_FALSE(version.IsValid());
 }
 
@@ -536,23 +525,23 @@
   std::string user_id_hash = "1234";
   base::Version version{"1.1.1.1"};
   dictionary_value.Set(user_id_hash, version.GetString());
-  pref_service_.Set(browser_util::kDataVerPref,
-                    base::Value(std::move(dictionary_value)));
+  local_state()->Set(browser_util::kDataVerPref,
+                     base::Value(std::move(dictionary_value)));
 
   base::Version result_version =
-      browser_util::GetDataVer(&pref_service_, user_id_hash);
+      browser_util::GetDataVer(local_state(), user_id_hash);
   EXPECT_EQ(version, result_version);
 }
 
 TEST_F(BrowserUtilTest, RecordDataVer) {
   std::string user_id_hash = "1234";
   base::Version version{"1.1.1.1"};
-  browser_util::RecordDataVer(&pref_service_, user_id_hash, version);
+  browser_util::RecordDataVer(local_state(), user_id_hash, version);
 
   base::Value::Dict expected;
   expected.Set(user_id_hash, version.GetString());
   const base::Value::Dict& dict =
-      pref_service_.GetDict(browser_util::kDataVerPref);
+      local_state()->GetDict(browser_util::kDataVerPref);
   EXPECT_EQ(dict, expected);
 }
 
@@ -561,14 +550,14 @@
 
   base::Version version1{"1.1.1.1"};
   base::Version version2{"1.1.1.2"};
-  browser_util::RecordDataVer(&pref_service_, user_id_hash, version1);
-  browser_util::RecordDataVer(&pref_service_, user_id_hash, version2);
+  browser_util::RecordDataVer(local_state(), user_id_hash, version1);
+  browser_util::RecordDataVer(local_state(), user_id_hash, version2);
 
   base::Value::Dict expected;
   expected.Set(user_id_hash, version2.GetString());
 
   const base::Value::Dict& dict =
-      pref_service_.GetDict(browser_util::kDataVerPref);
+      local_state()->GetDict(browser_util::kDataVerPref);
   EXPECT_EQ(dict, expected);
 }
 
@@ -577,21 +566,21 @@
   std::string user_id_hash_2 = "2345";
   base::Version version1{"1.1.1.1"};
   base::Version version2{"1.1.1.2"};
-  browser_util::RecordDataVer(&pref_service_, user_id_hash_1, version1);
-  browser_util::RecordDataVer(&pref_service_, user_id_hash_2, version2);
+  browser_util::RecordDataVer(local_state(), user_id_hash_1, version1);
+  browser_util::RecordDataVer(local_state(), user_id_hash_2, version2);
 
-  EXPECT_EQ(version1, browser_util::GetDataVer(&pref_service_, user_id_hash_1));
-  EXPECT_EQ(version2, browser_util::GetDataVer(&pref_service_, user_id_hash_2));
+  EXPECT_EQ(version1, browser_util::GetDataVer(local_state(), user_id_hash_1));
+  EXPECT_EQ(version2, browser_util::GetDataVer(local_state(), user_id_hash_2));
 
   base::Version version3{"3.3.3.3"};
-  browser_util::RecordDataVer(&pref_service_, user_id_hash_1, version3);
+  browser_util::RecordDataVer(local_state(), user_id_hash_1, version3);
 
   base::Value::Dict expected;
   expected.Set(user_id_hash_1, version3.GetString());
   expected.Set(user_id_hash_2, version2.GetString());
 
   const base::Value::Dict& dict =
-      pref_service_.GetDict(browser_util::kDataVerPref);
+      local_state()->GetDict(browser_util::kDataVerPref);
   EXPECT_EQ(dict, expected);
 }
 
@@ -668,18 +657,16 @@
   using browser_util::GetMigrationStatus;
   using browser_util::MigrationStatus;
 
-  AddRegularUser("user@test.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@test.com");
 
-  EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+  EXPECT_EQ(GetMigrationStatus(local_state(), user),
             MigrationStatus::kLacrosNotEnabled);
 
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       {ash::standalone_browser::features::kLacrosOnly}, {});
 
-  EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+  EXPECT_EQ(GetMigrationStatus(local_state(), user),
             MigrationStatus::kUncompleted);
 
   {
@@ -687,58 +674,63 @@
          i < ash::standalone_browser::migrator_util::kMaxMigrationAttemptCount;
          i++) {
       ash::standalone_browser::migrator_util::
-          UpdateMigrationAttemptCountForUser(&pref_service_,
+          UpdateMigrationAttemptCountForUser(local_state(),
                                              user->username_hash());
     }
 
-    EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+    EXPECT_EQ(GetMigrationStatus(local_state(), user),
               MigrationStatus::kMaxAttemptReached);
 
     ash::standalone_browser::migrator_util::ClearMigrationAttemptCountForUser(
-        &pref_service_, user->username_hash());
+        local_state(), user->username_hash());
   }
 
   {
     ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
-        &pref_service_, user->username_hash(),
+        local_state(), user->username_hash(),
         ash::standalone_browser::migrator_util::MigrationMode::kCopy);
 
-    EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+    EXPECT_EQ(GetMigrationStatus(local_state(), user),
               MigrationStatus::kCopyCompleted);
 
     ash::standalone_browser::migrator_util::
-        ClearProfileMigrationCompletedForUser(&pref_service_,
+        ClearProfileMigrationCompletedForUser(local_state(),
                                               user->username_hash());
   }
 
   {
     ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
-        &pref_service_, user->username_hash(),
+        local_state(), user->username_hash(),
         ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
-    EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+    EXPECT_EQ(GetMigrationStatus(local_state(), user),
               MigrationStatus::kMoveCompleted);
 
     ash::standalone_browser::migrator_util::
-        ClearProfileMigrationCompletedForUser(&pref_service_,
+        ClearProfileMigrationCompletedForUser(local_state(),
                                               user->username_hash());
   }
 
   {
     ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
-        &pref_service_, user->username_hash(),
+        local_state(), user->username_hash(),
         ash::standalone_browser::migrator_util::MigrationMode::kSkipForNewUser);
 
-    EXPECT_EQ(GetMigrationStatus(&pref_service_, user),
+    EXPECT_EQ(GetMigrationStatus(local_state(), user),
               MigrationStatus::kSkippedForNewUser);
 
     ash::standalone_browser::migrator_util::
-        ClearProfileMigrationCompletedForUser(&pref_service_,
+        ClearProfileMigrationCompletedForUser(local_state(),
                                               user->username_hash());
   }
 }
 
 TEST_F(BrowserUtilTest, IsAshBrowserSyncEnabled) {
+  const user_manager::User* const user = AddRegularUser("user@random.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
+
   {
     EXPECT_FALSE(browser_util::IsLacrosEnabled());
     EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled());
@@ -749,9 +741,9 @@
     base::test::ScopedFeatureList feature_list;
     feature_list.InitWithFeatures(
         {ash::standalone_browser::features::kLacrosOnly}, {});
-    EXPECT_FALSE(browser_util::IsLacrosEnabled());
-    EXPECT_TRUE(browser_util::IsAshWebBrowserEnabled());
-    EXPECT_TRUE(browser_util::IsAshBrowserSyncEnabled());
+    EXPECT_TRUE(browser_util::IsLacrosEnabled());
+    EXPECT_FALSE(browser_util::IsAshWebBrowserEnabled());
+    EXPECT_FALSE(browser_util::IsAshBrowserSyncEnabled());
   }
 }
 
@@ -838,7 +830,10 @@
 
 // Lacros availability has an effect on googlers
 TEST_F(BrowserUtilTest, LacrosAvailabilityIgnoreGoogleEnableToUserChoice) {
-  AddRegularUser("user@google.com");
+  const user_manager::User* const user = AddRegularUser("user@google.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
 
   base::test::ScopedCommandLine cmd_line;
   cmd_line.GetProcessCommandLine()->AppendSwitch(
@@ -851,7 +846,11 @@
 // Check that the exist configurations used for the Google rollout have the
 // precisely intended side-effects.
 TEST_F(BrowserUtilTest, LacrosGoogleRolloutUserChoice) {
-  AddRegularUser("user@google.com");
+  const user_manager::User* const user = AddRegularUser("user@google.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
+
   // Lacros availability is set by policy to user choice.
   ScopedLacrosAvailabilityCache cache(LacrosAvailability::kUserChoice);
 
@@ -866,9 +865,11 @@
 }
 
 TEST_F(BrowserUtilTest, LacrosGoogleRolloutOnly) {
-  AddRegularUser("user@google.com");
-  const user_manager::User* const user =
-      ash::ProfileHelper::Get()->GetUserByProfile(&testing_profile_);
+  const user_manager::User* const user = AddRegularUser("user@google.com");
+  ash::standalone_browser::migrator_util::SetProfileMigrationCompletedForUser(
+      local_state(), user->username_hash(),
+      ash::standalone_browser::migrator_util::MigrationMode::kMove);
+
   // Lacros availability is set by policy to only.
   ScopedLacrosAvailabilityCache cache(LacrosAvailability::kLacrosOnly);
 
@@ -884,64 +885,6 @@
       user, browser_util::PolicyInitState::kAfterInit));
 }
 
-TEST_F(BrowserUtilTest, IsArcAvailable) {
-  arc::SetArcAvailableCommandLineForTesting(
-      base::CommandLine::ForCurrentProcess());
-  IdleServiceAsh::DisableForTesting();
-  ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
-  AddRegularUser("user@google.com");
-
-  EnvironmentProvider environment_provider;
-  mojom::BrowserInitParamsPtr browser_init_params =
-      browser_util::GetBrowserInitParams(
-          &environment_provider,
-          browser_util::InitialBrowserAction(
-              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
-          /*is_keep_alive_enabled=*/false, absl::nullopt);
-  EXPECT_TRUE(browser_init_params->device_properties->is_arc_available);
-  EXPECT_FALSE(browser_init_params->device_properties->is_tablet_form_factor);
-}
-
-TEST_F(BrowserUtilTest, IsTabletFormFactor) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      ash::switches::kEnableTabletFormFactor);
-  IdleServiceAsh::DisableForTesting();
-  ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
-  AddRegularUser("user@google.com");
-
-  EnvironmentProvider environment_provider;
-  mojom::BrowserInitParamsPtr browser_init_params =
-      browser_util::GetBrowserInitParams(
-          &environment_provider,
-          browser_util::InitialBrowserAction(
-              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
-          /*is_keep_alive_enabled=*/false, absl::nullopt);
-  EXPECT_FALSE(browser_init_params->device_properties->is_arc_available);
-  EXPECT_TRUE(browser_init_params->device_properties->is_tablet_form_factor);
-}
-
-TEST_F(BrowserUtilTest, SerialNumber) {
-  IdleServiceAsh::DisableForTesting();
-  ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
-  AddRegularUser("user@google.com");
-
-  std::string expected_serial_number = "fake-serial-number";
-  statistics_provider_.SetMachineStatistic("serial_number",
-                                           expected_serial_number);
-
-  EnvironmentProvider environment_provider;
-  mojom::BrowserInitParamsPtr browser_init_params =
-      browser_util::GetBrowserInitParams(
-          &environment_provider,
-          browser_util::InitialBrowserAction(
-              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
-          /*is_keep_alive_enabled=*/false, absl::nullopt);
-
-  auto serial_number = browser_init_params->device_properties->serial_number;
-  ASSERT_TRUE(serial_number.has_value());
-  EXPECT_EQ(serial_number.value(), expected_serial_number);
-}
-
 TEST_F(BrowserUtilTest, LacrosSelection) {
   // Neither policy nor command line have any preference on Lacros selection.
   EXPECT_FALSE(browser_util::DetermineLacrosSelection());
diff --git a/chrome/browser/ash/crosapi/crosapi_util_unittest.cc b/chrome/browser/ash/crosapi/crosapi_util_unittest.cc
index 392f9eca..eb10750 100644
--- a/chrome/browser/ash/crosapi/crosapi_util_unittest.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util_unittest.cc
@@ -7,15 +7,22 @@
 #include <memory>
 #include <string>
 
+#include "ash/components/arc/test/arc_util_test_support.h"
+#include "ash/constants/ash_switches.h"
+#include "base/command_line.h"
 #include "base/memory/raw_ptr.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
+#include "chrome/browser/ash/crosapi/idle_service_ash.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/ash/components/browser_context_helper/browser_context_types.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
+#include "chromeos/ash/components/system/fake_statistics_provider.h"
+#include "chromeos/ash/components/system/statistics_provider.h"
 #include "chromeos/crosapi/mojom/keystore_service.mojom.h"
 #include "components/user_manager/scoped_user_manager.h"
 #include "content/public/test/browser_task_environment.h"
@@ -34,6 +41,7 @@
   void SetUp() override {
     fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>());
     browser_util::RegisterLocalStatePrefs(pref_service_.registry());
+    ash::system::StatisticsProvider::SetTestProvider(&statistics_provider_);
 
     profile_manager_ = std::make_unique<TestingProfileManager>(
         TestingBrowserProcess::GetGlobal());
@@ -42,12 +50,19 @@
         TestingProfile::kDefaultProfileUserName);
   }
 
+  void TearDown() override {
+    ash::system::StatisticsProvider::SetTestProvider(nullptr);
+  }
+
   void AddRegularUser(const std::string& email) {
     AccountId account_id = AccountId::FromUserEmail(email);
     const User* user = fake_user_manager_->AddUser(account_id);
     fake_user_manager_->UserLoggedIn(account_id, user->username_hash(),
                                      /*browser_restart=*/false,
                                      /*is_child=*/false);
+
+    ash::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
+        user, testing_profile_.get());
   }
 
   // The order of these members is relevant for both construction and
@@ -55,6 +70,7 @@
   content::BrowserTaskEnvironment task_environment_;
   user_manager::TypedScopedUserManager<ash::FakeChromeUserManager>
       fake_user_manager_;
+  ash::system::FakeStatisticsProvider statistics_provider_;
   std::unique_ptr<TestingProfileManager> profile_manager_;
   raw_ptr<TestingProfile> testing_profile_;
   TestingPrefServiceSimple pref_service_;
@@ -205,4 +221,59 @@
             kReportDeviceNetworkTelemetryCollectionRateMs);
 }
 
+TEST_F(CrosapiUtilTest, IsArcAvailable) {
+  arc::SetArcAvailableCommandLineForTesting(
+      base::CommandLine::ForCurrentProcess());
+  IdleServiceAsh::DisableForTesting();
+  AddRegularUser("user@google.com");
+
+  EnvironmentProvider environment_provider;
+  mojom::BrowserInitParamsPtr browser_init_params =
+      browser_util::GetBrowserInitParams(
+          &environment_provider,
+          browser_util::InitialBrowserAction(
+              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
+          /*is_keep_alive_enabled=*/false, absl::nullopt);
+  EXPECT_TRUE(browser_init_params->device_properties->is_arc_available);
+  EXPECT_FALSE(browser_init_params->device_properties->is_tablet_form_factor);
+}
+
+TEST_F(CrosapiUtilTest, IsTabletFormFactor) {
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      ash::switches::kEnableTabletFormFactor);
+  IdleServiceAsh::DisableForTesting();
+  AddRegularUser("user@google.com");
+
+  EnvironmentProvider environment_provider;
+  mojom::BrowserInitParamsPtr browser_init_params =
+      browser_util::GetBrowserInitParams(
+          &environment_provider,
+          browser_util::InitialBrowserAction(
+              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
+          /*is_keep_alive_enabled=*/false, absl::nullopt);
+  EXPECT_FALSE(browser_init_params->device_properties->is_arc_available);
+  EXPECT_TRUE(browser_init_params->device_properties->is_tablet_form_factor);
+}
+
+TEST_F(CrosapiUtilTest, SerialNumber) {
+  IdleServiceAsh::DisableForTesting();
+  AddRegularUser("user@google.com");
+
+  std::string expected_serial_number = "fake-serial-number";
+  statistics_provider_.SetMachineStatistic("serial_number",
+                                           expected_serial_number);
+
+  EnvironmentProvider environment_provider;
+  mojom::BrowserInitParamsPtr browser_init_params =
+      browser_util::GetBrowserInitParams(
+          &environment_provider,
+          browser_util::InitialBrowserAction(
+              crosapi::mojom::InitialBrowserAction::kDoNotOpenWindow),
+          /*is_keep_alive_enabled=*/false, absl::nullopt);
+
+  auto serial_number = browser_init_params->device_properties->serial_number;
+  ASSERT_TRUE(serial_number.has_value());
+  EXPECT_EQ(serial_number.value(), expected_serial_number);
+}
+
 }  // namespace crosapi
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index cc19fdb..717ba9f 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -1046,7 +1046,8 @@
 
 bool IsUpgradableContainerVersion(ContainerOsVersion version) {
   return version == ContainerOsVersion::kDebianStretch ||
-         version == ContainerOsVersion::kDebianBuster;
+         version == ContainerOsVersion::kDebianBuster ||
+         version == ContainerOsVersion::kDebianBullseye;
 }
 
 }  // namespace
@@ -1504,6 +1505,7 @@
   request.set_timeout(static_cast<uint32_t>(kStartVmTimeout.InSeconds()));
   if (base::FeatureList::IsEnabled(ash::features::kCrostiniGpuSupport)) {
     request.set_enable_gpu(true);
+    request.set_enable_vulkan(true);
   }
   if (profile_->GetPrefs()->GetBoolean(prefs::kCrostiniMicAllowed) &&
       profile_->GetPrefs()->GetBoolean(::prefs::kAudioCaptureAllowed)) {
diff --git a/chrome/browser/ash/crostini/crostini_upgrader.cc b/chrome/browser/ash/crostini/crostini_upgrader.cc
index 6296284..9cdbd61 100644
--- a/chrome/browser/ash/crostini/crostini_upgrader.cc
+++ b/chrome/browser/ash/crostini/crostini_upgrader.cc
@@ -334,7 +334,7 @@
               return;
             }
 
-            auto target_version = ContainerVersion::BULLSEYE;
+            auto target_version = ContainerVersion::BOOKWORM;
 
             CrostiniManager::GetForProfile(weak_this->profile_)
                 ->UpgradeContainer(
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 36cb194..ba65ba8 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -854,6 +854,7 @@
             .NewDirectoryTree(),
         TestCase("directoryTreeExpandFolderOnDelayExpansionVolume")
             .NewDirectoryTree(),
+        TestCase("directoryTreeExpandAndSelectedOnDragMove").NewDirectoryTree(),
         // Section end - browser tests for new directory tree
         TestCase("directoryTreeActiveDirectory"),
         TestCase("directoryTreeSelectedDirectory"),
@@ -866,7 +867,8 @@
             "directoryTreeExpandFolderWithHiddenFileAndShowHiddenFilesOff"),
         TestCase("directoryTreeExpandFolderWithHiddenFileAndShowHiddenFilesOn"),
         TestCase("directoryTreeExpandFolderOnNonDelayExpansionVolume"),
-        TestCase("directoryTreeExpandFolderOnDelayExpansionVolume")));
+        TestCase("directoryTreeExpandFolderOnDelayExpansionVolume"),
+        TestCase("directoryTreeExpandAndSelectedOnDragMove")));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
     DirectoryTreeContextMenu, /* directory_tree_context_menu.js */
@@ -2013,6 +2015,11 @@
             .NewDirectoryTree(),
         TestCase("searchFileSystemProvider").NewDirectoryTree(),
         TestCase("changingDirectoryClosesSearch").NewDirectoryTree(),
+        TestCase("verifyDriveLocationOption").NewDirectoryTree(),
+        TestCase("unselectCurrentDirectoryInTreeOnSearchInDownloads")
+            .NewDirectoryTree(),
+        TestCase("unselectCurrentDirectoryInTreeOnSearchInDrive")
+            .NewDirectoryTree(),
         // Section end - browser tests for new directory tree
         TestCase("searchDownloadsWithResults"),
         TestCase("searchDownloadsWithNoResults"),
@@ -2051,7 +2058,9 @@
         TestCase("searchImageByContent").EnableLocalImageSearch(),
         TestCase("changingDirectoryClosesSearch"),
         TestCase("searchQueryLaunchParam"),
-        TestCase("verifyDriveLocationOption")));
+        TestCase("verifyDriveLocationOption"),
+        TestCase("unselectCurrentDirectoryInTreeOnSearchInDownloads"),
+        TestCase("unselectCurrentDirectoryInTreeOnSearchInDrive")));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
     Metrics, /* metrics.js */
diff --git a/chrome/browser/ash/file_manager/file_manager_test_util.cc b/chrome/browser/ash/file_manager/file_manager_test_util.cc
index 755011e74..7795f31f2 100644
--- a/chrome/browser/ash/file_manager/file_manager_test_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_test_util.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_ash.h"
 #include "chrome/browser/ash/file_manager/app_id.h"
 #include "chrome/browser/ash/file_manager/file_tasks.h"
+#include "chrome/browser/ash/file_manager/fileapi_util.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/file_manager/volume_manager_observer.h"
 #include "chrome/browser/ash/file_system_provider/fake_extension_provider.h"
@@ -100,6 +101,35 @@
             });
 }
 
+std::vector<storage::FileSystemURL> CopyTestFilesIntoMyFiles(
+    Profile* profile,
+    std::vector<std::string> file_names) {
+  FolderInMyFiles folder(profile);
+  base::FilePath test_data_path;
+  EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_path));
+
+  for (const auto& file_name : file_names) {
+    base::FilePath file_path =
+        test_data_path.AppendASCII("chromeos/file_manager/" + file_name);
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      EXPECT_TRUE(base::PathExists(file_path));
+    }
+    // Copy the file into My Files.
+    folder.Add({file_path});
+  }
+
+  std::vector<storage::FileSystemURL> files;
+  for (const auto& path_in_my_files : folder.files()) {
+    GURL url;
+    CHECK(util::ConvertAbsoluteFilePathToFileSystemUrl(
+        profile, path_in_my_files, util::GetFileManagerURL(), &url));
+    auto* file_system_context = util::GetFileManagerFileSystemContext(profile);
+    files.push_back(file_system_context->CrackURLInFirstPartyContext(url));
+  }
+  return files;
+}
+
 void AddDefaultComponentExtensionsOnMainThread(Profile* profile) {
   CHECK(profile);
 
diff --git a/chrome/browser/ash/file_manager/file_manager_test_util.h b/chrome/browser/ash/file_manager/file_manager_test_util.h
index bf2ba28..54faf307 100644
--- a/chrome/browser/ash/file_manager/file_manager_test_util.h
+++ b/chrome/browser/ash/file_manager/file_manager_test_util.h
@@ -60,6 +60,12 @@
   std::vector<base::FilePath> files_;
 };
 
+// Take test files from the chromeos/file_manager/ test directory and copy them
+// into a temp folder mounted within MyFiles.
+std::vector<storage::FileSystemURL> CopyTestFilesIntoMyFiles(
+    Profile* profile,
+    std::vector<std::string> file_names);
+
 // Load the default set of component extensions used on ChromeOS. This should be
 // done in an override of InProcessBrowserTest::SetUpOnMainThread().
 void AddDefaultComponentExtensionsOnMainThread(Profile* profile);
diff --git a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
index 626f742..a96bc7b2 100644
--- a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
@@ -587,23 +587,8 @@
   TaskDescriptor task_descriptor(extension->id(), TASK_TYPE_FILE_HANDLER,
                                  "tiffAction");
 
-  base::FilePath path;
-  EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path));
-  path = path.AppendASCII("chromeos/file_manager/test_small.tiff");
-  {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    EXPECT_TRUE(base::PathExists(path));
-  }
-  // Copy the file into My Files.
-  file_manager::test::FolderInMyFiles folder(profile);
-  folder.Add({path});
-  base::FilePath path_in_my_files = folder.files()[0];
-
-  GURL tiff_url;
-  CHECK(util::ConvertAbsoluteFilePathToFileSystemUrl(
-      profile, path_in_my_files, util::GetFileManagerURL(), &tiff_url));
-  std::vector<storage::FileSystemURL> files;
-  files.push_back(storage::FileSystemURL::CreateForTest(tiff_url));
+  std::vector<storage::FileSystemURL> files =
+      test::CopyTestFilesIntoMyFiles(profile, {"test_small.tiff"});
 
   content::DOMMessageQueue message_queue;
   ExecuteFileTask(profile, task_descriptor, files, nullptr, base::DoNothing());
diff --git a/chrome/browser/ash/input_method/ui/undo_window.cc b/chrome/browser/ash/input_method/ui/undo_window.cc
index 716ee65..72955e7 100644
--- a/chrome/browser/ash/input_method/ui/undo_window.cc
+++ b/chrome/browser/ash/input_method/ui/undo_window.cc
@@ -87,12 +87,13 @@
 }
 
 void UndoWindow::OnThemeChanged() {
-  undo_button_->SetImage(
+  undo_button_->SetImageModel(
       views::Button::ButtonState::STATE_NORMAL,
-      gfx::CreateVectorIcon(
-          kAutocorrectUndoIcon, kIconSize,
+      ui::ImageModel::FromVectorIcon(
+          kAutocorrectUndoIcon,
           ash::ColorProvider::Get()->GetContentLayerColor(
-              ash::ColorProvider::ContentLayerType::kIconColorPrimary)));
+              ash::ColorProvider::ContentLayerType::kIconColorPrimary),
+          kIconSize));
   undo_button_->SetEnabledTextColors(
       ash::ColorProvider::Get()->GetContentLayerColor(
           ash::ColorProvider::ContentLayerType::kTextColorSecondary));
diff --git a/chrome/browser/ash/profiles/profile_helper.cc b/chrome/browser/ash/profiles/profile_helper.cc
index 7561149..c782260f 100644
--- a/chrome/browser/ash/profiles/profile_helper.cc
+++ b/chrome/browser/ash/profiles/profile_helper.cc
@@ -11,11 +11,10 @@
 
 #include "ash/constants/ash_switches.h"
 #include "base/barrier_closure.h"
+#include "base/check_is_test.h"
 #include "base/command_line.h"
-#include "base/debug/dump_without_crashing.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
@@ -272,19 +271,8 @@
 
   // Many tests do not have their users registered with UserManager and
   // runs here. If |active_user_| matches |profile|, returns it.
-
-  // There's no guard that this is only for testing. Adding metrics here
-  // temporarily to make sure we can safely clean up the code.
-  // TODO(crbug.com/1325210): Remove the metrics together with the following
-  // code refactored.
-  if (base::SysInfo::IsRunningOnChromeOS()) {
-    base::UmaHistogramBoolean("Ash.BrowserContext.UnexpectedGetUserByProfile",
-                              true);
-    // Also taking the stack trace, so we can identify who's the caller on
-    // unexpected cases.
-    base::debug::DumpWithoutCrashing();
-  }
-
+  // This is expected happening only for testing.
+  CHECK_IS_TEST();
   const user_manager::User* active_user = user_manager->GetActiveUser();
   return active_user &&
                  browser_context_helper_->GetBrowserContextPathByUserIdHash(
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 99c2bf51..4c527428 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -304,6 +304,8 @@
 #include "chrome/browser/speech/cros_speech_recognition_service_factory.h"
 #include "chrome/browser/ui/webui/ash/add_supervision/add_supervision.mojom.h"
 #include "chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install_ui.h"
 #include "chrome/browser/ui/webui/ash/audio/audio.mojom.h"
 #include "chrome/browser/ui/webui/ash/audio/audio_ui.h"
 #include "chrome/browser/ui/webui/ash/bluetooth_pairing_dialog.h"
@@ -354,8 +356,6 @@
 #include "chrome/browser/ui/webui/ash/smb_shares/smb_share_dialog.h"
 #include "chrome/browser/ui/webui/ash/vm/vm.mojom.h"
 #include "chrome/browser/ui/webui/ash/vm/vm_ui.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h"
 #include "chrome/browser/ui/webui/feedback/feedback_ui.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h"
@@ -1654,8 +1654,8 @@
   if (base::FeatureList::IsEnabled(
           chromeos::features::kCrosWebAppInstallDialog)) {
     RegisterWebUIControllerInterfaceBinder<
-        ash::web_app_install::mojom::PageHandlerFactory,
-        ash::web_app_install::WebAppInstallDialogUI>(map);
+        ash::app_install::mojom::PageHandlerFactory,
+        ash::app_install::AppInstallDialogUI>(map);
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
diff --git a/chrome/browser/download/bubble/download_bubble_prefs.cc b/chrome/browser/download/bubble/download_bubble_prefs.cc
index 13d63eb..a804282 100644
--- a/chrome/browser/download/bubble/download_bubble_prefs.cc
+++ b/chrome/browser/download/bubble/download_bubble_prefs.cc
@@ -25,11 +25,6 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
-bool IsDownloadBubbleV2Enabled(Profile* profile) {
-  return IsDownloadBubbleEnabled(profile) &&
-         base::FeatureList::IsEnabled(safe_browsing::kDownloadBubbleV2);
-}
-
 bool ShouldShowDownloadBubble(Profile* profile) {
   // If the download UI is disabled by at least one extension, do not show the
   // bubble and the toolbar icon.
diff --git a/chrome/browser/download/bubble/download_bubble_prefs.h b/chrome/browser/download/bubble/download_bubble_prefs.h
index 27d5d5f..b6cba201 100644
--- a/chrome/browser/download/bubble/download_bubble_prefs.h
+++ b/chrome/browser/download/bubble/download_bubble_prefs.h
@@ -10,11 +10,9 @@
 namespace download {
 
 // Called when deciding whether to show the bubble or the old download shelf UI.
+// TODO(chlily): Remove unused profile arg.
 bool IsDownloadBubbleEnabled(Profile* profile);
 
-// V2 is only eligible to be enabled if V1 is also enabled.
-bool IsDownloadBubbleV2Enabled(Profile* profile);
-
 // Called when deciding whether to show or hide the bubble.
 bool ShouldShowDownloadBubble(Profile* profile);
 
diff --git a/chrome/browser/download/bubble/download_bubble_prefs_unittest.cc b/chrome/browser/download/bubble/download_bubble_prefs_unittest.cc
index a166b78..51f24822 100644
--- a/chrome/browser/download/bubble/download_bubble_prefs_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_prefs_unittest.cc
@@ -81,15 +81,6 @@
 #endif
   }
 
-  void ExpectFeatureFlagV2EnabledStatus(bool expect_enabled) {
-    bool is_enabled = IsDownloadBubbleV2Enabled(profile_);
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-    EXPECT_FALSE(is_enabled);
-#else
-    EXPECT_EQ(is_enabled, expect_enabled);
-#endif
-  }
-
  private:
   content::BrowserTaskEnvironment task_environment_;
   TestingProfileManager testing_profile_manager_;
@@ -119,34 +110,6 @@
   EXPECT_TRUE(DoesDownloadConnectorBlock(profile_, GURL()));
 }
 
-TEST_F(DownloadBubblePrefsTest, V2FeatureFlagEnabled) {
-  feature_list_.InitWithFeatures(
-      {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
-  ExpectFeatureFlagEnabledStatus(/*expect_enabled=*/true);
-  ExpectFeatureFlagV2EnabledStatus(/*expect_enabled=*/true);
-}
-
-TEST_F(DownloadBubblePrefsTest, V2FeatureFlagDisabled_YesMVP_NoV2) {
-  feature_list_.InitWithFeatures({safe_browsing::kDownloadBubble},
-                                 {safe_browsing::kDownloadBubbleV2});
-  ExpectFeatureFlagEnabledStatus(/*expect_enabled=*/true);
-  ExpectFeatureFlagV2EnabledStatus(/*expect_enabled=*/false);
-}
-
-TEST_F(DownloadBubblePrefsTest, V2FeatureFlagDisabled_NoMVP_NoV2) {
-  feature_list_.InitWithFeatures(
-      {}, {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2});
-  ExpectFeatureFlagEnabledStatus(/*expect_enabled=*/false);
-  ExpectFeatureFlagV2EnabledStatus(/*expect_enabled=*/false);
-}
-
-TEST_F(DownloadBubblePrefsTest, V2FeatureFlagDisabled_NoMVP_YesV2) {
-  feature_list_.InitWithFeatures({safe_browsing::kDownloadBubbleV2},
-                                 {safe_browsing::kDownloadBubble});
-  ExpectFeatureFlagEnabledStatus(/*expect_enabled=*/false);
-  ExpectFeatureFlagV2EnabledStatus(/*expect_enabled=*/false);
-}
-
 TEST_F(DownloadBubblePrefsTest, ShouldSuppressIph) {
   // Test default value.
   EXPECT_FALSE(ShouldSuppressDownloadBubbleIph(profile_));
diff --git a/chrome/browser/download/bubble/download_bubble_ui_controller.cc b/chrome/browser/download/bubble/download_bubble_ui_controller.cc
index 53bf144..384502eb6 100644
--- a/chrome/browser/download/bubble/download_bubble_ui_controller.cc
+++ b/chrome/browser/download/bubble/download_bubble_ui_controller.cc
@@ -140,18 +140,6 @@
                                  model.ShouldShowDownloadStartedAnimation());
 }
 
-bool DownloadBubbleUIController::ShouldShowIncognitoIcon(
-    const DownloadUIModel* model) const {
-  return download::IsDownloadBubbleV2Enabled(profile_) && model->profile() &&
-         model->profile()->IsIncognitoProfile();
-}
-
-bool DownloadBubbleUIController::ShouldShowGuestIcon(
-    const DownloadUIModel* model) const {
-  return download::IsDownloadBubbleV2Enabled(profile_) && model->profile() &&
-         model->profile()->IsGuestSession();
-}
-
 void DownloadBubbleUIController::OnOfflineItemRemoved(const ContentId& id) {
   if (OfflineItemUtils::IsDownload(id)) {
     return;
diff --git a/chrome/browser/download/bubble/download_bubble_ui_controller.h b/chrome/browser/download/bubble/download_bubble_ui_controller.h
index b217070..e2a2019 100644
--- a/chrome/browser/download/bubble/download_bubble_ui_controller.h
+++ b/chrome/browser/download/bubble/download_bubble_ui_controller.h
@@ -91,12 +91,6 @@
   bool OpenMostSpecificDialog(
       const offline_items_collection::ContentId& content_id);
 
-  // Returns whether the incognito icon should be shown for the download.
-  bool ShouldShowIncognitoIcon(const DownloadUIModel* model) const;
-
-  // Returns whether the guest account icon should be shown for the download.
-  bool ShouldShowGuestIcon(const DownloadUIModel* model) const;
-
   // Schedules the ephemeral warning download to be hidden from the bubble, and
   // subsequently canceled. It will only be canceled if it continues to be an
   // ephemeral warning that hasn't been acted on when the scheduled time
diff --git a/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc b/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
index 4ac3bc7..333b3623 100644
--- a/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
+++ b/chrome/browser/download/bubble/download_bubble_update_service_unittest.cc
@@ -72,8 +72,7 @@
  public:
   DownloadBubbleUpdateServiceTest()
       : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {
-    feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+    feature_list_.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   }
   DownloadBubbleUpdateServiceTest(const DownloadBubbleUpdateServiceTest&) =
       delete;
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index ba284b9..5d4b413 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -30,6 +30,7 @@
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/bubble/download_bubble_prefs.h"
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_crx_util.h"
@@ -1893,6 +1894,9 @@
 #if !BUILDFLAG(IS_ANDROID)
 void ChromeDownloadManagerDelegate::ScheduleCancelForEphemeralWarning(
     const std::string& guid) {
+  if (!download::IsDownloadBubbleEnabled(profile_)) {
+    return;
+  }
   base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&ChromeDownloadManagerDelegate::CancelForEphemeralWarning,
@@ -1916,6 +1920,9 @@
 }
 
 void ChromeDownloadManagerDelegate::CancelAllEphemeralWarnings() {
+  if (!download::IsDownloadBubbleEnabled(profile_)) {
+    return;
+  }
   content::DownloadManager::DownloadVector downloads;
   download_manager_->GetAllDownloads(&downloads);
   for (auto* download : downloads) {
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 7c5699c..b7bcc4b 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -1816,8 +1816,7 @@
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 TEST_F(ChromeDownloadManagerDelegateTest, ScheduleCancelForEphemeralWarning) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+  feature_list.InitAndEnableFeature(safe_browsing::kDownloadBubble);
 
   std::unique_ptr<download::MockDownloadItem> download_item =
       CreateActiveDownloadItem(0);
@@ -1838,8 +1837,7 @@
 TEST_F(ChromeDownloadManagerDelegateTest,
        ScheduleCancelForEphemeralWarning_DownloadKept) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+  feature_list.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   std::unique_ptr<download::MockDownloadItem> download_item =
       CreateActiveDownloadItem(0);
   EXPECT_CALL(*download_item, GetDangerType())
@@ -1856,8 +1854,7 @@
 
 TEST_F(ChromeDownloadManagerDelegateTest, CancelAllEphemeralWarnings) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+  feature_list.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   std::vector<download::DownloadItem*> items;
   auto safe_item = CreateActiveDownloadItem(0);
   EXPECT_CALL(*safe_item, GetDangerType())
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc
index 166c40e..9c52b1a 100644
--- a/chrome/browser/download/download_item_model.cc
+++ b/chrome/browser/download/download_item_model.cc
@@ -518,7 +518,7 @@
   const DownloadItemModelData* data =
       DownloadItemModelData::GetOrCreate(download_);
 #if !BUILDFLAG(IS_ANDROID)
-  if (!data->should_prefer_opening_in_browser_ && IsBubbleV2Enabled()) {
+  if (!data->should_prefer_opening_in_browser_) {
     base::FilePath path = GetTargetFilePath();
     std::string mime_type = GetMimeType();
     DetermineAndSetShouldPreferOpeningInBrowser(
@@ -966,8 +966,7 @@
 }
 
 bool DownloadItemModel::ShouldShowTailoredWarning() const {
-  if (!IsBubbleV2Enabled() ||
-      !base::FeatureList::IsEnabled(safe_browsing::kDownloadTailoredWarnings)) {
+  if (!base::FeatureList::IsEnabled(safe_browsing::kDownloadTailoredWarnings)) {
     return false;
   }
 
@@ -1031,10 +1030,6 @@
 }
 
 bool DownloadItemModel::IsEphemeralWarning() const {
-  if (!IsBubbleV2Enabled()) {
-    return false;
-  }
-
   switch (GetInsecureDownloadStatus()) {
     case download::DownloadItem::InsecureDownloadStatus::BLOCK:
     case download::DownloadItem::InsecureDownloadStatus::WARN:
diff --git a/chrome/browser/download/download_item_model_unittest.cc b/chrome/browser/download/download_item_model_unittest.cc
index 39c0dbd..0c64ae430 100644
--- a/chrome/browser/download/download_item_model_unittest.cc
+++ b/chrome/browser/download/download_item_model_unittest.cc
@@ -233,12 +233,6 @@
     model_.set_status_text_builder_for_testing(for_bubble);
   }
 
-#if !BUILDFLAG(IS_ANDROID)
-  void SetIsBubbleV2Enabled(bool is_enabled) {
-    model_.set_is_bubble_v2_enabled_for_testing(is_enabled);
-  }
-#endif
-
   content::BrowserTaskEnvironment task_environment_;
 
  private:
@@ -579,11 +573,7 @@
               test_case.expected_bubble_status_msg);
 #if !BUILDFLAG(IS_ANDROID)
     // Android doesn't have BubbleUI info.
-    // Whether it's v2 or not doesn't affect the primary button, so it doesn't
-    // matter what we pass here.
-    EXPECT_EQ(model()
-                  .GetBubbleUIInfo(/*is_download_bubble_v2=*/false)
-                  .primary_button_command.value(),
+    EXPECT_EQ(model().GetBubbleUIInfo().primary_button_command.value(),
               DownloadCommands::Command::KEEP);
 #endif  // !BUILDFLAG(IS_ANDROID)
   }
@@ -645,11 +635,7 @@
               test_case.expected_bubble_status_msg);
 #if !BUILDFLAG(IS_ANDROID)
     // Android doesn't have BubbleUI info.
-    // Whether it's v2 or not doesn't affect the primary button, so it doesn't
-    // matter what we pass here.
-    EXPECT_EQ(model()
-                  .GetBubbleUIInfo(/*is_download_bubble_v2=*/true)
-                  .primary_button_command.value(),
+    EXPECT_EQ(model().GetBubbleUIInfo().primary_button_command.value(),
               DownloadCommands::Command::KEEP);
 #endif  // !BUILDFLAG(IS_ANDROID)
   }
@@ -719,19 +705,17 @@
 
 #if !BUILDFLAG(IS_ANDROID)
 
-TEST_F(DownloadItemModelTest, ShouldPreferOpeningInBrowser_V2On) {
+TEST_F(DownloadItemModelTest, ShouldPreferOpeningInBrowser) {
   SetupDownloadItemDefaults();
   SetupCompletedDownloadItem(base::Hours(1));
-  SetIsBubbleV2Enabled(true);
   EXPECT_TRUE(model().ShouldPreferOpeningInBrowser());
 }
 
-TEST_F(DownloadItemModelTest, InProgressOrCompletedBubbleUIInfo_V2On) {
+TEST_F(DownloadItemModelTest, InProgressOrCompletedBubbleUIInfo) {
   SetupDownloadItemDefaults();
 
   SetupCompletedDownloadItem(base::Hours(1));
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
   std::vector<DownloadCommands::Command> quick_action_commands;
   for (auto quick_action : bubble_ui_info.quick_actions) {
     quick_action_commands.push_back(quick_action.command);
@@ -747,7 +731,7 @@
   ON_CALL(item(), GetState())
       .WillByDefault(Return(download::DownloadItem::IN_PROGRESS));
   EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(true));
-  bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  bubble_ui_info = model().GetBubbleUIInfo();
   quick_action_commands = {};
   for (auto quick_action : bubble_ui_info.quick_actions) {
     quick_action_commands.push_back(quick_action.command);
@@ -761,7 +745,7 @@
   Mock::VerifyAndClearExpectations(&model());
 
   EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(false));
-  bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  bubble_ui_info = model().GetBubbleUIInfo();
   quick_action_commands = {};
   for (auto quick_action : bubble_ui_info.quick_actions) {
     quick_action_commands.push_back(quick_action.command);
@@ -772,41 +756,7 @@
   EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
 }
 
-TEST_F(DownloadItemModelTest, InProgressOrCompletedBubbleUIInfo_V2Off) {
-  SetupDownloadItemDefaults();
-
-  SetupCompletedDownloadItem(base::Hours(1));
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false);
-  std::vector<DownloadCommands::Command> quick_action_commands;
-  for (auto quick_action : bubble_ui_info.quick_actions) {
-    quick_action_commands.push_back(quick_action.command);
-  }
-  EXPECT_EQ(quick_action_commands, std::vector<DownloadCommands::Command>());
-  EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
-
-  Mock::VerifyAndClearExpectations(&item());
-  Mock::VerifyAndClearExpectations(&model());
-
-  ON_CALL(item(), GetState())
-      .WillByDefault(Return(download::DownloadItem::IN_PROGRESS));
-  EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(true));
-  bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false);
-  EXPECT_TRUE(bubble_ui_info.quick_actions.empty());
-  EXPECT_EQ(bubble_ui_info.primary_button_command.value(),
-            DownloadCommands::Command::RESUME);
-
-  Mock::VerifyAndClearExpectations(&item());
-  Mock::VerifyAndClearExpectations(&model());
-
-  EXPECT_CALL(item(), IsPaused()).WillRepeatedly(Return(false));
-  bubble_ui_info = model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false);
-  EXPECT_TRUE(bubble_ui_info.quick_actions.empty());
-  EXPECT_EQ(bubble_ui_info.primary_button_command.value(),
-            DownloadCommands::Command::CANCEL);
-}
-
-TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo_V2On_Old) {
+TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo_Old) {
   // TODO(crbug.com/1465966): Clean up after the base::Feature is removed.
   base::test::ScopedFeatureList features;
   features.InitAndDisableFeature(
@@ -814,45 +764,35 @@
   SetupCompletedDownloadItem(base::Hours(1));
   const struct DangerTypeTestCase {
     download::DownloadDangerType danger_type;
-    bool has_checkbox;
     absl::optional<DownloadCommands::Command> primary_button_command;
     std::vector<DownloadCommands::Command> subpage_button_commands;
   } kDangerTypeTestCases[] = {
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
-       false,
        DownloadCommands::Command::KEEP,
        {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
       {download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DEEP_SCAN,
         DownloadCommands::Command::BYPASS_DEEP_SCANNING}},
       {download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD,
         DownloadCommands::Command::CANCEL_DEEP_SCAN}},
@@ -865,9 +805,7 @@
     SetupDownloadItemDefaults();
     ON_CALL(item(), GetDangerType())
         .WillByDefault(Return(test_case.danger_type));
-    DownloadUIModel::BubbleUIInfo bubble_ui_info =
-        model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
-    EXPECT_EQ(bubble_ui_info.HasCheckbox(), test_case.has_checkbox);
+    DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
     EXPECT_EQ(bubble_ui_info.primary_button_command,
               test_case.primary_button_command);
     std::vector<DownloadCommands::Command> subpage_commands;
@@ -878,53 +816,42 @@
   }
 }
 
-TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo_V2On) {
+TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo) {
   SetupCompletedDownloadItem(base::Hours(1));
   const struct DangerTypeTestCase {
     download::DownloadDangerType danger_type;
-    bool has_checkbox;
     absl::optional<DownloadCommands::Command> primary_button_command;
     std::vector<DownloadCommands::Command> subpage_button_commands;
   } kDangerTypeTestCases[] = {
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD}},
       {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING,
-       false,
        DownloadCommands::Command::DISCARD,
        {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
       {download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
       {download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DEEP_SCAN,
         DownloadCommands::Command::BYPASS_DEEP_SCANNING}},
       {download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING,
-       false,
        absl::nullopt,
        {DownloadCommands::Command::DISCARD,
         DownloadCommands::Command::CANCEL_DEEP_SCAN}},
@@ -937,9 +864,7 @@
     SetupDownloadItemDefaults();
     ON_CALL(item(), GetDangerType())
         .WillByDefault(Return(test_case.danger_type));
-    DownloadUIModel::BubbleUIInfo bubble_ui_info =
-        model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
-    EXPECT_EQ(bubble_ui_info.HasCheckbox(), test_case.has_checkbox);
+    DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
     EXPECT_EQ(bubble_ui_info.primary_button_command,
               test_case.primary_button_command);
     std::vector<DownloadCommands::Command> subpage_commands;
@@ -950,80 +875,7 @@
   }
 }
 
-TEST_F(DownloadItemModelTest, DangerousWarningBubbleUIInfo_V2Off_Old) {
-  // TODO(crbug.com/1465966): Clean up after the base::Feature is removed.
-  base::test::ScopedFeatureList features;
-  features.InitAndDisableFeature(
-      safe_browsing::kImprovedDownloadBubbleWarnings);
-  SetupCompletedDownloadItem(base::Hours(1));
-  SetIsBubbleV2Enabled(false);
-  const struct DangerTypeTestCase {
-    download::DownloadDangerType danger_type;
-    bool has_checkbox;
-    absl::optional<DownloadCommands::Command> primary_button_command;
-    std::vector<DownloadCommands::Command> subpage_button_commands;
-  } kDangerTypeTestCases[] = {
-      {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
-       false,
-       DownloadCommands::Command::KEEP,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
-       true,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST,
-       true,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE,
-       true,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED,
-       true,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL,
-       true,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING,
-       false,
-       DownloadCommands::Command::DISCARD,
-       {DownloadCommands::Command::DISCARD, DownloadCommands::Command::KEEP}},
-      {download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING,
-       false,
-       absl::nullopt,
-       {DownloadCommands::Command::DEEP_SCAN,
-        DownloadCommands::Command::BYPASS_DEEP_SCANNING}},
-      {download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING,
-       false,
-       absl::nullopt,
-       {DownloadCommands::Command::DISCARD,
-        DownloadCommands::Command::CANCEL_DEEP_SCAN}},
-  };
-  for (const auto& test_case : kDangerTypeTestCases) {
-    SCOPED_TRACE(testing::Message()
-                 << "Failed for danger type "
-                 << download::GetDownloadDangerTypeString(test_case.danger_type)
-                 << std::endl);
-    SetupDownloadItemDefaults();
-    ON_CALL(item(), GetDangerType())
-        .WillByDefault(Return(test_case.danger_type));
-    DownloadUIModel::BubbleUIInfo bubble_ui_info =
-        model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false);
-    EXPECT_EQ(bubble_ui_info.HasCheckbox(), test_case.has_checkbox);
-    EXPECT_EQ(bubble_ui_info.primary_button_command,
-              test_case.primary_button_command);
-    std::vector<DownloadCommands::Command> subpage_commands;
-    for (auto button : bubble_ui_info.subpage_buttons) {
-      subpage_commands.push_back(button.command);
-    }
-    EXPECT_EQ(subpage_commands, test_case.subpage_button_commands);
-  }
-}
-
-TEST_F(DownloadItemModelTest, InterruptedBubbleUIInfo_V2On) {
+TEST_F(DownloadItemModelTest, InterruptedBubbleUIInfo) {
   std::vector<download::DownloadInterruptReason> no_retry_interrupt_reasons = {
       download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE,
       download::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED,
@@ -1089,7 +941,6 @@
        DownloadCommands::Command::RESUME},
   };
 
-  SetIsBubbleV2Enabled(true);
   SetupDownloadItemDefaults();
   for (const auto& test_case : kTestCases) {
     for (const auto& interrupt_reason : test_case.interrupt_reasons) {
@@ -1097,60 +948,7 @@
       EXPECT_CALL(item(), CanResume())
           .WillRepeatedly(Return(test_case.can_resume));
 
-      DownloadUIModel::BubbleUIInfo bubble_ui_info =
-          model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
-      EXPECT_EQ(test_case.expected_warning_summary,
-                base::UTF16ToUTF8(bubble_ui_info.warning_summary));
-      EXPECT_EQ(test_case.expected_icon_model_override,
-                bubble_ui_info.icon_model_override);
-      EXPECT_EQ(test_case.expected_primary_button_command,
-                bubble_ui_info.primary_button_command);
-      EXPECT_EQ(kColorDownloadItemIconDangerous,
-                bubble_ui_info.secondary_color);
-      EXPECT_FALSE(bubble_ui_info.has_progress_bar);
-    }
-  }
-}
-
-TEST_F(DownloadItemModelTest, InterruptedBubbleUIInfo_V2Off) {
-  const struct TestCase {
-    std::vector<download::DownloadInterruptReason> interrupt_reasons;
-
-    std::string expected_warning_summary;
-    raw_ptr<const gfx::VectorIcon> expected_icon_model_override;
-    absl::optional<DownloadCommands::Command> expected_primary_button_command;
-  } kTestCases[] = {
-      {{
-           download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
-           download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
-           download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT,
-           download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED,
-           download::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN,
-           download::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR,
-           download::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN,
-           download::DOWNLOAD_INTERRUPT_REASON_CRASH,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT,
-           download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
-           download::DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM,
-           download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE,
-           download::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT,
-       },
-       "",
-       &vector_icons::kFileDownloadOffIcon,
-       absl::optional<DownloadCommands::Command>()},
-  };
-
-  SetIsBubbleV2Enabled(false);
-  SetupDownloadItemDefaults();
-  for (const auto& test_case : kTestCases) {
-    for (const auto& interrupt_reason : test_case.interrupt_reasons) {
-      SetupInterruptedDownloadItem(interrupt_reason);
-      DownloadUIModel::BubbleUIInfo bubble_ui_info =
-          model().GetBubbleUIInfo(/*is_download_bubble_v2=*/false);
+      DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
       EXPECT_EQ(test_case.expected_warning_summary,
                 base::UTF16ToUTF8(bubble_ui_info.warning_summary));
       EXPECT_EQ(test_case.expected_icon_model_override,
@@ -1190,7 +988,6 @@
       {canceled, not_dangerous, ten_mins_ago, true},
   };
 
-  SetIsBubbleV2Enabled(true);
   SetupDownloadItemDefaults();
   for (const auto& test_case : kTestCases) {
     EXPECT_CALL(item(), GetState()).WillRepeatedly(Return(test_case.state));
@@ -1257,7 +1054,7 @@
  public:
   DownloadItemModelImprovedDownloadBubbleWarningsTest() {
     scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2,
+        {safe_browsing::kDownloadBubble,
          safe_browsing::kImprovedDownloadBubbleWarnings},
         {});
   }
@@ -1266,7 +1063,6 @@
     DownloadItemModelTest::SetUp();
     SetupDownloadItemDefaults();
     SetupCompletedDownloadItem(base::Minutes(30));
-    SetIsBubbleV2Enabled(true);
     SetStatusTextBuilder(/*for_bubble=*/true);
   }
   ~DownloadItemModelImprovedDownloadBubbleWarningsTest() override = default;
@@ -1287,8 +1083,7 @@
     safe_browsing::DownloadProtectionService::SetDownloadProtectionData(
         &item(), "token", safe_browsing::ClientDownloadResponse::DANGEROUS,
         safe_browsing::ClientDownloadResponse::TailoredVerdict());
-    DownloadUIModel::BubbleUIInfo bubble_ui_info =
-        model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+    DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
 
     // Subpage warning
     EXPECT_TRUE(bubble_ui_info.HasSubpage());
@@ -1324,8 +1119,7 @@
     SetSafeBrowsingState(profile()->GetPrefs(), sb_state);
     EXPECT_CALL(item(), GetDangerType())
         .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE));
-    DownloadUIModel::BubbleUIInfo bubble_ui_info =
-        model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+    DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
 
     // Subpage warning
     EXPECT_TRUE(bubble_ui_info.HasSubpage());
@@ -1359,8 +1153,7 @@
                        safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING);
   EXPECT_CALL(item(), GetDangerType())
       .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE));
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
 
   // Subpage warning
   EXPECT_TRUE(bubble_ui_info.HasSubpage());
@@ -1395,8 +1188,7 @@
       prefs::kSafeBrowsingEnabled, std::make_unique<base::Value>(false));
   EXPECT_CALL(item(), GetDangerType())
       .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE));
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
 
   // Subpage warning
   EXPECT_TRUE(bubble_ui_info.HasSubpage());
@@ -1594,7 +1386,7 @@
   DownloadItemModelTailoredWarningTest() {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2,
+        {safe_browsing::kDownloadBubble,
          safe_browsing::kDownloadTailoredWarnings},
         {});
   }
@@ -1655,8 +1447,7 @@
       download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE,
       TailoredVerdict::COOKIE_THEFT, /*adjustments=*/{});
 
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
   // No primary button on download row view. Button only appears on subpage.
   EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
   EXPECT_EQ(1u, bubble_ui_info.subpage_buttons.size());
@@ -1674,8 +1465,7 @@
                               TailoredVerdict::SUSPICIOUS_ARCHIVE,
                               /*adjustments=*/{});
 
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
   // No primary button on download row view. Button only appears on subpage.
   EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
   EXPECT_EQ(2u, bubble_ui_info.subpage_buttons.size());
@@ -1700,8 +1490,7 @@
   signin::SetPrimaryAccount(identity_manager, "test@example.com",
                             signin::ConsentLevel::kSignin);
 
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
   // No primary button on download row view. Button only appears on subpage.
   EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
   EXPECT_EQ(1u, bubble_ui_info.subpage_buttons.size());
@@ -1721,8 +1510,7 @@
       download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE,
       TailoredVerdict::COOKIE_THEFT, {TailoredVerdict::ACCOUNT_INFO_STRING});
 
-  DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      model().GetBubbleUIInfo(/*is_download_bubble_v2=*/true);
+  DownloadUIModel::BubbleUIInfo bubble_ui_info = model().GetBubbleUIInfo();
   // No primary button on download row view. Button only appears on subpage.
   EXPECT_FALSE(bubble_ui_info.primary_button_command.has_value());
   EXPECT_EQ(1u, bubble_ui_info.subpage_buttons.size());
@@ -1739,7 +1527,7 @@
   DownloadItemModelTailoredWarningDisabledTest() {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2},
+        {safe_browsing::kDownloadBubble},
         {safe_browsing::kDownloadTailoredWarnings});
   }
 
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index d1aa90d..3487e86 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -702,11 +702,12 @@
   auto_open_allowed_by_urls_.swap(allowed_urls);
 }
 
+// TODO(chlily): Clean this up as this feature is no longer being pursued.
 bool DownloadPrefs::PromptForDuplicateFile() const {
 #if BUILDFLAG(IS_ANDROID)
   return false;
 #else
-  return download::IsDownloadBubbleV2Enabled(profile_) &&
+  return download::IsDownloadBubbleEnabled(profile_) &&
          prompt_for_duplicate_file_.GetValue();
 #endif
 }
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc
index 6ff24c6..f220419c 100644
--- a/chrome/browser/download/download_prefs_unittest.cc
+++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -707,6 +707,7 @@
 
 #else  // !is_android
 // Verifies the returned value of PromptForDuplicateFile().
+// TODO(chlily): Clean up this test/pref. We no longer plan to implement this.
 TEST(DownloadPrefsTest, PromptForDuplicateFile) {
   content::BrowserTaskEnvironment task_environment;
   TestingProfile profile;
@@ -717,32 +718,14 @@
                                  false);
   EXPECT_FALSE(prefs.PromptForDuplicateFile());
 
-  // BubbleV2 enabled and duplicate prompt enabled.
-  {
-    base::test::ScopedFeatureList feature_list;
-    feature_list.InitWithFeatures(
-        /*enabled_features=*/{safe_browsing::kDownloadBubble,
-                              safe_browsing::kDownloadBubbleV2},
-        /*disabled_features=*/{});
-    profile.GetPrefs()->SetBoolean(prefs::kDownloadDuplicateFilePromptEnabled,
-                                   true);
+  // Duplicate prompt enabled.
+  profile.GetPrefs()->SetBoolean(prefs::kDownloadDuplicateFilePromptEnabled,
+                                 true);
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-    EXPECT_FALSE(prefs.PromptForDuplicateFile());
+  EXPECT_FALSE(prefs.PromptForDuplicateFile());
 #else
-    EXPECT_TRUE(prefs.PromptForDuplicateFile());
+  EXPECT_TRUE(prefs.PromptForDuplicateFile());
 #endif
-  }
-
-  // BubbleV2 disabled and duplicate prompt enabled.
-  {
-    base::test::ScopedFeatureList feature_list;
-    feature_list.InitWithFeatures(
-        /*enabled_features=*/{safe_browsing::kDownloadBubble},
-        /*disabled_features=*/{safe_browsing::kDownloadBubbleV2});
-    profile.GetPrefs()->SetBoolean(prefs::kDownloadDuplicateFilePromptEnabled,
-                                   true);
-    EXPECT_FALSE(prefs.PromptForDuplicateFile());
-  }
 }
 #endif  // BUILDFLAG(IS_ANDROID)
 
diff --git a/chrome/browser/download/download_status_updater_lacros.cc b/chrome/browser/download/download_status_updater_lacros.cc
index 5f99fa89..08b1f7c 100644
--- a/chrome/browser/download/download_status_updater_lacros.cc
+++ b/chrome/browser/download/download_status_updater_lacros.cc
@@ -57,23 +57,7 @@
         command == DownloadCommands::PAUSE ||
         command == DownloadCommands::RESUME);
 
-  const bool is_download_bubble_v2_enabled =
-      download::IsDownloadBubbleV2Enabled(Profile::FromBrowserContext(
-          content::DownloadItemUtils::GetBrowserContext(
-              model.GetDownloadItem())));
-
-  // `BubbleUIInfo` contains at most one of either `CANCEL`, `PAUSE`, or
-  // `RESUME` when download bubble v2 is disabled, despite the fact that a
-  // download may be simultaneously cancellable and pausable/resumable. For
-  // this reason, do not use `BubbleUIInfo`-based determination of command
-  // enablement when download bubble v2 is disabled.
-  if (!is_download_bubble_v2_enabled) {
-    DownloadCommands commands(model.GetWeakPtr());
-    return model.IsCommandEnabled(&commands, command);
-  }
-
-  const DownloadUIModel::BubbleUIInfo info =
-      model.GetBubbleUIInfo(/*is_download_bubble_v2_enabled=*/true);
+  const DownloadUIModel::BubbleUIInfo info = model.GetBubbleUIInfo();
 
   // A command is enabled if `BubbleUIInfo` contains a quick action for it. This
   // is preferred over non-`BubbleUIInfo`-based determination of command
diff --git a/chrome/browser/download/download_ui_controller.cc b/chrome/browser/download/download_ui_controller.cc
index c3c424b..b3817ad 100644
--- a/chrome/browser/download/download_ui_controller.cc
+++ b/chrome/browser/download/download_ui_controller.cc
@@ -136,8 +136,7 @@
   // |profile| is required to outlive DownloadBubbleUIControllerDelegate.
   explicit DownloadBubbleUIControllerDelegate(Profile* profile)
       : profile_(profile) {
-    if (download::IsDownloadBubbleV2Enabled(profile_) &&
-        profile_->IsOffTheRecord()) {
+    if (profile_->IsOffTheRecord()) {
       profile_->GetPrefs()->SetBoolean(prefs::kPromptForDownload, true);
     }
   }
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc
index b5f2a02e..324f9991 100644
--- a/chrome/browser/download/download_ui_model.cc
+++ b/chrome/browser/download/download_ui_model.cc
@@ -809,12 +809,6 @@
   primary_button_command = command;
   return *this;
 }
-DownloadUIModel::BubbleUIInfo& DownloadUIModel::BubbleUIInfo::AddCheckbox(
-    const std::u16string& label) {
-  CHECK(!label.empty());  // An empty summary is interpreted as no checkbox
-  checkbox_label = label;
-  return *this;
-}
 DownloadUIModel::BubbleUIInfo&
 DownloadUIModel::BubbleUIInfo::AddPrimarySubpageButton(
     const std::u16string& label,
@@ -928,9 +922,6 @@
 bool DownloadUIModel::BubbleUIInfo::HasSubpage() const {
   return !warning_summary.empty();
 }
-bool DownloadUIModel::BubbleUIInfo::HasCheckbox() const {
-  return !checkbox_label.empty();
-}
 
 DownloadUIModel::BubbleUIInfo DownloadUIModel::GetBubbleUIInfoForInterrupted(
     FailState fail_state) const {
@@ -1076,22 +1067,18 @@
   }
 
   DownloadUIModel::BubbleUIInfo bubble_ui_info =
-      DownloadUIModel::BubbleUIInfo().AddIconAndColor(
-          features::IsChromeRefresh2023()
-              ? vector_icons::kFileDownloadOffChromeRefreshIcon
-              : vector_icons::kFileDownloadOffIcon,
-          kColorDownloadItemIconDangerous);
-  if (IsBubbleV2Enabled()) {
-    bubble_ui_info.AddPrimaryButton(CanResume()
-                                        ? DownloadCommands::Command::RESUME
+      DownloadUIModel::BubbleUIInfo()
+          .AddIconAndColor(features::IsChromeRefresh2023()
+                               ? vector_icons::kFileDownloadOffChromeRefreshIcon
+                               : vector_icons::kFileDownloadOffIcon,
+                           kColorDownloadItemIconDangerous)
+          .AddPrimaryButton(CanResume() ? DownloadCommands::Command::RESUME
                                         : DownloadCommands::Command::RETRY);
-  }
   return bubble_ui_info;
 }
 
 DownloadUIModel::BubbleUIInfo
-DownloadUIModel::GetBubbleUIInfoForInProgressOrComplete(
-    bool is_download_bubble_v2) const {
+DownloadUIModel::GetBubbleUIInfoForInProgressOrComplete() const {
   switch (GetInsecureDownloadStatus()) {
     case download::DownloadItem::InsecureDownloadStatus::BLOCK:
     case download::DownloadItem::InsecureDownloadStatus::WARN:
@@ -1223,15 +1210,6 @@
             .AddPrimarySubpageButton(
                 l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE),
                 DownloadCommands::Command::DISCARD);
-        if (!is_download_bubble_v2) {
-          ui_info
-              .AddCheckbox(l10n_util::GetStringUTF16(
-                  IDS_DOWNLOAD_BUBBLE_CHECKBOX_BYPASS))
-              .AddSecondarySubpageButton(
-                  l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE),
-                  DownloadCommands::Command::KEEP,
-                  kColorDownloadItemTextDangerous);
-        }
         return ui_info;
       }
 
@@ -1255,15 +1233,6 @@
                 .AddPrimarySubpageButton(
                     l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE),
                     DownloadCommands::Command::DISCARD);
-        if (!is_download_bubble_v2) {
-          ui_info
-              .AddCheckbox(l10n_util::GetStringUTF16(
-                  IDS_DOWNLOAD_BUBBLE_CHECKBOX_BYPASS))
-              .AddSecondarySubpageButton(
-                  l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE),
-                  DownloadCommands::Command::KEEP,
-                  kColorDownloadItemTextWarning);
-        }
         return ui_info;
       }
 
@@ -1290,15 +1259,6 @@
                 .AddPrimarySubpageButton(
                     l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DELETE),
                     DownloadCommands::Command::DISCARD);
-        if (!is_download_bubble_v2) {
-          ui_info
-              .AddCheckbox(l10n_util::GetStringUTF16(
-                  IDS_DOWNLOAD_BUBBLE_CHECKBOX_BYPASS))
-              .AddSecondarySubpageButton(
-                  l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CONTINUE),
-                  DownloadCommands::Command::KEEP,
-                  kColorDownloadItemTextDangerous);
-        }
         return ui_info;
       }
     case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: {
@@ -1506,56 +1466,46 @@
   if (has_progress_bar) {
     bubble_ui_info.AddProgressBar();
     if (IsPaused()) {
-      if (is_download_bubble_v2) {
-        bubble_ui_info.AddQuickAction(
-            DownloadCommands::Command::RESUME,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kPlayArrowChromeRefreshIcon
-                : &vector_icons::kPlayArrowIcon);
-        bubble_ui_info.AddQuickAction(
-            DownloadCommands::Command::CANCEL,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kCancelChromeRefreshIcon
-                : &vector_icons::kCancelIcon);
-      } else {
-        bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::RESUME);
-      }
+      bubble_ui_info.AddQuickAction(
+          DownloadCommands::Command::RESUME,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kPlayArrowChromeRefreshIcon
+              : &vector_icons::kPlayArrowIcon);
+      bubble_ui_info.AddQuickAction(
+          DownloadCommands::Command::CANCEL,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kCancelChromeRefreshIcon
+              : &vector_icons::kCancelIcon);
     } else {
-      if (is_download_bubble_v2) {
-        bubble_ui_info.AddQuickAction(
-            DownloadCommands::Command::PAUSE,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kPauseChromeRefreshIcon
-                : &vector_icons::kPauseIcon);
-        bubble_ui_info.AddQuickAction(
-            DownloadCommands::Command::CANCEL,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kCancelChromeRefreshIcon
-                : &vector_icons::kCancelIcon);
-      } else {
-        bubble_ui_info.AddPrimaryButton(DownloadCommands::Command::CANCEL);
-      }
+      bubble_ui_info.AddQuickAction(
+          DownloadCommands::Command::PAUSE,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kPauseChromeRefreshIcon
+              : &vector_icons::kPauseIcon);
+      bubble_ui_info.AddQuickAction(
+          DownloadCommands::Command::CANCEL,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kCancelChromeRefreshIcon
+              : &vector_icons::kCancelIcon);
     }
   } else {
-    if (is_download_bubble_v2) {
-      bubble_ui_info.AddQuickAction(
-          DownloadCommands::Command::SHOW_IN_FOLDER,
-          l10n_util::GetStringUTF16(
-              IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION),
-          features::IsChromeRefresh2023()
-              ? &vector_icons::kFolderChromeRefreshIcon
-              : &vector_icons::kFolderIcon);
-      bubble_ui_info.AddQuickAction(
-          DownloadCommands::Command::OPEN_WHEN_COMPLETE,
-          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION),
-          features::IsChromeRefresh2023()
-              ? &vector_icons::kLaunchChromeRefreshIcon
-              : &kOpenInNewIcon);
-    }
+    bubble_ui_info.AddQuickAction(
+        DownloadCommands::Command::SHOW_IN_FOLDER,
+        l10n_util::GetStringUTF16(
+            IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION),
+        features::IsChromeRefresh2023()
+            ? &vector_icons::kFolderChromeRefreshIcon
+            : &vector_icons::kFolderIcon);
+    bubble_ui_info.AddQuickAction(
+        DownloadCommands::Command::OPEN_WHEN_COMPLETE,
+        l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION),
+        features::IsChromeRefresh2023()
+            ? &vector_icons::kLaunchChromeRefreshIcon
+            : &kOpenInNewIcon);
   }
   return bubble_ui_info;
 }
@@ -1584,12 +1534,11 @@
   return ui_info;
 }
 
-DownloadUIModel::BubbleUIInfo DownloadUIModel::GetBubbleUIInfo(
-    bool is_download_bubble_v2) const {
+DownloadUIModel::BubbleUIInfo DownloadUIModel::GetBubbleUIInfo() const {
   switch (GetState()) {
     case DownloadItem::IN_PROGRESS:
     case DownloadItem::COMPLETE:
-      return GetBubbleUIInfoForInProgressOrComplete(is_download_bubble_v2);
+      return GetBubbleUIInfoForInProgressOrComplete();
     case DownloadItem::INTERRUPTED: {
       const FailState fail_state = GetLastFailState();
       if (fail_state != FailState::USER_CANCELED) {
@@ -2053,19 +2002,6 @@
   status_text_builder_->SetModel(this);
 }
 
-#if !BUILDFLAG(IS_ANDROID)
-void DownloadUIModel::set_is_bubble_v2_enabled_for_testing(bool is_enabled) {
-  is_bubble_V2_enabled_for_testing_ = is_enabled;
-}
-
-bool DownloadUIModel::IsBubbleV2Enabled() const {
-  if (is_bubble_V2_enabled_for_testing_.has_value()) {
-    return is_bubble_V2_enabled_for_testing_.value();
-  }
-  return download::IsDownloadBubbleV2Enabled(profile());
-}
-#endif
-
 std::u16string DownloadUIModel::GetInterruptDescription() const {
   const auto fail_state = GetLastFailState();
   std::u16string state_description = FailStateDescription(fail_state);
diff --git a/chrome/browser/download/download_ui_model.h b/chrome/browser/download/download_ui_model.h
index 7071449..9b3d21b 100644
--- a/chrome/browser/download/download_ui_model.h
+++ b/chrome/browser/download/download_ui_model.h
@@ -177,9 +177,6 @@
     // Icon for the secondary text in the subpage
     raw_ptr<const gfx::VectorIcon> warning_secondary_icon = nullptr;
 
-    // Label for the checkbox, empty if no checkbox is needed
-    std::u16string checkbox_label;
-
     // The command for the primary button
     absl::optional<DownloadCommands::Command> primary_button_command;
 
@@ -211,10 +208,8 @@
                                   ui::ColorId color_id);
     BubbleUIInfo& AddSecondaryTextColor(ui::ColorId color_id);
     BubbleUIInfo& AddPrimaryButton(DownloadCommands::Command command);
-    BubbleUIInfo& AddCheckbox(const std::u16string& label);
     // Add button to the subpage. Only two buttons are supported.
     // The first one added is the primary, and the second one the secondary.
-    // The checkbox, if present, controls the secondary.
     BubbleUIInfo& AddPrimarySubpageButton(const std::u16string& label,
                                           DownloadCommands::Command command);
     BubbleUIInfo& AddSecondarySubpageButton(
@@ -247,7 +242,6 @@
 
     ui::ColorId GetColorForSecondaryText() const;
     bool HasSubpage() const;
-    bool HasCheckbox() const;
   };
 #endif
 
@@ -575,15 +569,16 @@
                               DownloadCommands::Command command);
 
   // Gets the information about the download bubbles subpage.
-  BubbleUIInfo GetBubbleUIInfo(bool is_download_bubble_v2) const;
+  BubbleUIInfo GetBubbleUIInfo() const;
   BubbleUIInfo GetBubbleUIInfoForInterrupted(
       offline_items_collection::FailState fail_state) const;
-  BubbleUIInfo GetBubbleUIInfoForInProgressOrComplete(
-      bool is_download_bubble_v2) const;
+  BubbleUIInfo GetBubbleUIInfoForInProgressOrComplete() const;
   virtual BubbleUIInfo GetBubbleUIInfoForTailoredWarning() const;
   BubbleUIInfo GetBubbleUIInfoForFileTypeWarningNoSafeBrowsing() const;
 
   // Returns |true| if this download should be displayed in the download bubble.
+  // Note that this may return true even if the download bubble is not enabled
+  // on the platform.
   virtual bool ShouldShowInBubble() const;
 
   // Should this download trigger a tailored warning?
@@ -632,11 +627,6 @@
 
   raw_ptr<Delegate> delegate_ = nullptr;
 
-#if !BUILDFLAG(IS_ANDROID)
-  // Returns whether the DownloadBubbleV2 functionality is enabled.
-  bool IsBubbleV2Enabled() const;
-#endif
-
  private:
   friend class DownloadItemModelTest;
 
@@ -644,20 +634,9 @@
 
   void set_status_text_builder_for_testing(bool for_bubble);
 
-#if !BUILDFLAG(IS_ANDROID)
-  // The following two methods exist for simpler unit testing.
-  // Setting an override for whether the DownloadBubbleV2 functionality is
-  // enabled.
-  void set_is_bubble_v2_enabled_for_testing(bool is_enabled);
-#endif
-
   // Unowned Clock to override the time of "Now".
   raw_ptr<base::Clock> clock_ = base::DefaultClock::GetInstance();
 
-#if !BUILDFLAG(IS_ANDROID)
-  absl::optional<bool> is_bubble_V2_enabled_for_testing_;
-#endif
-
   std::unique_ptr<StatusTextBuilderBase> status_text_builder_;
 
   base::WeakPtrFactory<DownloadUIModel> weak_ptr_factory_{this};
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc
index b405627..07b1e46 100644
--- a/chrome/browser/download/notification/download_notification_browsertest.cc
+++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -295,8 +295,7 @@
 class DownloadNotificationTestBase : public InProcessBrowserTest {
  public:
   DownloadNotificationTestBase() {
-    scoped_feature_list_.InitWithFeatures(
-        {}, {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2});
+    scoped_feature_list_.InitAndDisableFeature(safe_browsing::kDownloadBubble);
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
index a05fb9e..425469a 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
@@ -727,8 +727,8 @@
   icon->SetLayoutManager(std::make_unique<views::FillLayout>());
 
   auto side_image = std::make_unique<DeepScanningSideIconImageView>(this);
-  side_image->SetImage(gfx::CreateVectorIcon(
-      gfx::IconDescription(vector_icons::kBusinessIcon, kSideImageSize)));
+  side_image->SetImage(ui::ImageModel::FromVectorIcon(
+      vector_icons::kBusinessIcon, gfx::kPlaceholderColor, kSideImageSize));
   side_image->SetBorder(views::CreateEmptyBorder(kSideImageInsets));
   side_icon_image_ = icon->AddChildView(std::move(side_image));
 
@@ -983,9 +983,8 @@
       contents_view_->GetColorProvider()->GetColor(ui::kColorDialogBackground));
 }
 
-const gfx::ImageSkia* ContentAnalysisDialog::GetTopImage() const {
-  return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-      GetTopImageId(ShouldUseDarkTopImage()));
+ui::ImageModel ContentAnalysisDialog::GetTopImage() const {
+  return ui::ImageModel::FromResourceId(GetTopImageId(ShouldUseDarkTopImage()));
 }
 
 bool ContentAnalysisDialog::is_print_scan() const {
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h
index f5e1ec54..e356f91 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.h
@@ -24,10 +24,6 @@
 class WebContents;
 }  // namespace content
 
-namespace gfx {
-class ImageSkia;
-}  // namespace gfx
-
 namespace views {
 class BoxLayoutView;
 class ImageView;
@@ -166,7 +162,7 @@
   bool ShouldUseDarkTopImage() const;
 
   // Returns the appropriate top image depending on `dialog_state_`.
-  const gfx::ImageSkia* GetTopImage() const;
+  ui::ImageModel GetTopImage() const;
 
   // Accessors used to validate the views in tests.
   views::ImageView* GetTopImageForTesting() const;
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc
index 43052a2c..845708fc 100644
--- a/chrome/browser/metrics/chrome_feature_list_creator.cc
+++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -94,9 +94,6 @@
        std::cref(safe_browsing::kDownloadBubble),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE},
       {switches::kEnableDownloadWarningImprovements,
-       std::cref(safe_browsing::kDownloadBubbleV2),
-       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
-      {switches::kEnableDownloadWarningImprovements,
        std::cref(safe_browsing::kDownloadTailoredWarnings),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE},
       {switches::kEnableDownloadWarningImprovements,
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
index 99f8f74..a485a08 100644
--- a/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -15,6 +15,7 @@
     ":multidevice_setup_resources",
     "accessibility:build",
     "add_supervision:resources",
+    "app_install:resources",
     "arc_account_picker:resources",
     "assistant_optin:resources",
     "audio:resources",
@@ -45,7 +46,6 @@
     "sensor_info:resources",
     "supervision:resources",
     "vc_tray_tester:resources",
-    "web_app_install:resources",
   ]
 }
 
diff --git a/chrome/browser/resources/chromeos/web_app_install/BUILD.gn b/chrome/browser/resources/chromeos/app_install/BUILD.gn
similarity index 68%
rename from chrome/browser/resources/chromeos/web_app_install/BUILD.gn
rename to chrome/browser/resources/chromeos/app_install/BUILD.gn
index 1907e378..200af12 100644
--- a/chrome/browser/resources/chromeos/web_app_install/BUILD.gn
+++ b/chrome/browser/resources/chromeos/app_install/BUILD.gn
@@ -5,14 +5,14 @@
 import("//ui/webui/resources/tools/build_webui.gni")
 
 build_webui("build") {
-  grd_prefix = "web_app_install"
+  grd_prefix = "app_install"
 
   static_files = [ "main.html" ]
-  web_component_files = [ "web_app_install_dialog.ts" ]
+  web_component_files = [ "app_install_dialog.ts" ]
   non_web_component_files = [ "browser_proxy.ts" ]
-  mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom-webui.ts" ]
+  mojo_files = [ "$root_gen_dir/chrome/browser/ui/webui/ash/app_install/app_install.mojom-webui.ts" ]
   mojo_files_deps = [
-    "//chrome/browser/ui/webui/ash/web_app_install:mojo_bindings_ts__generator",
+    "//chrome/browser/ui/webui/ash/app_install:mojo_bindings_ts__generator",
   ]
 
   html_to_wrapper_template = "native"
diff --git a/chrome/browser/resources/chromeos/web_app_install/OWNERS b/chrome/browser/resources/chromeos/app_install/OWNERS
similarity index 100%
rename from chrome/browser/resources/chromeos/web_app_install/OWNERS
rename to chrome/browser/resources/chromeos/app_install/OWNERS
diff --git a/chrome/browser/resources/chromeos/web_app_install/web_app_install_dialog.html b/chrome/browser/resources/chromeos/app_install/app_install_dialog.html
similarity index 100%
rename from chrome/browser/resources/chromeos/web_app_install/web_app_install_dialog.html
rename to chrome/browser/resources/chromeos/app_install/app_install_dialog.html
diff --git a/chrome/browser/resources/chromeos/web_app_install/web_app_install_dialog.ts b/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts
similarity index 88%
rename from chrome/browser/resources/chromeos/web_app_install/web_app_install_dialog.ts
rename to chrome/browser/resources/chromeos/app_install/app_install_dialog.ts
index ad365d6..3a1e14e 100644
--- a/chrome/browser/resources/chromeos/web_app_install/web_app_install_dialog.ts
+++ b/chrome/browser/resources/chromeos/app_install/app_install_dialog.ts
@@ -10,17 +10,16 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
 import {BrowserProxy} from './browser_proxy.js';
-import {getTemplate} from './web_app_install_dialog.html.js';
+import {getTemplate} from './app_install_dialog.html.js';
 
 /**
  * @fileoverview
- * 'web-app-install-dialog' defines the UI for the ChromeOS web app install
- * dialog.
+ * 'app-install-dialog' defines the UI for the ChromeOS app install dialog.
  */
 
-class WebAppInstallDialogElement extends HTMLElement {
+class AppInstallDialogElement extends HTMLElement {
   static get is() {
-    return 'web-app-install-dialog';
+    return 'app-install-dialog';
   }
 
   static get template() {
@@ -32,7 +31,7 @@
   constructor() {
     super();
     const template = document.createElement('template');
-    template.innerHTML = WebAppInstallDialogElement.template as string;
+    template.innerHTML = AppInstallDialogElement.template as string;
     const fragment = template.content.cloneNode(true);
     this.attachShadow({mode: 'open'}).appendChild(fragment);
 
@@ -100,5 +99,4 @@
   }
 }
 
-customElements.define(
-    WebAppInstallDialogElement.is, WebAppInstallDialogElement);
+customElements.define(AppInstallDialogElement.is, AppInstallDialogElement);
diff --git a/chrome/browser/resources/chromeos/web_app_install/browser_proxy.ts b/chrome/browser/resources/chromeos/app_install/browser_proxy.ts
similarity index 85%
rename from chrome/browser/resources/chromeos/web_app_install/browser_proxy.ts
rename to chrome/browser/resources/chromeos/app_install/browser_proxy.ts
index 9636356..d9eb690 100644
--- a/chrome/browser/resources/chromeos/web_app_install/browser_proxy.ts
+++ b/chrome/browser/resources/chromeos/app_install/browser_proxy.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {PageHandlerFactory, PageHandlerRemote} from './web_app_install.mojom-webui.js';
+import {PageHandlerFactory, PageHandlerRemote} from './app_install.mojom-webui.js';
 
 export class BrowserProxy {
   handler: PageHandlerRemote = new PageHandlerRemote();
diff --git a/chrome/browser/resources/chromeos/web_app_install/main.html b/chrome/browser/resources/chromeos/app_install/main.html
similarity index 77%
rename from chrome/browser/resources/chromeos/web_app_install/main.html
rename to chrome/browser/resources/chromeos/app_install/main.html
index c07d1f0..18325273 100644
--- a/chrome/browser/resources/chromeos/web_app_install/main.html
+++ b/chrome/browser/resources/chromeos/app_install/main.html
@@ -10,9 +10,9 @@
         background-color: var(--cros-bg-color-elevation-3);
       }
     </style>
-    <script type="module" src="web_app_install_dialog.js"></script>
+    <script type="module" src="app_install_dialog.js"></script>
   </head>
   <body>
-    <web-app-install-dialog></web-app-install-dialog>
+    <app-install-dialog></app-install-dialog>
   </body>
 </html>
\ No newline at end of file
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
index 7b09c9c..713decd 100644
--- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -269,7 +269,8 @@
         {syncer::kEnablePreferencesAccountStorage,
          syncer::kSyncEnableContactInfoDataTypeInTransportMode,
          syncer::kSyncEnableContactInfoDataTypeForCustomPassphraseUsers,
-         syncer::kReplaceSyncPromosWithSignInPromos},
+         syncer::kReplaceSyncPromosWithSignInPromos,
+         syncer::kSyncAutofillWalletCredentialData},
         /*disabled_features=*/{});
   }
   ~SingleClientStandaloneTransportWithReplaceSyncWithSigninSyncTest() override =
@@ -326,6 +327,8 @@
       syncer::AUTOFILL_WALLET_DATA));
   EXPECT_TRUE(
       GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO));
+  EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
+      syncer::AUTOFILL_WALLET_CREDENTIAL));
 }
 
 // TODO(crbug.com/1117345): Android currently doesn't support PRE_ tests.
@@ -382,11 +385,14 @@
       GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO));
   if (!base::FeatureList::IsEnabled(
           syncer::kSyncDecoupleAddressPaymentSettings)) {
-    // AUTOFILL_WALLET_DATA should be disabled when CONTACT_INFO is disabled.
+    // AUTOFILL_WALLET_DATA and AUTOFILL_WALLET_CREDENTIAL should be disabled
+    // when CONTACT_INFO is disabled.
     // TODO(crbug.com/1435431): It shouldn't be disabled once kPayments is
     // decoupled from kAutofill.
     EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(
         syncer::AUTOFILL_WALLET_DATA));
+    EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(
+        syncer::AUTOFILL_WALLET_CREDENTIAL));
   }
 
   // Enabling kAutofill to enable CONTACT_INFO.
@@ -404,11 +410,14 @@
             GetSyncService(0)->GetTransportState());
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
 
-  // CONTACT_INFO and AUTOFILL_WALLET_DATA should be enabled.
+  // CONTACT_INFO, AUTOFILL_WALLET_DATA, and AUTOFILL_WALLET_CREDENTIAL should
+  // be enabled.
   EXPECT_TRUE(
       GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO));
   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
       syncer::AUTOFILL_WALLET_DATA));
+  EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
+      syncer::AUTOFILL_WALLET_CREDENTIAL));
 }
 
 // Tests that a custom passphrase user's opt-in to kAutofill (which happened in
@@ -423,13 +432,16 @@
   ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
             GetSyncService(0)->GetTransportState());
 
-  // CONTACT_INFO and AUTOFILL_WALLET_DATA should be enabled after restarting.
+  // CONTACT_INFO, AUTOFILL_WALLET_DATA, and AUTOFILL_WALLET_CREDENTIAL should
+  // be enabled after restarting.
   EXPECT_TRUE(
       GetSyncService(0)->GetActiveDataTypes().Has(syncer::CONTACT_INFO));
   // TODO(crbug.com/1435431): This should be removed once kPayments is decoupled
   // from kAutofill.
   EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
       syncer::AUTOFILL_WALLET_DATA));
+  EXPECT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(
+      syncer::AUTOFILL_WALLET_CREDENTIAL));
 }
 #endif  // BUILDFLAG(IS_ANDROID)
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 53508b5..7f0eee4 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2926,6 +2926,12 @@
       "webui/ash/add_supervision/add_supervision_ui.h",
       "webui/ash/add_supervision/confirm_signout_dialog.cc",
       "webui/ash/add_supervision/confirm_signout_dialog.h",
+      "webui/ash/app_install/app_install_dialog.cc",
+      "webui/ash/app_install/app_install_dialog.h",
+      "webui/ash/app_install/app_install_page_handler.cc",
+      "webui/ash/app_install/app_install_page_handler.h",
+      "webui/ash/app_install/app_install_ui.cc",
+      "webui/ash/app_install/app_install_ui.h",
       "webui/ash/arc_graphics_tracing/arc_graphics_tracing_handler.cc",
       "webui/ash/arc_graphics_tracing/arc_graphics_tracing_handler.h",
       "webui/ash/arc_graphics_tracing/arc_graphics_tracing_ui.cc",
@@ -3509,12 +3515,6 @@
       "webui/ash/vc_tray_tester/vc_tray_tester_ui.h",
       "webui/ash/vm/vm_ui.cc",
       "webui/ash/vm/vm_ui.h",
-      "webui/ash/web_app_install/web_app_install_dialog.cc",
-      "webui/ash/web_app_install/web_app_install_dialog.h",
-      "webui/ash/web_app_install/web_app_install_page_handler.cc",
-      "webui/ash/web_app_install/web_app_install_page_handler.h",
-      "webui/ash/web_app_install/web_app_install_ui.cc",
-      "webui/ash/web_app_install/web_app_install_ui.h",
       "webui/chromeos/chrome_url_disabled/chrome_url_disabled_ui.cc",
       "webui/chromeos/chrome_url_disabled/chrome_url_disabled_ui.h",
       "webui/extensions/ash/kiosk_apps_handler.cc",
@@ -3660,6 +3660,7 @@
       "//chrome/browser/scalable_iph:scalable_iph_factory",
       "//chrome/browser/ui/quick_answers",
       "//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings",
+      "//chrome/browser/ui/webui/ash/app_install:mojo_bindings",
       "//chrome/browser/ui/webui/ash/audio:mojo_bindings",
       "//chrome/browser/ui/webui/ash/borealis_installer:mojo_bindings",
       "//chrome/browser/ui/webui/ash/cloud_upload:mojo_bindings",
@@ -3678,7 +3679,6 @@
       "//chrome/browser/ui/webui/ash/settings/pages/privacy/mojom",
       "//chrome/browser/ui/webui/ash/settings/search/mojom",
       "//chrome/browser/ui/webui/ash/vm:mojo_bindings",
-      "//chrome/browser/ui/webui/ash/web_app_install:mojo_bindings",
       "//chrome/browser/ui/webui/nearby_share:mojom",
       "//chrome/browser/web_applications",
       "//chrome/browser/webshare:storage",
@@ -6523,7 +6523,7 @@
       deps += [
         "//chrome/browser/ash/system_web_apps/types",
         "//chrome/browser/ui/ash/system_web_apps",
-        "//chrome/browser/ui/webui/ash/web_app_install:mojo_bindings",
+        "//chrome/browser/ui/webui/ash/app_install:mojo_bindings",
       ]
       allow_circular_includes_from +=
           [ "//chrome/browser/ui/ash/system_web_apps" ]
diff --git a/chrome/browser/ui/download/download_bubble_row_view_info.cc b/chrome/browser/ui/download/download_bubble_row_view_info.cc
index eb89759..d5b698a 100644
--- a/chrome/browser/ui/download/download_bubble_row_view_info.cc
+++ b/chrome/browser/ui/download/download_bubble_row_view_info.cc
@@ -333,56 +333,46 @@
   if (has_progress_bar) {
     has_progress_bar_ = true;
     if (model_->IsPaused()) {
-      if (download::IsDownloadBubbleV2Enabled(model_->profile())) {
-        quick_actions_.emplace_back(
-            DownloadCommands::Command::RESUME,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kPlayArrowChromeRefreshIcon
-                : &vector_icons::kPlayArrowIcon);
-        quick_actions_.emplace_back(
-            DownloadCommands::Command::CANCEL,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kCancelChromeRefreshIcon
-                : &vector_icons::kCancelIcon);
-      } else {
-        primary_button_command_ = DownloadCommands::Command::RESUME;
-      }
+      quick_actions_.emplace_back(
+          DownloadCommands::Command::RESUME,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_RESUME_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kPlayArrowChromeRefreshIcon
+              : &vector_icons::kPlayArrowIcon);
+      quick_actions_.emplace_back(
+          DownloadCommands::Command::CANCEL,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kCancelChromeRefreshIcon
+              : &vector_icons::kCancelIcon);
     } else {
-      if (download::IsDownloadBubbleV2Enabled(model_->profile())) {
-        quick_actions_.emplace_back(
-            DownloadCommands::Command::PAUSE,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kPauseChromeRefreshIcon
-                : &vector_icons::kPauseIcon);
-        quick_actions_.emplace_back(
-            DownloadCommands::Command::CANCEL,
-            l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
-            features::IsChromeRefresh2023()
-                ? &vector_icons::kCancelChromeRefreshIcon
-                : &vector_icons::kCancelIcon);
-      } else {
-        primary_button_command_ = DownloadCommands::Command::CANCEL;
-      }
+      quick_actions_.emplace_back(
+          DownloadCommands::Command::PAUSE,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_PAUSE_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kPauseChromeRefreshIcon
+              : &vector_icons::kPauseIcon);
+      quick_actions_.emplace_back(
+          DownloadCommands::Command::CANCEL,
+          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_CANCEL_QUICK_ACTION),
+          features::IsChromeRefresh2023()
+              ? &vector_icons::kCancelChromeRefreshIcon
+              : &vector_icons::kCancelIcon);
     }
   } else {
-    if (download::IsDownloadBubbleV2Enabled(model_->profile())) {
-      quick_actions_.emplace_back(
-          DownloadCommands::Command::SHOW_IN_FOLDER,
-          l10n_util::GetStringUTF16(
-              IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION),
-          features::IsChromeRefresh2023()
-              ? &vector_icons::kFolderChromeRefreshIcon
-              : &vector_icons::kFolderIcon);
-      quick_actions_.emplace_back(
-          DownloadCommands::Command::OPEN_WHEN_COMPLETE,
-          l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION),
-          features::IsChromeRefresh2023()
-              ? &vector_icons::kLaunchChromeRefreshIcon
-              : &kOpenInNewIcon);
-    }
+    quick_actions_.emplace_back(
+        DownloadCommands::Command::SHOW_IN_FOLDER,
+        l10n_util::GetStringUTF16(
+            IDS_DOWNLOAD_BUBBLE_SHOW_IN_FOLDER_QUICK_ACTION),
+        features::IsChromeRefresh2023()
+            ? &vector_icons::kFolderChromeRefreshIcon
+            : &vector_icons::kFolderIcon);
+    quick_actions_.emplace_back(
+        DownloadCommands::Command::OPEN_WHEN_COMPLETE,
+        l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_OPEN_QUICK_ACTION),
+        features::IsChromeRefresh2023()
+            ? &vector_icons::kLaunchChromeRefreshIcon
+            : &kOpenInNewIcon);
   }
 }
 
@@ -518,11 +508,9 @@
                        ? &vector_icons::kFileDownloadOffChromeRefreshIcon
                        : &vector_icons::kFileDownloadOffIcon;
   secondary_color_ = kColorDownloadItemIconDangerous;
-  if (download::IsDownloadBubbleV2Enabled(model_->profile())) {
-    primary_button_command_ = model_->CanResume()
-                                  ? DownloadCommands::Command::RESUME
-                                  : DownloadCommands::Command::RETRY;
-  }
+  primary_button_command_ = model_->CanResume()
+                                ? DownloadCommands::Command::RESUME
+                                : DownloadCommands::Command::RETRY;
 }
 
 void DownloadBubbleRowViewInfo::PopulateForCancelled() {
diff --git a/chrome/browser/ui/download/download_bubble_row_view_info_unittest.cc b/chrome/browser/ui/download/download_bubble_row_view_info_unittest.cc
index 72dcb99..6e0a5bee 100644
--- a/chrome/browser/ui/download/download_bubble_row_view_info_unittest.cc
+++ b/chrome/browser/ui/download/download_bubble_row_view_info_unittest.cc
@@ -47,8 +47,7 @@
                                       public DownloadBubbleRowViewInfoObserver {
  public:
   DownloadBubbleRowViewInfoTest() {
-    scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+    scoped_feature_list_.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   }
 
   void SetUp() override {
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc
index 93844e28..39d019d2 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_contents_view.cc
@@ -63,8 +63,7 @@
 
   primary_view_ = AddChildView(std::move(primary_view));
   security_view_ = AddChildView(std::make_unique<DownloadBubbleSecurityView>(
-      /*delegate=*/this, navigation_handler, bubble_delegate,
-      download::IsDownloadBubbleV2Enabled(browser->profile())));
+      /*delegate=*/this, navigation_handler, bubble_delegate));
 
   // Starts on the primary page.
   ShowPrimaryPage();
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc
index 54d9ec5..5168bff 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_interactive_uitest.cc
@@ -62,12 +62,11 @@
  public:
   DownloadBubbleInteractiveUiTest() {
     test_features_.InitAndEnableFeatures(
-        {
-          feature_engagement::kIPHDownloadToolbarButtonFeature,
-              safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2
+        {feature_engagement::kIPHDownloadToolbarButtonFeature,
+         safe_browsing::kDownloadBubble
 #if BUILDFLAG(IS_MAC)
-              ,
-              features::kImmersiveFullscreen
+         ,
+         features::kImmersiveFullscreen
 #endif  // BUILDFLAG(IS_MAC)
         },
         {});
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_primary_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_primary_view.cc
index 5fd69cb..fea34a2b 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_primary_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_primary_view.cc
@@ -37,12 +37,10 @@
 constexpr int kMaxHeightForRowList = 450;
 
 bool IsOtrInfoRowEnabled(Browser* browser) {
-  if (!browser) {
+  if (!browser || !browser->profile()) {
     return false;
   }
-  Profile* profile = browser->profile();
-  return download::IsDownloadBubbleV2Enabled(profile) &&
-         profile->IsOffTheRecord();
+  return browser->profile()->IsOffTheRecord();
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_list_view_unittest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_list_view_unittest.cc
index 816d88c..7843b78 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_list_view_unittest.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_list_view_unittest.cc
@@ -33,8 +33,7 @@
 class DownloadBubbleRowListViewTest : public TestWithBrowserView {
  public:
   DownloadBubbleRowListViewTest() {
-    scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+    scoped_feature_list_.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   }
   ~DownloadBubbleRowListViewTest() override = default;
 
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index a3d96be1..4e86322 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -276,8 +276,8 @@
   }
 
   // For downloads in incognito mode.
-  if (bubble_controller_ &&
-      bubble_controller_->ShouldShowIncognitoIcon(info_->model())) {
+  if (info_->model()->profile() &&
+      info_->model()->profile()->IsIncognitoProfile()) {
     if (last_overridden_icon_ == &kIncognitoIcon) {
       return;
     }
@@ -289,8 +289,8 @@
   }
 
   // For downloads in guest sessions.
-  if (bubble_controller_ &&
-      bubble_controller_->ShouldShowGuestIcon(info_->model())) {
+  if (info_->model()->profile() &&
+      info_->model()->profile()->IsGuestSession()) {
     if (last_overridden_icon_ == &kUserAccountAvatarIcon) {
       return;
     }
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view_unittest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view_unittest.cc
index 3996782..804287d 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view_unittest.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view_unittest.cc
@@ -38,8 +38,7 @@
   DownloadBubbleRowViewTest()
       : TestWithBrowserView(
             content::BrowserTaskEnvironment::TimeSource::MOCK_TIME) {
-    scoped_feature_list_.InitWithFeatures(
-        {safe_browsing::kDownloadBubble, safe_browsing::kDownloadBubbleV2}, {});
+    scoped_feature_list_.InitAndEnableFeature(safe_browsing::kDownloadBubble);
   }
 
   DownloadBubbleRowViewTest(const DownloadBubbleRowViewTest&) = delete;
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
index 4be503cc..3f6f9ad6 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.cc
@@ -32,7 +32,6 @@
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/md_text_button.h"
@@ -48,7 +47,6 @@
 namespace {
 using offline_items_collection::ContentId;
 
-constexpr int kCheckboxHeight = 32;
 constexpr int kProgressBarHeight = 3;
 // Num of columns in the table layout, the width of which progress bar will
 // span. The 5 columns are Download Icon, Padding, Status text,
@@ -60,12 +58,12 @@
 // numeric values should never be reused.
 enum class DownloadBubbleSubpageAction {
   kShown = 0,
-  kShownCheckbox = 1,
+  // Reserved (obsolete): kShownCheckbox = 1,
   kShownSecondaryButton = 2,
   kShownPrimaryButton = 3,
   kPressedBackButton = 4,
   kClosedSubpage = 5,
-  kClickedCheckbox = 6,
+  // Reserved (obsolete): kClickedCheckbox = 6,
   kPressedSecondaryButton = 7,
   kPressedPrimaryButton = 8,
   kMaxValue = kPressedPrimaryButton
@@ -301,13 +299,6 @@
                                 DownloadBubbleSubpageAction::kClosedSubpage);
 }
 
-void DownloadBubbleSecurityView::OnCheckboxClicked() {
-  DCHECK(secondary_button_);
-  secondary_button_->SetEnabled(checkbox_->GetChecked());
-  base::UmaHistogramEnumeration(kSubpageActionHistogram,
-                                DownloadBubbleSubpageAction::kClickedCheckbox);
-}
-
 void DownloadBubbleSecurityView::UpdateIconAndText() {
   icon_->SetImage(ui::ImageModel::FromVectorIcon(
       *(ui_info_.icon_model_override), ui_info_.secondary_color,
@@ -320,14 +311,6 @@
   // Layout will stretch it back out into any additional space available.
   paragraphs_->SizeToFit(GetMinimumLabelWidth());
 
-  checkbox_->SetVisible(ui_info_.HasCheckbox());
-  if (ui_info_.HasCheckbox()) {
-    base::UmaHistogramEnumeration(kSubpageActionHistogram,
-                                  DownloadBubbleSubpageAction::kShownCheckbox);
-    checkbox_->SetChecked(false);
-    checkbox_->SetText(ui_info_.checkbox_label);
-  }
-
   // TODO(chlily): Implement deep_scanning_link_ as a learn_more_link_.
   if (danger_type_ == download::DownloadDangerType::
                           DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING ||
@@ -460,28 +443,6 @@
                               paragraphs_->GetLineHeight() / 2));
   }
 
-  checkbox_ = wrapper->AddChildView(std::make_unique<views::Checkbox>(
-      std::u16string(),
-      base::BindRepeating(&DownloadBubbleSecurityView::OnCheckboxClicked,
-                          base::Unretained(this))));
-  checkbox_->SetMultiLine(true);
-  checkbox_->SetProperty(
-      views::kMarginsKey,
-      gfx::Insets::VH(ChromeLayoutProvider::Get()->GetDistanceMetric(
-                          views::DISTANCE_RELATED_CONTROL_VERTICAL),
-                      0));
-  checkbox_->SetProperty(views::kCrossAxisAlignmentKey,
-                         views::LayoutAlignment::kStretch);
-  checkbox_->SetProperty(
-      views::kFlexBehaviorKey,
-      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
-                               views::MaximumFlexSizeRule::kUnbounded,
-                               /*adjust_height_for_width=*/true));
-  // Set min height for checkbox, so that it can layout label accordingly.
-  checkbox_->SetMinSize(gfx::Size(0, kCheckboxHeight));
-  // Will be updated later if checkbox should exist.
-  checkbox_->SetVisible(false);
-
   // TODO(chlily): Implement deep_scanning_link_ as a learn_more_link_.
   deep_scanning_link_ =
       wrapper->AddChildView(std::make_unique<views::StyledLabel>());
@@ -648,8 +609,7 @@
 
 void DownloadBubbleSecurityView::UpdateButton(
     DownloadUIModel::BubbleUIInfo::SubpageButton button_info,
-    bool is_secondary_button,
-    bool has_checkbox) {
+    bool is_secondary_button) {
   ui::DialogButton button_type =
       is_secondary_button ? ui::DIALOG_BUTTON_CANCEL : ui::DIALOG_BUTTON_OK;
 
@@ -659,7 +619,7 @@
 
   if (button_type == ui::DIALOG_BUTTON_CANCEL) {
     bubble_delegate_->SetCancelCallbackWithClose(callback);
-    bubble_delegate_->SetButtonEnabled(button_type, !has_checkbox);
+    bubble_delegate_->SetButtonEnabled(button_type, true);
     views::LabelButton* button = bubble_delegate_->GetCancelButton();
     if (button_info.color) {
       button->SetEnabledTextColorIds(*button_info.color);
@@ -687,15 +647,13 @@
 
   if (ui_info_.subpage_buttons.size() > 0) {
     bubble_delegate_->SetButtons(ui::DIALOG_BUTTON_OK);
-    UpdateButton(ui_info_.subpage_buttons[0], /*is_secondary_button=*/false,
-                 ui_info_.HasCheckbox());
+    UpdateButton(ui_info_.subpage_buttons[0], /*is_secondary_button=*/false);
   }
 
   if (ui_info_.subpage_buttons.size() > 1) {
     bubble_delegate_->SetButtons(ui::DIALOG_BUTTON_OK |
                                  ui::DIALOG_BUTTON_CANCEL);
-    UpdateButton(ui_info_.subpage_buttons[1], /*is_secondary_button=*/true,
-                 ui_info_.HasCheckbox());
+    UpdateButton(ui_info_.subpage_buttons[1], /*is_secondary_button=*/true);
   }
   // After we have updated the buttons, set the minimum width to avoid the rest
   // of the contents stretching out the dialog unnecessarily.
@@ -811,7 +769,7 @@
   }
   if (is_different_download || danger_type_changed) {
     warning_time_ = base::Time::Now();
-    ui_info_ = DownloadItemModel(download).GetBubbleUIInfo(is_bubble_v2_);
+    ui_info_ = DownloadItemModel(download).GetBubbleUIInfo();
     download::DownloadDangerType old_danger_type = danger_type_;
     danger_type_ = download->GetDangerType();
     // If this represents a "terminal" state of a deep scan, or if the download
@@ -886,10 +844,8 @@
 DownloadBubbleSecurityView::DownloadBubbleSecurityView(
     Delegate* delegate,
     base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler,
-    views::BubbleDialogDelegate* bubble_delegate,
-    bool is_bubble_v2)
+    views::BubbleDialogDelegate* bubble_delegate)
     : delegate_(delegate),
-      is_bubble_v2_(is_bubble_v2),
       navigation_handler_(std::move(navigation_handler)),
       bubble_delegate_(bubble_delegate) {
   CHECK(delegate_);
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
index ab69a44..3044e58 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view.h
@@ -19,7 +19,6 @@
 #include "ui/views/view.h"
 
 namespace views {
-class Checkbox;
 class ImageView;
 class StyledLabel;
 class ImageButton;
@@ -79,8 +78,7 @@
   DownloadBubbleSecurityView(
       Delegate* delegate,
       base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler,
-      views::BubbleDialogDelegate* bubble_delegate,
-      bool is_bubble_v2);
+      views::BubbleDialogDelegate* bubble_delegate);
   DownloadBubbleSecurityView(const DownloadBubbleSecurityView&) = delete;
   DownloadBubbleSecurityView& operator=(const DownloadBubbleSecurityView&) =
       delete;
@@ -130,7 +128,6 @@
   void BackButtonPressed();
   void AddHeader();
   void CloseBubble();
-  void OnCheckboxClicked();
   void AddIconAndContents();
   void AddSecondaryIconAndText();
   void AddProgressBar();
@@ -147,8 +144,7 @@
   // Updates the subpage button. Setting initial state and color for enabled
   // state, if it is a secondary button.
   void UpdateButton(DownloadUIModel::BubbleUIInfo::SubpageButton button,
-                    bool is_secondary_button,
-                    bool has_checkbox);
+                    bool is_secondary_button);
   void UpdateButtons();
   void UpdateProgressBar();
   void UpdatePasswordPrompt();
@@ -189,15 +185,11 @@
   download::DownloadDangerType danger_type_ =
       download::DOWNLOAD_DANGER_TYPE_MAX;
 
-  // Whether V2 of the download bubble is enabled.
-  const bool is_bubble_v2_;
   base::WeakPtr<DownloadBubbleNavigationHandler> navigation_handler_ = nullptr;
   raw_ptr<views::BubbleDialogDelegate, DanglingUntriaged> bubble_delegate_ =
       nullptr;
 
-  // The secondary button is the one that may be protected by the checkbox.
   raw_ptr<views::LabelButton, DanglingUntriaged> secondary_button_ = nullptr;
-  raw_ptr<views::Checkbox> checkbox_ = nullptr;
   raw_ptr<views::StyledLabel> title_ = nullptr;
   raw_ptr<views::ImageView> icon_ = nullptr;
   raw_ptr<ParagraphsView> paragraphs_ = nullptr;
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc b/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc
index 9afcf68..a0148a1 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_security_view_unittest.cc
@@ -182,7 +182,7 @@
     security_view_ = bubble_delegate_->SetContentsView(
         std::make_unique<DownloadBubbleSecurityView>(
             security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-            bubble_delegate_, /*is_bubble_v2=*/true));
+            bubble_delegate_));
 
     DownloadCoreServiceFactory::GetInstance()->SetTestingFactory(
         browser_->profile(),
@@ -350,7 +350,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     security_view->BackButtonPressed();
@@ -368,7 +368,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     security_view->CloseBubble();
@@ -386,7 +386,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     security_view.reset();
@@ -402,7 +402,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     security_view->BackButtonPressed();
@@ -428,7 +428,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     security_view->BackButtonPressed();
@@ -464,7 +464,7 @@
   {
     auto security_view = std::make_unique<DownloadBubbleSecurityView>(
         security_view_delegate_.get(), bubble_navigator_->GetWeakPtr(),
-        bubble_delegate_, /*is_bubble_v2=*/true);
+        bubble_delegate_);
     security_view->InitializeForDownload(*row1_model_);
 
     // No action is logged upon removal of download.
@@ -582,7 +582,7 @@
 // Test that an update with an insecure download status does not cause us to
 // return to the primary dialog.
 TEST_F(DownloadBubbleSecurityViewTest, InsecureDontReturnToPrimaryDialog) {
-  ASSERT_TRUE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage());
   security_view_->InitializeForDownload(*row1_model_);
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
@@ -599,7 +599,7 @@
       .WillRepeatedly(ReturnRefOfCopy(GURL("http://insecure.com/a.exe")));
   download_item1_.NotifyObserversDownloadUpdated();
 
-  ASSERT_TRUE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage());
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
             OfflineItemUtils::GetContentIdForDownload(&download_item1_));
@@ -611,7 +611,7 @@
 // Test that an update where the new state does not have a subpage causes us to
 // return to the primary dialog.
 TEST_F(DownloadBubbleSecurityViewTest, ReturnToPrimaryDialogNoSubpage) {
-  ASSERT_TRUE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage());
   security_view_->InitializeForDownload(*row1_model_);
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
@@ -623,7 +623,7 @@
           download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
   download_item1_.NotifyObserversDownloadUpdated();
 
-  ASSERT_FALSE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_FALSE(row1_model_->GetBubbleUIInfo().HasSubpage());
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
             OfflineItemUtils::GetContentIdForDownload(&download_item1_));
@@ -634,7 +634,7 @@
 // Test validating a dangerous download, such that it goes from having
 // a UI info subpage to not having one. See crbug.com/1478390.
 TEST_F(DownloadBubbleSecurityViewTest, ValidateDangerousDownload) {
-  ASSERT_TRUE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_TRUE(row1_model_->GetBubbleUIInfo().HasSubpage());
   security_view_->InitializeForDownload(*row1_model_);
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
@@ -646,7 +646,7 @@
           download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_USER_VALIDATED));
   download_item1_.NotifyObserversDownloadUpdated();
 
-  ASSERT_FALSE(row1_model_->GetBubbleUIInfo(true).HasSubpage());
+  ASSERT_FALSE(row1_model_->GetBubbleUIInfo().HasSubpage());
   EXPECT_TRUE(security_view_->IsInitialized());
   EXPECT_EQ(security_view_->content_id(),
             OfflineItemUtils::GetContentIdForDownload(&download_item1_));
diff --git a/chrome/browser/ui/views/elevation_icon_setter.cc b/chrome/browser/ui/views/elevation_icon_setter.cc
index 0321891..3e25fb39 100644
--- a/chrome/browser/ui/views/elevation_icon_setter.cc
+++ b/chrome/browser/ui/views/elevation_icon_setter.cc
@@ -73,9 +73,10 @@
     // mark this image as having been scaled for the current DPI already.
     device_scale_factor = display::win::GetDPIScale();
 #endif
-    button_->SetImage(
+    button_->SetImageModel(
         views::Button::STATE_NORMAL,
-        gfx::ImageSkia::CreateFromBitmap(icon, device_scale_factor));
+        ui::ImageModel::FromImageSkia(
+            gfx::ImageSkia::CreateFromBitmap(icon, device_scale_factor)));
     button_->SizeToPreferredSize();
     if (button_->parent())
       button_->parent()->Layout();
diff --git a/chrome/browser/ui/views/permissions/permissions_flow_interactive_uitest.cc b/chrome/browser/ui/views/permissions/permissions_flow_interactive_uitest.cc
index 48b99b3..d69d1b3 100644
--- a/chrome/browser/ui/views/permissions/permissions_flow_interactive_uitest.cc
+++ b/chrome/browser/ui/views/permissions/permissions_flow_interactive_uitest.cc
@@ -146,7 +146,7 @@
       PressButton(kLocationIconElementId),
       WaitForShow(PageInfoMainView::kPermissionsElementId),
       NameChildView(PageInfoMainView::kPermissionsElementId,
-                    kFirstPermissionRow, 0),
+                    kFirstPermissionRow, 0u),
       CheckViewProperty(
           kFirstPermissionRow, &PermissionToggleRowView::GetRowTitleForTesting,
           l10n_util::GetStringUTF16(IDS_SITE_SETTINGS_TYPE_NOTIFICATIONS)));
@@ -172,7 +172,7 @@
       PressButton(kLocationIconElementId),
       WaitForShow(PageInfoMainView::kPermissionsElementId),
       NameChildView(PageInfoMainView::kPermissionsElementId,
-                    kFirstPermissionRow, 0),
+                    kFirstPermissionRow, 0u),
       CheckViewProperty(
           kFirstPermissionRow, &PermissionToggleRowView::GetRowTitleForTesting,
           l10n_util::GetStringUTF16(IDS_SITE_SETTINGS_TYPE_CAMERA)));
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
index 7867d8c..62a956f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -194,14 +194,14 @@
                                         size);
 }
 
-const gfx::ImageSkia ProfileManagementImageFromIcon(
+const ui::ImageModel ProfileManagementImageFromIcon(
     const gfx::VectorIcon& icon,
     const ui::ColorProvider* color_provider) {
   constexpr float kIconToImageRatio = 0.75f;
   constexpr int kIconSize = 20;
   const SkColor icon_color = color_provider->GetColor(ui::kColorIcon);
   gfx::ImageSkia image = ImageForMenu(icon, kIconToImageRatio, icon_color);
-  return SizeImage(image, kIconSize);
+  return ui::ImageModel::FromImageSkia(SizeImage(image, kIconSize));
 }
 
 // TODO(crbug.com/1146998): Adjust button size to be 16x16.
@@ -339,8 +339,8 @@
   // HoverButton:
   void OnThemeChanged() override {
     HoverButton::OnThemeChanged();
-    SetImage(STATE_NORMAL,
-             ProfileManagementImageFromIcon(*icon_, GetColorProvider()));
+    SetImageModel(Button::STATE_NORMAL,
+                  ProfileManagementImageFromIcon(*icon_, GetColorProvider()));
   }
 
  private:
@@ -435,7 +435,9 @@
   // HoverButton:
   void OnThemeChanged() override {
     HoverButton::OnThemeChanged();
-    SetImage(STATE_NORMAL, SizeImage(root_view_->GetSyncIcon(), kBadgeSize));
+    SetImageModel(Button::STATE_NORMAL,
+                  ui::ImageModel::FromImageSkia(
+                      SizeImage(root_view_->GetSyncIcon(), kBadgeSize)));
   }
 
  private:
diff --git a/chrome/browser/ui/views/site_data/page_specific_site_data_dialog_interactive_uitest.cc b/chrome/browser/ui/views/site_data/page_specific_site_data_dialog_interactive_uitest.cc
index b2a7d9c..1a8483b 100644
--- a/chrome/browser/ui/views/site_data/page_specific_site_data_dialog_interactive_uitest.cc
+++ b/chrome/browser/ui/views/site_data/page_specific_site_data_dialog_interactive_uitest.cc
@@ -283,7 +283,7 @@
                             &observer),
       // Name the third-party cookies row.
       InAnyContext(NameChildView(kPageSpecificSiteDataDialogThirdPartySection,
-                                 kThirdPartyBlockedRow, 2)),
+                                 kThirdPartyBlockedRow, 2u)),
       CheckRowLabel(kThirdPartyBlockedRow,
                     IDS_PAGE_SPECIFIC_SITE_DATA_DIALOG_BLOCKED_STATE_SUBTITLE),
       OpenRowMenu(kThirdPartyBlockedRow),
@@ -329,7 +329,7 @@
       // Find the third party section and name the row with partitioned only
       // access (b.test).
       InAnyContext(NameChildView(kPageSpecificSiteDataDialogThirdPartySection,
-                                 kOnlyPartitionedRow, 0)),
+                                 kOnlyPartitionedRow, 0u)),
       CheckRowLabel(
           kOnlyPartitionedRow,
           IDS_PAGE_SPECIFIC_SITE_DATA_DIALOG_PARTITIONED_STATE_SUBTITLE),
@@ -369,7 +369,7 @@
       // Find the third party section and name the row with mixed storage
       // access (c.test).
       InAnyContext(NameChildView(kPageSpecificSiteDataDialogThirdPartySection,
-                                 kMixedPartitionedRow, 1)),
+                                 kMixedPartitionedRow, 1u)),
       CheckRowLabel(
           kMixedPartitionedRow,
           IDS_PAGE_SPECIFIC_SITE_DATA_DIALOG_PARTITIONED_STATE_SUBTITLE),
@@ -465,7 +465,7 @@
                             kPageSpecificSiteDataDialogFirstPartySection),
       // Name the first row in the first-party section.
       InAnyContext(NameChildView(kPageSpecificSiteDataDialogFirstPartySection,
-                                 kFirstPartyAllowedRow, 0)),
+                                 kFirstPartyAllowedRow, 0u)),
       // Verify no empty state label is present.
       InAnyContext(
           EnsureNotPresent(kPageSpecificSiteDataDialogEmptyStateLabel)),
@@ -515,7 +515,7 @@
       NavigateAndOpenDialog(kPageSpecificSiteDataDialogFirstPartySection),
       // Name the first row in the first-party section.
       InAnyContext(NameChildView(kPageSpecificSiteDataDialogFirstPartySection,
-                                 kFirstPartyAllowedRow, 0)),
+                                 kFirstPartyAllowedRow, 0u)),
       // Verify no empty state label is present.
       InAnyContext(
           EnsureNotPresent(kPageSpecificSiteDataDialogEmptyStateLabel)),
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
index a52773b..0579737 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
@@ -15,6 +15,10 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/side_search/side_search_config.h"
+#include "chrome/browser/ui/toolbar/app_menu_model.h"
+#include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
+#include "chrome/browser/ui/toolbar/reading_list_sub_menu_model.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/side_panel/side_panel.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
@@ -53,6 +57,20 @@
   // Opens the side panel and instruments the Read Later WebContents as
   // kReadLaterWebContentsElementId.
   auto OpenReadingListSidePanel() {
+    if (features::IsChromeRefresh2023() &&
+        base::FeatureList::IsEnabled(features::kSidePanelPinning)) {
+      return Steps(
+          PressButton(kToolbarAppMenuButtonElementId),
+          SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
+          SelectMenuItem(BookmarkSubMenuModel::kReadingListMenuItem),
+          SelectMenuItem(ReadingListSubMenuModel::kReadingListMenuShowUI),
+          WaitForShow(kSidePanelElementId),
+          WaitForShow(kReadLaterSidePanelWebViewElementId), FlushEvents(),
+          // Ensure that the Reading List side panel loads properly.
+          InstrumentNonTabWebView(kReadLaterWebContentsElementId,
+                                  kReadLaterSidePanelWebViewElementId));
+    }
+
     return Steps(
         // Remove delays in switching side panels to prevent possible race
         // conditions when selecting items from the side panel dropdown.
@@ -73,6 +91,23 @@
                                 kReadLaterSidePanelWebViewElementId));
   }
 
+  auto OpenBookmarksSidePanel() {
+    if (features::IsChromeRefresh2023() &&
+        base::FeatureList::IsEnabled(features::kSidePanelPinning)) {
+      return Steps(
+          PressButton(kToolbarAppMenuButtonElementId),
+          SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
+          SelectMenuItem(BookmarkSubMenuModel::kShowBookmarkSidePanelItem),
+          WaitForShow(kSidePanelElementId), FlushEvents());
+    }
+
+    // Yes, this assumes the side panel is already open.
+    return Steps(
+        EnsurePresent(kSidePanelElementId),
+        SelectDropdownItem(kSidePanelComboboxElementId,
+                           static_cast<int>(SidePanelEntry::Id::kBookmarks)));
+  }
+
   auto ShowHelpBubble(ElementSpecifier element) {
     return InAnyContext(std::move(
         AfterShow(
@@ -239,8 +274,7 @@
           user_education::HelpBubbleView::kHelpBubbleElementIdForTesting),
       // Switch to a different side panel; this removes the Reading List WebView
       // from its widget and effectively hides the WebContents.
-      SelectDropdownItem(kSidePanelComboboxElementId,
-                         static_cast<int>(SidePanelEntry::Id::kBookmarks)),
+      OpenBookmarksSidePanel(),
       WaitForHide(
           user_education::HelpBubbleView::kHelpBubbleElementIdForTesting));
 }
diff --git a/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc
index 60163ea..78e6dbe 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_handler_interactive_uitest.cc
@@ -2,10 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/feature_list.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/side_search/side_search_config.h"
+#include "chrome/browser/ui/toolbar/app_menu_model.h"
+#include "chrome/browser/ui/toolbar/bookmark_sub_menu_model.h"
+#include "chrome/browser/ui/toolbar/reading_list_sub_menu_model.h"
+#include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
@@ -31,6 +36,26 @@
   // Opens the side panel and instruments the Read Later WebContents as
   // kReadLaterWebContentsElementId.
   auto OpenReadingListSidePanel() {
+    if (features::IsChromeRefresh2023() &&
+        base::FeatureList::IsEnabled(features::kSidePanelPinning)) {
+      return Steps(
+          // Remove delays in switching side panels to prevent possible race
+          // conditions when selecting items from the side panel dropdown.
+          Do([this]() {
+            SidePanelUtil::GetSidePanelCoordinatorForBrowser(browser())
+                ->SetNoDelaysForTesting(true);
+          }),
+          PressButton(kToolbarAppMenuButtonElementId),
+          SelectMenuItem(AppMenuModel::kBookmarksMenuItem),
+          SelectMenuItem(BookmarkSubMenuModel::kReadingListMenuItem),
+          SelectMenuItem(ReadingListSubMenuModel::kReadingListMenuShowUI),
+          WaitForShow(kSidePanelElementId),
+          WaitForShow(kReadLaterSidePanelWebViewElementId), FlushEvents(),
+          // Ensure that the Reading List side panel loads properly.
+          InstrumentNonTabWebView(kReadLaterWebContentsElementId,
+                                  kReadLaterSidePanelWebViewElementId));
+    }
+
     return Steps(
         // Remove delays in switching side panels to prevent possible race
         // conditions when selecting items from the side panel dropdown.
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
index 5a40d03f..47894d4e 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -42,7 +42,7 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install_dialog.h"
 #include "chromeos/constants/chromeos_features.h"
 #endif
 
@@ -82,9 +82,9 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
       if (base::FeatureList::IsEnabled(
               chromeos::features::kCrosWebAppInstallDialog)) {
-        ash::web_app_install::WebAppInstallDialog::Show(
+        ash::app_install::AppInstallDialog::Show(
             initiator_web_contents->GetNativeView(),
-            ash::web_app_install::ChromeOsAppInstallDialogParams(
+            ash::app_install::ChromeOsAppInstallDialogParams(
                 std::move(web_app_info),
                 webapps::AppBannerManager::FromWebContents(
                     initiator_web_contents)
diff --git a/chrome/browser/ui/webui/ash/web_app_install/BUILD.gn b/chrome/browser/ui/webui/ash/app_install/BUILD.gn
similarity index 91%
rename from chrome/browser/ui/webui/ash/web_app_install/BUILD.gn
rename to chrome/browser/ui/webui/ash/app_install/BUILD.gn
index dfcb9b7..b409d08f 100644
--- a/chrome/browser/ui/webui/ash/web_app_install/BUILD.gn
+++ b/chrome/browser/ui/webui/ash/app_install/BUILD.gn
@@ -8,7 +8,7 @@
 assert(is_chromeos_ash, "The install dialog is ash-chrome only")
 
 mojom("mojo_bindings") {
-  sources = [ "web_app_install.mojom" ]
+  sources = [ "app_install.mojom" ]
 
   public_deps = [
     "//mojo/public/mojom/base",
diff --git a/chrome/browser/ui/webui/ash/web_app_install/OWNERS b/chrome/browser/ui/webui/ash/app_install/OWNERS
similarity index 100%
rename from chrome/browser/ui/webui/ash/web_app_install/OWNERS
rename to chrome/browser/ui/webui/ash/app_install/OWNERS
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom b/chrome/browser/ui/webui/ash/app_install/app_install.mojom
similarity index 96%
rename from chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom
rename to chrome/browser/ui/webui/ash/app_install/app_install.mojom
index 7c37a1b4..6644fa7 100644
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom
+++ b/chrome/browser/ui/webui/ash/app_install/app_install.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module ash.web_app_install.mojom;
+module ash.app_install.mojom;
 
 import "url/mojom/url.mojom";
 
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.cc b/chrome/browser/ui/webui/ash/app_install/app_install_dialog.cc
similarity index 72%
rename from chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.cc
rename to chrome/browser/ui/webui/ash/app_install/app_install_dialog.cc
index 3132b685..55deb491 100644
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.cc
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_dialog.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install_dialog.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install_ui.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/webapps/browser/installable/installable_data.h"
 #include "components/webapps/common/constants.h"
 #include "ui/gfx/text_elider.h"
 
-namespace ash::web_app_install {
+namespace ash::app_install {
 
 namespace {
 
@@ -52,13 +52,13 @@
 ChromeOsAppInstallDialogParams::~ChromeOsAppInstallDialogParams() = default;
 
 // static
-bool WebAppInstallDialog::Show(gfx::NativeWindow parent,
-                               ChromeOsAppInstallDialogParams params) {
+bool AppInstallDialog::Show(gfx::NativeWindow parent,
+                            ChromeOsAppInstallDialogParams params) {
   CHECK(base::FeatureList::IsEnabled(
       chromeos::features::kCrosWebAppInstallDialog));
   // Allow no more than one upload dialog at a time.
   if (SystemWebDialogDelegate::HasInstance(
-          GURL(chrome::kChromeUIWebAppInstallDialogURL))) {
+          GURL(chrome::kChromeUIAppInstallDialogURL))) {
     return false;
   }
 
@@ -72,26 +72,26 @@
 
   // The pointer is managed by an instance of `views::WebDialogView` and removed
   // in `SystemWebDialogDelegate::OnDialogClosed`.
-  WebAppInstallDialog* dialog = new WebAppInstallDialog(std::move(args));
+  AppInstallDialog* dialog = new AppInstallDialog(std::move(args));
   dialog->ShowSystemDialog(parent);
   return true;
 }
 
-void WebAppInstallDialog::OnDialogShown(content::WebUI* webui) {
+void AppInstallDialog::OnDialogShown(content::WebUI* webui) {
   DCHECK(dialog_args_);
-  static_cast<WebAppInstallDialogUI*>(webui->GetController())
+  static_cast<AppInstallDialogUI*>(webui->GetController())
       ->SetDialogArgs(std::move(dialog_args_));
 }
 
-WebAppInstallDialog::WebAppInstallDialog(mojom::DialogArgsPtr args)
-    : SystemWebDialogDelegate(GURL(chrome::kChromeUIWebAppInstallDialogURL),
+AppInstallDialog::AppInstallDialog(mojom::DialogArgsPtr args)
+    : SystemWebDialogDelegate(GURL(chrome::kChromeUIAppInstallDialogURL),
                               std::u16string() /* title */),
       dialog_args_(std::move(args)) {}
 
-WebAppInstallDialog::~WebAppInstallDialog() = default;
+AppInstallDialog::~AppInstallDialog() = default;
 
-bool WebAppInstallDialog::ShouldShowCloseButton() const {
+bool AppInstallDialog::ShouldShowCloseButton() const {
   return false;
 }
 
-}  // namespace ash::web_app_install
+}  // namespace ash::app_install
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_dialog.h b/chrome/browser/ui/webui/ash/app_install/app_install_dialog.h
new file mode 100644
index 0000000..7d87fd3
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_dialog.h
@@ -0,0 +1,54 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_DIALOG_H_
+#define CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_DIALOG_H_
+
+#include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h"
+#include "chrome/browser/ui/webui/ash/system_web_dialog_delegate.h"
+// TODO(b/308717267): Remove this dependency when moving to mojom struct
+// definition for Lacros support.
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "components/webapps/browser/installable/installable_data.h"
+
+namespace ash::app_install {
+
+struct ChromeOsAppInstallDialogParams {
+  std::optional<SkBitmap> icon_bitmap;
+  std::string name;
+  GURL url;
+  std::string description;
+  std::vector<webapps::Screenshot> screenshots;
+
+  ChromeOsAppInstallDialogParams(
+      std::unique_ptr<web_app::WebAppInstallInfo> web_app_info,
+      std::vector<webapps::Screenshot> screenshots);
+  ~ChromeOsAppInstallDialogParams();
+};
+
+// Defines the web dialog used for installing an app.
+class AppInstallDialog : public SystemWebDialogDelegate {
+ public:
+  AppInstallDialog(const AppInstallDialog&) = delete;
+  AppInstallDialog& operator=(const AppInstallDialog&) = delete;
+
+  // Creates and shows a new dialog for installing an app. Returns true
+  // if a new dialog has been effectively created.
+  static bool Show(gfx::NativeWindow parent,
+                   ChromeOsAppInstallDialogParams params);
+
+  void OnDialogShown(content::WebUI* webui) override;
+
+ protected:
+  explicit AppInstallDialog(mojom::DialogArgsPtr args);
+  ~AppInstallDialog() override;
+  bool ShouldShowCloseButton() const override;
+
+ private:
+  mojom::DialogArgsPtr dialog_args_;
+};
+
+}  // namespace ash::app_install
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_DIALOG_H_
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc
new file mode 100644
index 0000000..770048cf
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.cc
@@ -0,0 +1,35 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h"
+
+#include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h"
+
+namespace ash::app_install {
+
+AppInstallPageHandler::AppInstallPageHandler(
+    mojom::DialogArgsPtr args,
+    mojo::PendingReceiver<mojom::PageHandler>
+        pending_page_handler,
+    CloseDialogCallback close_dialog_callback)
+    : dialog_args_{std::move(args)},
+      receiver_{this, std::move(pending_page_handler)},
+      close_dialog_callback_{std::move(close_dialog_callback)} {}
+
+AppInstallPageHandler::~AppInstallPageHandler() = default;
+
+void AppInstallPageHandler::GetDialogArgs(GetDialogArgsCallback callback) {
+  std::move(callback).Run(dialog_args_ ? dialog_args_.Clone()
+                                       : mojom::DialogArgs::New());
+}
+
+void AppInstallPageHandler::CloseDialog() {
+  // The callback could be null if the close button is clicked a second time
+  // before the dialog closes.
+  if (close_dialog_callback_) {
+    std::move(close_dialog_callback_).Run();
+  }
+}
+
+}  // namespace ash::app_install
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h
new file mode 100644
index 0000000..e221708
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h
@@ -0,0 +1,47 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_PAGE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_PAGE_HANDLER_H_
+
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace ash::app_install {
+
+// Handles communication from the chrome://app-install renderer process to
+// the browser process exposing various methods for the JS to invoke.
+class AppInstallPageHandler : public mojom::PageHandler {
+ public:
+  using CloseDialogCallback = base::OnceCallback<void()>;
+  explicit AppInstallPageHandler(
+      mojom::DialogArgsPtr args,
+      mojo::PendingReceiver<mojom::PageHandler> pending_page_handler,
+      CloseDialogCallback close_dialog_callback);
+
+  AppInstallPageHandler(const AppInstallPageHandler&) = delete;
+  AppInstallPageHandler& operator=(const AppInstallPageHandler&) = delete;
+
+  ~AppInstallPageHandler() override;
+
+  // mojom::PageHandler:
+  void GetDialogArgs(GetDialogArgsCallback callback) override;
+  void CloseDialog() override;
+
+ private:
+  mojom::DialogArgsPtr dialog_args_;
+  mojo::Receiver<mojom::PageHandler> receiver_;
+  CloseDialogCallback close_dialog_callback_;
+
+  base::WeakPtrFactory<AppInstallPageHandler> weak_ptr_factory_{this};
+};
+
+}  // namespace ash::app_install
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc b/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc
new file mode 100644
index 0000000..78e1a75
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_ui.cc
@@ -0,0 +1,78 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/ash/app_install/app_install_ui.h"
+
+#include "base/feature_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/grit/app_install_resources.h"
+#include "chrome/grit/app_install_resources_map.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/url_constants.h"
+
+namespace ash::app_install {
+
+AppInstallDialogUI::AppInstallDialogUI(content::WebUI* web_ui)
+    : ui::MojoWebDialogUI(web_ui) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      Profile::FromWebUI(web_ui), chrome::kChromeUIAppInstallDialogHost);
+
+  static constexpr webui::LocalizedString kStrings[] = {
+      {"cancel", IDS_CANCEL},
+      {"install", IDS_INSTALL},
+      {"installing", IDS_OFFICE_INSTALL_PWA_INSTALLING_BUTTON},
+  };
+
+  source->AddLocalizedStrings(kStrings);
+  webui::SetupWebUIDataSource(
+      source,
+      base::make_span(kAppInstallResources, kAppInstallResourcesSize),
+      IDR_APP_INSTALL_MAIN_HTML);
+}
+
+AppInstallDialogUI::~AppInstallDialogUI() = default;
+
+void AppInstallDialogUI::SetDialogArgs(mojom::DialogArgsPtr args) {
+  dialog_args_ = std::move(args);
+}
+
+void AppInstallDialogUI::BindInterface(
+    mojo::PendingReceiver<mojom::PageHandlerFactory> pending_receiver) {
+  if (factory_receiver_.is_bound()) {
+    factory_receiver_.reset();
+  }
+  factory_receiver_.Bind(std::move(pending_receiver));
+}
+
+void AppInstallDialogUI::CreatePageHandler(
+    mojo::PendingReceiver<mojom::PageHandler> receiver) {
+  page_handler_ = std::make_unique<AppInstallPageHandler>(
+      std::move(dialog_args_), std::move(receiver),
+      base::BindOnce(&AppInstallDialogUI::CloseDialog,
+                     base::Unretained(this)));
+}
+
+void AppInstallDialogUI::CloseDialog() {
+  ui::MojoWebDialogUI::CloseDialog(base::Value::List());
+}
+
+WEB_UI_CONTROLLER_TYPE_IMPL(AppInstallDialogUI)
+
+bool AppInstallDialogUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  return base::FeatureList::IsEnabled(
+      chromeos::features::kCrosWebAppInstallDialog);
+}
+
+AppInstallDialogUIConfig::AppInstallDialogUIConfig()
+    : DefaultWebUIConfig(content::kChromeUIScheme,
+                         chrome::kChromeUIAppInstallDialogHost) {}
+
+}  // namespace ash::app_install
diff --git a/chrome/browser/ui/webui/ash/app_install/app_install_ui.h b/chrome/browser/ui/webui/ash/app_install/app_install_ui.h
new file mode 100644
index 0000000..3d49ecd
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/app_install/app_install_ui.h
@@ -0,0 +1,55 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_UI_H_
+
+#include "chrome/browser/ui/webui/ash/app_install/app_install_page_handler.h"
+#include "content/public/browser/webui_config.h"
+#include "ui/web_dialogs/web_dialog_ui.h"
+
+namespace ash::app_install {
+
+// The WebUI for chrome://app-install-dialog, used for confirming app
+// installation.
+class AppInstallDialogUI : public ui::MojoWebDialogUI,
+                              public mojom::PageHandlerFactory {
+ public:
+  explicit AppInstallDialogUI(content::WebUI* web_ui);
+  AppInstallDialogUI(const AppInstallDialogUI&) = delete;
+  AppInstallDialogUI& operator=(const AppInstallDialogUI&) = delete;
+  ~AppInstallDialogUI() override;
+
+  void SetDialogArgs(mojom::DialogArgsPtr args);
+
+  // Instantiates the implementor of the mojom::PageHandlerFactory mojo
+  // interface passing the pending receiver that will be internally bound.
+  void BindInterface(mojo::PendingReceiver<mojom::PageHandlerFactory> receiver);
+
+  // mojom::PageHandlerFactory:
+  void CreatePageHandler(
+      mojo::PendingReceiver<mojom::PageHandler> pending_page_handler) override;
+
+ private:
+  void CloseDialog();
+
+  mojom::DialogArgsPtr dialog_args_;
+  std::unique_ptr<AppInstallPageHandler> page_handler_;
+  mojo::Receiver<mojom::PageHandlerFactory> factory_receiver_{this};
+
+  WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+// WebUIConfig for chrome://app-install-dialog
+class AppInstallDialogUIConfig
+    : public content::DefaultWebUIConfig<AppInstallDialogUI> {
+ public:
+  AppInstallDialogUIConfig();
+
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+};
+
+}  // namespace ash::app_install
+
+#endif  // CHROME_BROWSER_UI_WEBUI_ASH_APP_INSTALL_APP_INSTALL_UI_H_
diff --git a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc
index b29dc86..1b839c8 100644
--- a/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc
+++ b/chrome/browser/ui/webui/ash/chrome_web_ui_configs_chromeos.cc
@@ -59,6 +59,7 @@
 #include "chrome/browser/ui/webui/ash/account_manager/account_manager_error_ui.h"
 #include "chrome/browser/ui/webui/ash/account_manager/account_migration_welcome_ui.h"
 #include "chrome/browser/ui/webui/ash/add_supervision/add_supervision_ui.h"
+#include "chrome/browser/ui/webui/ash/app_install/app_install_ui.h"
 #include "chrome/browser/ui/webui/ash/arc_graphics_tracing/arc_graphics_tracing_ui.h"
 #include "chrome/browser/ui/webui/ash/arc_power_control/arc_power_control_ui.h"
 #include "chrome/browser/ui/webui/ash/assistant_optin/assistant_optin_ui.h"
@@ -102,7 +103,6 @@
 #include "chrome/browser/ui/webui/ash/sys_internals/sys_internals_ui.h"
 #include "chrome/browser/ui/webui/ash/vc_tray_tester/vc_tray_tester_ui.h"
 #include "chrome/browser/ui/webui/ash/vm/vm_ui.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h"
 #include "chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h"
 #include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h"
 #if !defined(OFFICIAL_BUILD)
@@ -224,6 +224,7 @@
   map.AddWebUIConfig(std::make_unique<AccountManagerErrorUIConfig>());
   map.AddWebUIConfig(std::make_unique<AccountMigrationWelcomeUIConfig>());
   map.AddWebUIConfig(std::make_unique<AddSupervisionUIConfig>());
+  map.AddWebUIConfig(std::make_unique<app_install::AppInstallDialogUIConfig>());
   map.AddWebUIConfig(std::make_unique<ArcGraphicsTracingUIConfig>());
   map.AddWebUIConfig(std::make_unique<ArcPowerControlUIConfig>());
   map.AddWebUIConfig(std::make_unique<AssistantOptInUIConfig>());
@@ -320,8 +321,6 @@
       std::make_unique<UrgentPasswordExpiryNotificationUIConfig>());
   map.AddWebUIConfig(std::make_unique<VcTrayTesterUIConfig>());
   map.AddWebUIConfig(std::make_unique<VmUIConfig>());
-  map.AddWebUIConfig(
-      std::make_unique<web_app_install::WebAppInstallDialogUIConfig>());
 #if !defined(OFFICIAL_BUILD)
   map.AddWebUIConfig(std::make_unique<SampleSystemWebAppUIConfig>());
   map.AddWebUIConfig(std::make_unique<StatusAreaInternalsUIConfig>());
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
index 882532c..7fe880e1 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
@@ -212,32 +212,8 @@
         {kDocxFileExtension, kPptxFileExtension, kXlsxFileExtension},
         {kDocxMimeType, kPptxMimeType, kXlsxMimeType}, num_tasks_);
 
-    file_manager::test::FolderInMyFiles folder(profile());
-
-    base::FilePath test_data_path;
-    EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_path));
-    std::string file_names[] = {"text.docx", "presentation.pptx"};
-
-    for (const auto& file_name : file_names) {
-      base::FilePath file_path =
-          test_data_path.AppendASCII("chromeos/file_manager/" + file_name);
-      {
-        base::ScopedAllowBlockingForTesting allow_blocking;
-        EXPECT_TRUE(base::PathExists(file_path));
-      }
-      // Copy the file into My Files.
-      folder.Add({file_path});
-    }
-
-    for (const auto& path_in_my_files : folder.files()) {
-      GURL url;
-      CHECK(file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl(
-          profile(), path_in_my_files, file_manager::util::GetFileManagerURL(),
-          &url));
-      auto* file_system_context =
-          file_manager::util::GetFileManagerFileSystemContext(profile());
-      files_.push_back(file_system_context->CrackURLInFirstPartyContext(url));
-    }
+    files_ = file_manager::test::CopyTestFilesIntoMyFiles(
+        profile(), {"text.docx", "presentation.pptx"});
   }
 
  protected:
diff --git a/chrome/browser/ui/webui/ash/settings/pages/crostini/crostini_section.cc b/chrome/browser/ui/webui/ash/settings/pages/crostini/crostini_section.cc
index b64a409..1a96d232 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/crostini/crostini_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/crostini/crostini_section.cc
@@ -424,7 +424,7 @@
   html_source->AddString(
       "crostiniContainerUpgrade",
       l10n_util::GetStringUTF16(
-          IDS_SETTINGS_CROSTINI_CONTAINER_UPGRADE_BULLSEYE_MESSAGE));
+          IDS_OS_SETTINGS_CROSTINI_CONTAINER_UPGRADE_BOOKWORM_MESSAGE));
 
   if (auto* pretty_name_value = guest_os::GetContainerPrefValue(
           profile_, crostini::DefaultContainerId(),
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.h b/chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.h
deleted file mode 100644
index 348a2d5d..0000000
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_dialog.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_DIALOG_H_
-#define CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_DIALOG_H_
-
-#include "chrome/browser/ui/webui/ash/system_web_dialog_delegate.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom.h"
-// TODO(b/308717267): Remove this dependency when moving to mojom struct
-// definition for Lacros support.
-#include "chrome/browser/web_applications/web_app_install_info.h"
-#include "components/webapps/browser/installable/installable_data.h"
-
-namespace ash::web_app_install {
-
-struct ChromeOsAppInstallDialogParams {
-  std::optional<SkBitmap> icon_bitmap;
-  std::string name;
-  GURL url;
-  std::string description;
-  std::vector<webapps::Screenshot> screenshots;
-
-  ChromeOsAppInstallDialogParams(
-      std::unique_ptr<web_app::WebAppInstallInfo> web_app_info,
-      std::vector<webapps::Screenshot> screenshots);
-  ~ChromeOsAppInstallDialogParams();
-};
-
-// Defines the web dialog used for installing a web app.
-class WebAppInstallDialog : public SystemWebDialogDelegate {
- public:
-  WebAppInstallDialog(const WebAppInstallDialog&) = delete;
-  WebAppInstallDialog& operator=(const WebAppInstallDialog&) = delete;
-
-  // Creates and shows a new dialog for installing a web app. Returns true
-  // if a new dialog has been effectively created.
-  static bool Show(gfx::NativeWindow parent,
-                   ChromeOsAppInstallDialogParams params);
-
-  void OnDialogShown(content::WebUI* webui) override;
-
- protected:
-  explicit WebAppInstallDialog(mojom::DialogArgsPtr args);
-  ~WebAppInstallDialog() override;
-  bool ShouldShowCloseButton() const override;
-
- private:
-  mojom::DialogArgsPtr dialog_args_;
-};
-
-}  // namespace ash::web_app_install
-
-#endif  // CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_DIALOG_H_
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.cc b/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.cc
deleted file mode 100644
index 59bd618a..0000000
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.h"
-
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom.h"
-
-namespace ash::web_app_install {
-
-WebAppInstallPageHandler::WebAppInstallPageHandler(
-    mojom::DialogArgsPtr args,
-    mojo::PendingReceiver<ash::web_app_install::mojom::PageHandler>
-        pending_page_handler,
-    CloseDialogCallback close_dialog_callback)
-    : dialog_args_{std::move(args)},
-      receiver_{this, std::move(pending_page_handler)},
-      close_dialog_callback_{std::move(close_dialog_callback)} {}
-
-WebAppInstallPageHandler::~WebAppInstallPageHandler() = default;
-
-void WebAppInstallPageHandler::GetDialogArgs(GetDialogArgsCallback callback) {
-  std::move(callback).Run(dialog_args_ ? dialog_args_.Clone()
-                                       : mojom::DialogArgs::New());
-}
-
-void WebAppInstallPageHandler::CloseDialog() {
-  // The callback could be null if the close button is clicked a second time
-  // before the dialog closes.
-  if (close_dialog_callback_) {
-    std::move(close_dialog_callback_).Run();
-  }
-}
-
-}  // namespace ash::web_app_install
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.h b/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.h
deleted file mode 100644
index cbab6d3..0000000
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_page_handler.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_PAGE_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_PAGE_HANDLER_H_
-
-#include "base/functional/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install.mojom.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-
-namespace ash::web_app_install {
-
-// Handles communication from the chrome://web-app-install renderer process to
-// the browser process exposing various methods for the JS to invoke.
-class WebAppInstallPageHandler : public mojom::PageHandler {
- public:
-  using CloseDialogCallback = base::OnceCallback<void()>;
-  explicit WebAppInstallPageHandler(
-      mojom::DialogArgsPtr args,
-      mojo::PendingReceiver<mojom::PageHandler> pending_page_handler,
-      CloseDialogCallback close_dialog_callback);
-
-  WebAppInstallPageHandler(const WebAppInstallPageHandler&) = delete;
-  WebAppInstallPageHandler& operator=(const WebAppInstallPageHandler&) = delete;
-
-  ~WebAppInstallPageHandler() override;
-
-  // mojom::PageHandler:
-  void GetDialogArgs(GetDialogArgsCallback callback) override;
-  void CloseDialog() override;
-
- private:
-  mojom::DialogArgsPtr dialog_args_;
-  mojo::Receiver<mojom::PageHandler> receiver_;
-  CloseDialogCallback close_dialog_callback_;
-
-  base::WeakPtrFactory<WebAppInstallPageHandler> weak_ptr_factory_{this};
-};
-
-}  // namespace ash::web_app_install
-
-#endif  // CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.cc b/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.cc
deleted file mode 100644
index 452ed24..0000000
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h"
-
-#include "base/feature_list.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/webui_util.h"
-#include "chrome/common/webui_url_constants.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/web_app_install_resources.h"
-#include "chrome/grit/web_app_install_resources_map.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/common/url_constants.h"
-
-namespace ash::web_app_install {
-
-WebAppInstallDialogUI::WebAppInstallDialogUI(content::WebUI* web_ui)
-    : ui::MojoWebDialogUI(web_ui) {
-  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
-      Profile::FromWebUI(web_ui), chrome::kChromeUIWebAppInstallDialogHost);
-
-  static constexpr webui::LocalizedString kStrings[] = {
-      {"cancel", IDS_CANCEL},
-      {"install", IDS_INSTALL},
-      {"installing", IDS_OFFICE_INSTALL_PWA_INSTALLING_BUTTON},
-  };
-
-  source->AddLocalizedStrings(kStrings);
-  webui::SetupWebUIDataSource(
-      source,
-      base::make_span(kWebAppInstallResources, kWebAppInstallResourcesSize),
-      IDR_WEB_APP_INSTALL_MAIN_HTML);
-}
-
-WebAppInstallDialogUI::~WebAppInstallDialogUI() = default;
-
-void WebAppInstallDialogUI::SetDialogArgs(mojom::DialogArgsPtr args) {
-  dialog_args_ = std::move(args);
-}
-
-void WebAppInstallDialogUI::BindInterface(
-    mojo::PendingReceiver<mojom::PageHandlerFactory> pending_receiver) {
-  if (factory_receiver_.is_bound()) {
-    factory_receiver_.reset();
-  }
-  factory_receiver_.Bind(std::move(pending_receiver));
-}
-
-void WebAppInstallDialogUI::CreatePageHandler(
-    mojo::PendingReceiver<mojom::PageHandler> receiver) {
-  page_handler_ = std::make_unique<WebAppInstallPageHandler>(
-      std::move(dialog_args_), std::move(receiver),
-      base::BindOnce(&WebAppInstallDialogUI::CloseDialog,
-                     base::Unretained(this)));
-}
-
-void WebAppInstallDialogUI::CloseDialog() {
-  ui::MojoWebDialogUI::CloseDialog(base::Value::List());
-}
-
-WEB_UI_CONTROLLER_TYPE_IMPL(WebAppInstallDialogUI)
-
-bool WebAppInstallDialogUIConfig::IsWebUIEnabled(
-    content::BrowserContext* browser_context) {
-  return base::FeatureList::IsEnabled(
-      chromeos::features::kCrosWebAppInstallDialog);
-}
-
-WebAppInstallDialogUIConfig::WebAppInstallDialogUIConfig()
-    : DefaultWebUIConfig(content::kChromeUIScheme,
-                         chrome::kChromeUIWebAppInstallDialogHost) {}
-
-}  // namespace ash::web_app_install
diff --git a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h b/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h
deleted file mode 100644
index a8d3705..0000000
--- a/chrome/browser/ui/webui/ash/web_app_install/web_app_install_ui.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2023 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_UI_H_
-
-#include "chrome/browser/ui/webui/ash/web_app_install//web_app_install_page_handler.h"
-#include "content/public/browser/webui_config.h"
-#include "ui/web_dialogs/web_dialog_ui.h"
-
-namespace ash::web_app_install {
-
-// The WebUI for chrome://web-app-install-dialog, used for confirming web app
-// installation.
-class WebAppInstallDialogUI : public ui::MojoWebDialogUI,
-                              public mojom::PageHandlerFactory {
- public:
-  explicit WebAppInstallDialogUI(content::WebUI* web_ui);
-  WebAppInstallDialogUI(const WebAppInstallDialogUI&) = delete;
-  WebAppInstallDialogUI& operator=(const WebAppInstallDialogUI&) = delete;
-  ~WebAppInstallDialogUI() override;
-
-  void SetDialogArgs(mojom::DialogArgsPtr args);
-
-  // Instantiates the implementor of the mojom::PageHandlerFactory mojo
-  // interface passing the pending receiver that will be internally bound.
-  void BindInterface(mojo::PendingReceiver<mojom::PageHandlerFactory> receiver);
-
-  // mojom::PageHandlerFactory:
-  void CreatePageHandler(
-      mojo::PendingReceiver<mojom::PageHandler> pending_page_handler) override;
-
- private:
-  void CloseDialog();
-
-  mojom::DialogArgsPtr dialog_args_;
-  std::unique_ptr<WebAppInstallPageHandler> page_handler_;
-  mojo::Receiver<mojom::PageHandlerFactory> factory_receiver_{this};
-
-  WEB_UI_CONTROLLER_TYPE_DECL();
-};
-
-// WebUIConfig for chrome://web-app-install-dialog
-class WebAppInstallDialogUIConfig
-    : public content::DefaultWebUIConfig<WebAppInstallDialogUI> {
- public:
-  WebAppInstallDialogUIConfig();
-
-  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
-};
-
-}  // namespace ash::web_app_install
-
-#endif  // CHROME_BROWSER_UI_WEBUI_ASH_WEB_APP_INSTALL_WEB_APP_INSTALL_UI_H_
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 0fcca74..f45fb59 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1700998322-ce6dd7b53f31d6d19151a45fc41ddbf6f0318f55.profdata
+chrome-android32-main-1701063908-925cecbb2d23474d525b1a32bb668e1d70c98cbf.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 5b5577ec..e7a11f7 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1700998322-58eb7f25ad9827c3a024d5402ed823e0e0616a5c.profdata
+chrome-android64-main-1701063908-18d912fa2204d22b47b313932402d7f6f1ddc2db.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 359e8537..90d99f5 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1700978206-5768dc024463ee3c26ca94d5df67d5c364ed27f0.profdata
+chrome-linux-main-1701042811-6d94db0968f146523895c636fe5f39801b80056d.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 2315449..faaf4c1 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1701007083-aed66938e7104fac03aeff85d04c54767f5df9a6.profdata
+chrome-mac-arm-main-1701063908-c7b4fd8a3dafb163a928e7bb01d0bcdf89cae0a5.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index f8107f2..cf9733c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1700998322-d5fcaf23130f97293cedc22a8a3516d478a574cd.profdata
+chrome-mac-main-1701042811-346902c6218402b28223b42b2b5a7fc4cc3aee77.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 787f523..596a6f4 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1700998322-40e76fac3419cd57dcd8bc5abd35a7554aa6ca76.profdata
+chrome-win-arm64-main-1701042811-45974bdf6132c8d0bb83ef4a570f39940503fd64.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 2f2b110c..dac32464 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1700998322-144b63df6e5128034c7b548170f0624949e54b39.profdata
+chrome-win32-main-1701053839-750582b2a210945923f7a6ba3d9cbe2f5049a39a.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ce52112..59620ae7 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1700998322-f5d75546e053c4a16b52c241302bc911e5211b77.profdata
+chrome-win64-main-1701053839-6036593c049803bdc408176f211cbc3b6c46e5b6.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 5b1d8342..2ecbae6a 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -254,6 +254,7 @@
         "$root_gen_dir/ash/webui/file_manager/resources/file_manager_swa_resources.pak",
         "$root_gen_dir/ash/webui/file_manager/untrusted_resources/file_manager_untrusted_resources.pak",
         "$root_gen_dir/chrome/add_supervision_resources.pak",
+        "$root_gen_dir/chrome/app_install_resources.pak",
         "$root_gen_dir/chrome/arc_account_picker_resources.pak",
         "$root_gen_dir/chrome/assistant_optin_resources.pak",
         "$root_gen_dir/chrome/audio_resources.pak",
@@ -289,7 +290,6 @@
         "$root_gen_dir/chrome/sensor_info_resources.pak",
         "$root_gen_dir/chrome/supervision_resources.pak",
         "$root_gen_dir/chrome/vc_tray_tester_resources.pak",
-        "$root_gen_dir/chrome/web_app_install_resources.pak",
         "$root_gen_dir/chromeos/ash/ash_resources.pak",
         "$root_gen_dir/chromeos/chromeos_help_app_bundle_resources.pak",
         "$root_gen_dir/chromeos/chromeos_help_app_kids_magazine_bundle_resources.pak",
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index fe56c9a..dfa8ab1 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -322,6 +322,8 @@
     "chrome://account-migration-welcome";
 const char kChromeUIAddSupervisionHost[] = "add-supervision";
 const char kChromeUIAddSupervisionURL[] = "chrome://add-supervision/";
+const char kChromeUIAppInstallDialogHost[] = "app-install-dialog";
+const char kChromeUIAppInstallDialogURL[] = "chrome://app-install-dialog/";
 const char kChromeUIArcOverviewTracingHost[] = "arc-overview-tracing";
 const char kChromeUIArcOverviewTracingURL[] = "chrome://arc-overview-tracing/";
 const char kChromeUIArcPowerControlHost[] = "arc-power-control";
@@ -423,9 +425,6 @@
 const char kChromeUIVcTrayTesterURL[] = "chrome://vc-tray-tester";
 const char kChromeUIVmHost[] = "vm";
 const char kChromeUIVmUrl[] = "chrome://vm";
-const char kChromeUIWebAppInstallDialogHost[] = "web-app-install-dialog";
-const char kChromeUIWebAppInstallDialogURL[] =
-    "chrome://web-app-install-dialog/";
 
 const char kChromeUIUrgentPasswordExpiryNotificationHost[] =
     "urgent-password-expiry-notification";
@@ -438,40 +437,40 @@
   // Compares host instead of full URL for performance (the strings are
   // shorter).
   static const char* const kHosts[] = {
-    kChromeUIAccountManagerErrorHost,
-    kChromeUIAccountMigrationWelcomeHost,
-    kChromeUIAddSupervisionHost,
-    kChromeUIAssistantOptInHost,
-    kChromeUIBluetoothPairingHost,
-    kChromeUIBorealisCreditsHost,
-    kChromeUIBorealisInstallerHost,
-    kChromeUICertificateManagerHost,
-    kChromeUICloudUploadHost,
-    kChromeUICrostiniCreditsHost,
-    kChromeUICrostiniInstallerHost,
-    kChromeUICryptohomeHost,
-    kChromeUIDeviceEmulatorHost,
-    kChromeUIEmojiPickerHost,
-    kChromeUIInternetConfigDialogHost,
-    kChromeUIInternetDetailDialogHost,
-    kChromeUILockScreenNetworkHost,
-    kChromeUILockScreenStartReauthHost,
-    kChromeUIMobileSetupHost,
-    kChromeUIMultiDeviceSetupHost,
-    kChromeUINetworkHost,
-    kChromeUINotificationTesterHost,
-    kChromeUIOobeHost,
-    kChromeUIOSCreditsHost,
-    kChromeUIOSSettingsHost,
-    kChromeUIPasswordChangeHost,
-    kChromeUIPowerHost,
-    kChromeUISetTimeHost,
-    kChromeUISmbCredentialsHost,
-    kChromeUISmbShareHost,
-    kChromeUIVcTrayTesterHost,
-    kChromeUIWebAppInstallDialogHost,
+      kChromeUIAccountManagerErrorHost,
+      kChromeUIAccountMigrationWelcomeHost,
+      kChromeUIAddSupervisionHost,
+      kChromeUIAppInstallDialogHost,
+      kChromeUIAssistantOptInHost,
+      kChromeUIBluetoothPairingHost,
+      kChromeUIBorealisCreditsHost,
+      kChromeUIBorealisInstallerHost,
+      kChromeUICertificateManagerHost,
+      kChromeUICloudUploadHost,
+      kChromeUICrostiniCreditsHost,
+      kChromeUICrostiniInstallerHost,
+      kChromeUICryptohomeHost,
+      kChromeUIDeviceEmulatorHost,
+      kChromeUIEmojiPickerHost,
+      kChromeUIInternetConfigDialogHost,
+      kChromeUIInternetDetailDialogHost,
+      kChromeUILockScreenNetworkHost,
+      kChromeUILockScreenStartReauthHost,
+      kChromeUIMobileSetupHost,
+      kChromeUIMultiDeviceSetupHost,
+      kChromeUINetworkHost,
+      kChromeUINotificationTesterHost,
+      kChromeUIOobeHost,
+      kChromeUIOSCreditsHost,
+      kChromeUIOSSettingsHost,
+      kChromeUIPasswordChangeHost,
+      kChromeUIPowerHost,
+      kChromeUISetTimeHost,
+      kChromeUISmbCredentialsHost,
+      kChromeUISmbShareHost,
+      kChromeUIVcTrayTesterHost,
 #if BUILDFLAG(PLATFORM_CFM)
-    kCfmNetworkSettingsHost,
+      kCfmNetworkSettingsHost,
 #endif  // BUILDFLAG(PLATFORM_CFM)
   };
   for (const char* h : kHosts) {
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index a2101e0e..c94f8a4 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -291,6 +291,8 @@
 extern const char kChromeUIAccountMigrationWelcomeURL[];
 extern const char kChromeUIAddSupervisionHost[];
 extern const char kChromeUIAddSupervisionURL[];
+extern const char kChromeUIAppInstallDialogHost[];
+extern const char kChromeUIAppInstallDialogURL[];
 extern const char kChromeUIArcOverviewTracingHost[];
 extern const char kChromeUIArcOverviewTracingURL[];
 extern const char kChromeUIArcPowerControlHost[];
@@ -389,8 +391,6 @@
 extern const char kChromeUIVcTrayTesterHost[];
 extern const char kChromeUIVmHost[];
 extern const char kChromeUIVmUrl[];
-extern const char kChromeUIWebAppInstallDialogHost[];
-extern const char kChromeUIWebAppInstallDialogURL[];
 
 // Returns true if this web UI is part of the "system UI". Generally this is
 // UI that opens in a window (not a browser tab) and that on other operating
diff --git a/chrome/updater/win/ui/owner_draw_controls.h b/chrome/updater/win/ui/owner_draw_controls.h
index 76712a9..86c5d0ca 100644
--- a/chrome/updater/win/ui/owner_draw_controls.h
+++ b/chrome/updater/win/ui/owner_draw_controls.h
@@ -8,17 +8,16 @@
 #include <windows.h>
 
 #include "base/win/atl.h"
+
+#include <atltypes.h>
+
 #include "chrome/updater/win/ui/ui_constants.h"
-
-// These headers must be included after base/win/atl.h.
-#include "./atlapp.h"
-#include "./atltypes.h"
-
+#include "third_party/wtl/include/atlapp.h"
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wunused-but-set-variable"
 #pragma clang diagnostic ignored "-Wmissing-braces"
-#include "./atlctrls.h"
-#include "./atlframe.h"
+#include "third_party/wtl/include/atlctrls.h"
+#include "third_party/wtl/include/atlframe.h"
 #pragma clang diagnostic pop
 
 namespace updater::ui {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index e7910ca6..7d682a7 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-15690.0.0
\ No newline at end of file
+15691.0.0
\ No newline at end of file
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index f5fc119..4312cb6 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-121-6126.0-1700479769-benchmark-121.0.6146.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-121-6126.0-1700479769-benchmark-121.0.6148.0-r1-redacted.afdo.xz
diff --git a/clank b/clank
index bd44c4c..3e758b9 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit bd44c4cb90445bd38f361c33924f84a375e17f6f
+Subproject commit 3e758b938a904b48f4618173377ce9ad2c6ba408
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc
index a08c5817..05ff89b 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -2527,7 +2527,8 @@
           AutofillMetrics::FieldGlobalIdToHash64Bit(field.global_id()))
       .SetFieldSignature(HashFieldSignature(field.GetFieldSignature()))
       .SetFormControlType2(base::to_underlying(field.form_control_type))
-      .SetAutocompleteState(base::to_underlying(autocomplete_state));
+      .SetAutocompleteState(base::to_underlying(autocomplete_state))
+      .SetFieldLogEventCount(field_log_events.size());
 
   SetStatusVector(AutofillStatus::kIsFocusable, field.IsFocusable());
   SetStatusVector(AutofillStatus::kUserTypedIntoField,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
index 244a7c02..4bc6f153 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -8278,6 +8278,7 @@
           {UFIT::kAutocompleteStateName,
            base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
           {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
+          {UFIT::kFieldLogEventCountName, 1},
       };
 
       EXPECT_EQ(expected.size(), entry->metrics.size());
@@ -8358,6 +8359,7 @@
           i == 2 ? FieldFillingSkipReason::kNoFillableGroup
                  : FieldFillingSkipReason::kNotSkipped;
       DenseSet<AutofillStatus> autofill_status_vector;
+      int field_log_events_count = 0;
       if (i == 0) {
         autofill_status_vector = {
             AutofillStatus::kIsFocusable,
@@ -8370,14 +8372,17 @@
             AutofillStatus::kUserTypedIntoField,
             AutofillStatus::kFilledValueWasModified,
             AutofillStatus::kHadTypedOrFilledValueAtSubmission};
+        field_log_events_count = 4;
       } else if (i == 1) {
         autofill_status_vector = {
             AutofillStatus::kIsFocusable, AutofillStatus::kWasAutofillTriggered,
             AutofillStatus::kWasAutofilled,
             AutofillStatus::kHadTypedOrFilledValueAtSubmission};
+        field_log_events_count = 1;
       } else if (i == 2) {
         autofill_status_vector = {AutofillStatus::kIsFocusable,
                                   AutofillStatus::kWasAutofillTriggered};
+        field_log_events_count = 1;
       }
       std::map<std::string, int64_t> expected = {
           {UFIT::kFormSessionIdentifierName,
@@ -8394,6 +8399,7 @@
           {UFIT::kAutocompleteStateName,
            base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
           {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
+          {UFIT::kFieldLogEventCountName, field_log_events_count},
       };
       EXPECT_EQ(expected.size(), entry->metrics.size());
       for (const auto& [metric, value] : expected) {
@@ -8601,7 +8607,7 @@
       AutofillMetrics::AutocompleteState::kOff,
       AutofillMetrics::AutocompleteState::kValid,
       AutofillMetrics::AutocompleteState::kGarbage};
-
+  int field_log_events_count = 0;
   // Verify FieldInfo UKM event for every field.
   for (size_t i = 0; i < entries.size(); ++i) {
     SCOPED_TRACE(testing::Message() << i);
@@ -8613,6 +8619,7 @@
             : FieldPrediction::SOURCE_UNSPECIFIED;
     DenseSet<AutofillStatus> autofill_status_vector = {
         AutofillStatus::kIsFocusable};
+    field_log_events_count = 2;
     std::map<std::string, int64_t> expected = {
         {UFIT::kFormSessionIdentifierName,
          AutofillMetrics::FormGlobalIdToHash64Bit(form.global_id())},
@@ -8644,19 +8651,28 @@
           {UFIT::kHeuristicTypeDefaultName, heuristic_types[i]},
           {UFIT::kHeuristicTypeExperimentalName, heuristic_types[i]},
           {UFIT::kHeuristicTypeNextGenName, heuristic_types[i]},
+      }));
+      field_log_events_count += 5;
 #else
           {UFIT::kHeuristicTypeDefaultName, UNKNOWN_TYPE},
           {UFIT::kHeuristicTypeExperimentalName, UNKNOWN_TYPE},
           {UFIT::kHeuristicTypeNextGenName, UNKNOWN_TYPE},
-#endif
       }));
+      field_log_events_count += 2;
+#endif
+    } else {
+      ++field_log_events_count;
     }
     if (autocomplete_states[i] != AutofillMetrics::AutocompleteState::kOff) {
       expected.merge(std::map<std::string, int64_t>({
           {UFIT::kHtmlFieldTypeName, base::to_underlying(html_field_types[i])},
           {UFIT::kHtmlFieldModeName, base::to_underlying(HtmlFieldMode::kNone)},
       }));
+      ++field_log_events_count;
     }
+    expected.merge(std::map<std::string, int64_t>({
+        {UFIT::kFieldLogEventCountName, field_log_events_count},
+    }));
     EXPECT_EQ(expected.size(), entry->metrics.size());
     for (const auto& [metric, value] : expected) {
       test_ukm_recorder().ExpectEntryMetric(entry, metric, value);
@@ -8795,6 +8811,7 @@
         {UFIT::kAutocompleteStateName,
          base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
         {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
+        {UFIT::kFieldLogEventCountName, 1},
     };
 
     EXPECT_EQ(expected.size(), entry->metrics.size());
@@ -9095,6 +9112,7 @@
         {UFIT::kAutocompleteStateName,
          base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
         {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
+        {UFIT::kFieldLogEventCountName, 1},
     };
 
     EXPECT_EQ(expected.size(), entry->metrics.size());
@@ -9271,31 +9289,34 @@
     using UFIT = UkmFieldInfoType;
     const auto* const entry = entries[i];
     std::map<std::string, int64_t> expected = {
-      {UFIT::kFormSessionIdentifierName,
-       AutofillMetrics::FormGlobalIdToHash64Bit(form.global_id())},
-      {UFIT::kFieldSessionIdentifierName,
-       AutofillMetrics::FieldGlobalIdToHash64Bit(form.fields[i].global_id())},
-      {UFIT::kFieldSignatureName,
-       Collapse(CalculateFieldSignatureForField(form.fields[i])).value()},
-      {UFIT::kOverallTypeName, field_types[i]},
-      {UFIT::kSectionIdName, 1},
-      {UFIT::kTypeChangedByRationalizationName, false},
-      {UFIT::kFormControlType2Name, base::to_underlying(form_control_types[i])},
-      {UFIT::kAutocompleteStateName,
-       base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
-      {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
-      {UFIT::kHeuristicTypeName, field_types[i]},
-      {UFIT::kHeuristicTypeLegacyName, field_types[i]},
+        {UFIT::kFormSessionIdentifierName,
+         AutofillMetrics::FormGlobalIdToHash64Bit(form.global_id())},
+        {UFIT::kFieldSessionIdentifierName,
+         AutofillMetrics::FieldGlobalIdToHash64Bit(form.fields[i].global_id())},
+        {UFIT::kFieldSignatureName,
+         Collapse(CalculateFieldSignatureForField(form.fields[i])).value()},
+        {UFIT::kOverallTypeName, field_types[i]},
+        {UFIT::kSectionIdName, 1},
+        {UFIT::kTypeChangedByRationalizationName, false},
+        {UFIT::kFormControlType2Name,
+         base::to_underlying(form_control_types[i])},
+        {UFIT::kAutocompleteStateName,
+         base::to_underlying(AutofillMetrics::AutocompleteState::kNone)},
+        {UFIT::kAutofillStatusVectorName, autofill_status_vector.data()[0]},
+        {UFIT::kHeuristicTypeName, field_types[i]},
+        {UFIT::kHeuristicTypeLegacyName, field_types[i]},
 #if BUILDFLAG(USE_INTERNAL_AUTOFILL_PATTERNS)
-      {UFIT::kHeuristicTypeDefaultName, field_types[i]},
-      {UFIT::kHeuristicTypeExperimentalName, field_types[i]},
-      {UFIT::kHeuristicTypeNextGenName, field_types[i]},
+        {UFIT::kHeuristicTypeDefaultName, field_types[i]},
+        {UFIT::kHeuristicTypeExperimentalName, field_types[i]},
+        {UFIT::kHeuristicTypeNextGenName, field_types[i]},
+        {UFIT::kFieldLogEventCountName, 5},
 #else
-      {UFIT::kHeuristicTypeDefaultName, UNKNOWN_TYPE},
-      {UFIT::kHeuristicTypeExperimentalName, UNKNOWN_TYPE},
-      {UFIT::kHeuristicTypeNextGenName, UNKNOWN_TYPE},
+        {UFIT::kHeuristicTypeDefaultName, UNKNOWN_TYPE},
+        {UFIT::kHeuristicTypeExperimentalName, UNKNOWN_TYPE},
+        {UFIT::kHeuristicTypeNextGenName, UNKNOWN_TYPE},
+        {UFIT::kFieldLogEventCountName, 2},
 #endif
-      {UFIT::kRankInFieldSignatureGroupName, 1},
+        {UFIT::kRankInFieldSignatureGroupName, 1},
     };
 
     EXPECT_EQ(expected.size(), entry->metrics.size());
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 869d69c4..3c33bf6 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -1080,13 +1080,18 @@
     layer->SetOldestAcceptableFallback(
         viz::SurfaceId(frame_sink_id_, current_lsi));
   } else {
-    // `current_lsi` has caught up to `layer`. Allow the shell_surface to modify
-    // the surface layer bounds, clear the oldest fallback and disable stretch.
-    layer->SetShowSurface(viz::SurfaceId(frame_sink_id_, current_lsi),
-                          layer->bounds().size(), SK_ColorWHITE,
-                          cc::DeadlinePolicy::UseDefaultDeadline(),
-                          false /* stretch_content_to_fill_bounds */);
-    layer->SetOldestAcceptableFallback(viz::SurfaceId{});
+    viz::SurfaceId surface_id(frame_sink_id_, current_lsi);
+    // Update the surface only when the surface id changes, which indicates that
+    // the change needs to be synchronized due to size change or scale change.
+    if (!layer->GetSurfaceId() || *layer->GetSurfaceId() != surface_id) {
+      // `current_lsi` has caught up to `layer`. Allow the shell_surface to
+      // modify the surface layer bounds, clear the oldest fallback and disable
+      // stretch.
+      layer->SetShowSurface(surface_id, layer->bounds().size(), SK_ColorWHITE,
+                            cc::DeadlinePolicy::UseDefaultDeadline(),
+                            false /* stretch_content_to_fill_bounds */);
+      layer->SetOldestAcceptableFallback(viz::SurfaceId{});
+    }
   }
 }
 
diff --git a/components/exo/surface_tree_host.cc b/components/exo/surface_tree_host.cc
index 249452d..aa2881a 100644
--- a/components/exo/surface_tree_host.cc
+++ b/components/exo/surface_tree_host.cc
@@ -347,6 +347,9 @@
           : absl::make_optional(GetScaleFactor()),
       &frame);
 
+  // Update after resource is updated.
+  UpdateHostLayerOpacity();
+
   std::vector<GLbyte*> sync_tokens;
   // We track previously verified tokens and set them to be verified to avoid
   // the considerable overhead of flush verification in
@@ -437,14 +440,6 @@
   if (client_submits_surfaces_in_pixel_coordinates_) {
     SetScaleFactorTransform(GetScaleFactor());
   }
-  const bool fills_bounds_opaquely =
-      gfx::SizeF(bounds.size()) == root_surface_->content_size() &&
-      root_surface_->FillsBoundsOpaquely();
-  if (commit_target_layer == host_window_->layer()) {
-    host_window_->SetTransparent(!fills_bounds_opaquely);
-  } else if (commit_target_layer) {
-    commit_target_layer->SetFillsBoundsOpaquely(fills_bounds_opaquely);
-  }
 
   root_surface_origin_pixel_ = gfx::Point() - bounds.OffsetFromOrigin();
   gfx::Point root_surface_origin_dp =
@@ -463,6 +458,22 @@
   }
 }
 
+void SurfaceTreeHost::UpdateHostLayerOpacity() {
+  ui::Layer* commit_target_layer = GetCommitTargetLayer();
+
+  const gfx::Rect& bounds = root_surface_->surface_hierarchy_content_bounds();
+
+  const bool fills_bounds_opaquely =
+      gfx::SizeF(bounds.size()) == root_surface_->content_size() &&
+      root_surface_->FillsBoundsOpaquely();
+
+  if (commit_target_layer == host_window_->layer()) {
+    host_window_->SetTransparent(!fills_bounds_opaquely);
+  } else if (commit_target_layer) {
+    commit_target_layer->SetFillsBoundsOpaquely(fills_bounds_opaquely);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // SurfaceTreeHost, private:
 
diff --git a/components/exo/surface_tree_host.h b/components/exo/surface_tree_host.h
index 4a37bd5..ea8ab8e52 100644
--- a/components/exo/surface_tree_host.h
+++ b/components/exo/surface_tree_host.h
@@ -195,6 +195,10 @@
   // It also updates `root_surface_origin_` accordingly to the origin.
   void UpdateSurfaceLayerSizeAndRootSurfaceOrigin();
 
+  // Updates the host layer's opacity. This has to be called after root
+  // surface's resource is updated.
+  void UpdateHostLayerOpacity();
+
   bool client_submits_surfaces_in_pixel_coordinates() const {
     return client_submits_surfaces_in_pixel_coordinates_;
   }
diff --git a/components/exo/wayland/shell_unittest.cc b/components/exo/wayland/shell_unittest.cc
index 47a624d55..dcf2542 100644
--- a/components/exo/wayland/shell_unittest.cc
+++ b/components/exo/wayland/shell_unittest.cc
@@ -8,12 +8,17 @@
 #include <xdg-shell-client-protocol.h>
 #include <cstdint>
 
+#include "ash/host/ash_window_tree_host_platform.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
+#include "cc/trees/layer_tree_host.h"
 #include "components/exo/shell_surface_util.h"
 #include "components/exo/wayland/test/client_util.h"
 #include "components/exo/wayland/test/server_util.h"
 #include "components/exo/wayland/test/wayland_server_test.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/compositor/compositor.h"
+#include "ui/compositor/test/begin_main_frame_waiter.h"
 
 namespace exo::wayland {
 
@@ -413,4 +418,72 @@
   }
 }
 
+TEST_F(ShellWithClientTest, BufferCommitNoNeedsCommit) {
+  auto* ash_window_tree_host = static_cast<ash::AshWindowTreeHostPlatform*>(
+      ash::Shell::GetPrimaryRootWindow()->GetHost());
+  // The compositor may receive draw request upon X11's damage event, which
+  // results in commit request. The event is not important in this test, so
+  // simply ignore the damage rect event.
+  ash_window_tree_host->set_ignore_platform_damage_rect_for_test(true);
+  auto* compositor = ash_window_tree_host->compositor();
+
+  // Wait if the commit requests during initialization still exists.
+  if (compositor->host_for_testing()->CommitRequested()) {
+    ui::BeginMainFrameWaiter(compositor).Wait();
+  }
+
+  {
+    ui::BeginMainFrameWaiter waiter(compositor);
+    PostToClientAndWait([&](test::TestClient* client) {
+      ASSERT_TRUE(client->InitShmBufferFactory(800 * 100 * 4));
+      auto data = std::make_unique<ShellClientData>(client);
+      auto* data_ptr = data.get();
+      client->set_data(std::move(data));
+      data_ptr->CreateXdgToplevel();
+    });
+
+    // Make sure a commit never been received nor processed.
+    EXPECT_FALSE(waiter.begin_main_frame_received());
+    EXPECT_FALSE(compositor->host_for_testing()->CommitRequested());
+  }
+  {
+    ui::BeginMainFrameWaiter waiter(compositor);
+    PostToClientAndWait([&](test::TestClient* client) {
+      auto* data_ptr = client->GetDataAs<ShellClientData>();
+      data_ptr->CreateAndAttachBuffer({256, 256});
+      data_ptr->Commit();
+    });
+    // BeginMainFrame might have been already processed so check both
+    // condition.
+    EXPECT_TRUE(waiter.begin_main_frame_received() ||
+                compositor->host_for_testing()->CommitRequested());
+  }
+
+  if (compositor->host_for_testing()->CommitRequested()) {
+    ui::BeginMainFrameWaiter(compositor).Wait();
+  }
+
+  {
+    ui::BeginMainFrameWaiter waiter(compositor);
+    PostToClientAndWait([&](test::TestClient* client) {
+      auto* data_ptr = client->GetDataAs<ShellClientData>();
+      data_ptr->CreateAndAttachBuffer({256, 256});
+      data_ptr->Commit();
+    });
+    EXPECT_FALSE(waiter.begin_main_frame_received());
+    EXPECT_FALSE(compositor->host_for_testing()->CommitRequested());
+  }
+
+  {
+    ui::BeginMainFrameWaiter waiter(compositor);
+    PostToClientAndWait([&](test::TestClient* client) {
+      auto* data_ptr = client->GetDataAs<ShellClientData>();
+      data_ptr->CreateAndAttachBuffer({256, 128});
+      data_ptr->Commit();
+    });
+    EXPECT_TRUE(waiter.begin_main_frame_received() ||
+                compositor->host_for_testing()->CommitRequested());
+  }
+}
+
 }  // namespace exo::wayland
diff --git a/components/exo/wayland/test/test_wayland_client_thread.cc b/components/exo/wayland/test/test_wayland_client_thread.cc
index f26ec8b6..b076d41 100644
--- a/components/exo/wayland/test/test_wayland_client_thread.cc
+++ b/components/exo/wayland/test/test_wayland_client_thread.cc
@@ -109,6 +109,7 @@
 
 void TestWaylandClientThread::DoRun(base::OnceClosure closure) {
   std::move(closure).Run();
+  wl_display_flush(client_->display());
   wl_display_roundtrip(client_->display());
 }
 
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc
index 7a39a6d..7a1c648 100644
--- a/components/safe_browsing/core/common/features.cc
+++ b/components/safe_browsing/core/common/features.cc
@@ -68,10 +68,6 @@
              "DownloadBubble",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kDownloadBubbleV2,
-             "DownloadBubbleV2",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kDownloadTailoredWarnings,
              "DownloadTailoredWarnings",
              base::FEATURE_ENABLED_BY_DEFAULT);
@@ -367,7 +363,6 @@
     {&kClientSideDetectionTypeForceRequest, true},
     {&kDelayedWarnings, true},
     {&kDownloadBubble, true},
-    {&kDownloadBubbleV2, true},
     {&kDownloadTailoredWarnings, true},
     {&kEvaluateProtectedPasswordLengthMinimum, false},
     {&kExtensionTelemetryDisableOffstoreExtensions, true},
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h
index b30b9760..015063d 100644
--- a/components/safe_browsing/core/common/features.h
+++ b/components/safe_browsing/core/common/features.h
@@ -60,11 +60,6 @@
 // Whether to use download bubble instead of download shelf.
 BASE_DECLARE_FEATURE(kDownloadBubble);
 
-// The V2 of the download bubble, consisting of features that were not available
-// on the download shelf. This is only eligible to be enabled when
-// kDownloadBubble is already enabled.
-BASE_DECLARE_FEATURE(kDownloadBubbleV2);
-
 // The kill switch for download tailored warnings. The main control is on the
 // server-side.
 BASE_DECLARE_FEATURE(kDownloadTailoredWarnings);
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index a806166..a5fce16 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -243,6 +243,7 @@
     ui::TouchSelectionControllerClient* client) {
   DCHECK(client != &internal_client_);
   if (client == active_client_) {
+    GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
     active_client_ = &internal_client_;
     active_menu_client_ = this;
   }
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index 419da45..7af783f 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -994,6 +994,66 @@
             initial_selection_bounds_in_child_coords);
 }
 
+IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest,
+                       TouchSelectionDeactivatedAfterReload) {
+  const GURL main_url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(a)"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetPrimaryFrameTree()
+                            .root();
+  WaitForHitTestData(root->current_frame_host());
+
+  InitSelectionController(true);
+
+  {
+    // Load touch selection test page into iframe.
+    const GURL child_url(
+        embedded_test_server()->GetURL("b.com", "/touch_selection.html"));
+    EXPECT_TRUE(NavigateToURLFromRenderer(root->child_at(0), child_url));
+    FrameTreeNode* child = root->child_at(0);
+    WaitForHitTestData(child->current_frame_host());
+
+    // Find the location of some text in the iframe to select.
+    RenderWidgetHostViewChildFrame* child_view =
+        static_cast<RenderWidgetHostViewChildFrame*>(
+            child->current_frame_host()->GetRenderWidgetHost()->GetView());
+    gfx::PointF point_in_text;
+    JSONToPoint(EvalJs(child->current_frame_host(), "get_top_left_of_text()")
+                    .ExtractString(),
+                &point_in_text);
+    point_in_text.Offset(2.0 * kCharacterWidth, 0.5f * kCharacterHeight);
+    point_in_text = child_view->TransformPointToRootCoordSpaceF(point_in_text);
+
+    // Long press some text in the iframe to show selection handles.
+    selection_controller_client()->InitWaitForSelectionEvent(
+        ui::SELECTION_HANDLES_SHOWN);
+    SelectWithLongTap(gfx::Point(point_in_text.x(), point_in_text.y()),
+                      child_view);
+    selection_controller_client()->Wait();
+  }
+
+  // Touch selection handles and menu should be active.
+  EXPECT_EQ(
+      ui::TouchSelectionController::SELECTION_ACTIVE,
+      GetRenderWidgetHostViewAura()->selection_controller()->active_status());
+  EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+
+  {
+    // Reload web contents.
+    TestNavigationObserver reload_observer(shell()->web_contents());
+    shell()->web_contents()->GetController().Reload(
+        content::ReloadType::NORMAL, false /* check_for_repost */);
+    reload_observer.Wait();
+  }
+
+  // Touch selection handles and menu should be deactivated.
+  EXPECT_EQ(
+      ui::TouchSelectionController::INACTIVE,
+      GetRenderWidgetHostViewAura()->selection_controller()->active_status());
+  EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+}
+
 // Tests that tapping in a textfield brings up the insertion handle, but not the
 // quick menu, initially. Then, successive taps on the insertion handle toggle
 // the quick menu visibility.
diff --git a/content/browser/site_per_process_layout_browsertest.cc b/content/browser/site_per_process_layout_browsertest.cc
index a4c75dc7..9f5ccba 100644
--- a/content/browser/site_per_process_layout_browsertest.cc
+++ b/content/browser/site_per_process_layout_browsertest.cc
@@ -1780,8 +1780,16 @@
 // This test verifies that hiding an OOPIF in CSS will stop generating
 // compositor frames for the OOPIF and any nested OOPIFs inside it. This holds
 // even when the whole page is shown.
+#if BUILDFLAG(IS_MAC)
+// Flaky on Mac. https://crbug.com/1505297
+#define MAYBE_HiddenOOPIFWillNotGenerateCompositorFrames \
+  DISABLED_HiddenOOPIFWillNotGenerateCompositorFrames
+#else
+#define MAYBE_HiddenOOPIFWillNotGenerateCompositorFrames \
+  HiddenOOPIFWillNotGenerateCompositorFrames
+#endif
 IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTest,
-                       HiddenOOPIFWillNotGenerateCompositorFrames) {
+                       MAYBE_HiddenOOPIFWillNotGenerateCompositorFrames) {
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/frame_tree/page_with_two_frames.html"));
   ASSERT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/renderer/pepper/pepper_video_encoder_host.cc b/content/renderer/pepper/pepper_video_encoder_host.cc
index 34958e0e1..3920625 100644
--- a/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -328,7 +328,7 @@
     return encoder_last_error_;
 
   encoder_->RequestEncodingParametersChange(
-      media::Bitrate::ConstantBitrate(bitrate), framerate);
+      media::Bitrate::ConstantBitrate(bitrate), framerate, absl::nullopt);
 
   return PP_OK;
 }
diff --git a/content/renderer/pepper/video_encoder_shim.cc b/content/renderer/pepper/video_encoder_shim.cc
index 916e9280..69e31808 100644
--- a/content/renderer/pepper/video_encoder_shim.cc
+++ b/content/renderer/pepper/video_encoder_shim.cc
@@ -108,7 +108,8 @@
   void Encode(scoped_refptr<media::VideoFrame> frame, bool force_keyframe);
   void UseOutputBitstreamBuffer(media::BitstreamBuffer buffer, uint8_t* mem);
   void RequestEncodingParametersChange(const media::Bitrate& bitrate,
-                                       uint32_t framerate);
+                                       uint32_t framerate,
+                                       const absl::optional<gfx::Size>& size);
   void Stop();
 
  private:
@@ -259,13 +260,20 @@
 
 void VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange(
     const media::Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   // If this is changed to use variable bitrate encoding, change the mode check
   // to check that the mode matches the current mode.
   if (bitrate.mode() != media::Bitrate::Mode::kConstant) {
     NotifyErrorStatus(media::EncoderStatus::Codes::kEncoderUnsupportedConfig);
     return;
   }
+
+  if (size.has_value()) {
+    NotifyErrorStatus(media::EncoderStatus::Codes::kEncoderUnsupportedConfig);
+    return;
+  }
+
   framerate_ = framerate;
 
   uint32_t bitrate_kbit = bitrate.target_bps() / 1000;
@@ -454,14 +462,15 @@
 
 void VideoEncoderShim::RequestEncodingParametersChange(
     const media::Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK(RenderThreadImpl::current());
 
   media_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
           &VideoEncoderShim::EncoderImpl::RequestEncodingParametersChange,
-          base::Unretained(encoder_impl_.get()), bitrate, framerate));
+          base::Unretained(encoder_impl_.get()), bitrate, framerate, size));
 }
 
 void VideoEncoderShim::Destroy() {
diff --git a/content/renderer/pepper/video_encoder_shim.h b/content/renderer/pepper/video_encoder_shim.h
index 76b618a..ead3ab72 100644
--- a/content/renderer/pepper/video_encoder_shim.h
+++ b/content/renderer/pepper/video_encoder_shim.h
@@ -48,8 +48,10 @@
   void Encode(scoped_refptr<media::VideoFrame> frame,
               bool force_keyframe) override;
   void UseOutputBitstreamBuffer(media::BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const media::Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const media::Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
 
  private:
diff --git a/docs/linux/build_instructions.md b/docs/linux/build_instructions.md
index 0730a192..e6f4557 100644
--- a/docs/linux/build_instructions.md
+++ b/docs/linux/build_instructions.md
@@ -155,51 +155,80 @@
 
 #### Use reclient
 
-If you are a Google employee, do not follow the instructions below. See
-[go/chrome-linux-build#setup-remote-execution](http://go/chrome-linux-build#setup-remote-execution)
-instead.
-
-Google developed the
-[Remote Execution API](https://github.com/bazelbuild/remote-apis)
-client called [reclient](https://github.com/bazelbuild/reclient).
-
 *** note
-**Warning:** Following instruction is not ready to be used yet.
+**Warning:** If you are a Google employee, do not follow the instructions below.
+See [go/chrome-linux-build#setup-remote-execution](http://go/chrome-linux-build#setup-remote-execution)
+instead.
 ***
 
-If you would like to use `reclient`, install gcloud via
-https://cloud.google.com/sdk/docs/install, authorize with your account via
-https://cloud.google.com/sdk/docs/authorizing and specify your `rbe_instance`
-in .gclient like
+Chromium's build can be sped up significantly by using a remote execution system
+compatible with [REAPI](https://github.com/bazelbuild/remote-apis). This allows
+you to benefit from remote caching and executing many build actions in parallel
+on a shared cluster of workers.
+
+To get started, you need access to an REAPI-compatible backend. The following
+instructions assume that you received an invitation from Google to use
+Chromium's RBE service and were granted access to it. However, you are welcome
+to use any of the
+[other compatible backends](https://github.com/bazelbuild/remote-apis#servers),
+in which case you will have to adapt the following instructions regarding the
+authentication method, instance name, etc. to work with your backend.
+
+Chromium's build uses a client developed by Google called
+[reclient](https://github.com/bazelbuild/reclient) to remotely execute build
+actions. If you would like to use `reclient` with RBE, you'll first need to:
+
+1. [Install the gcloud CLI](https://cloud.google.com/sdk/docs/install). You can
+   pick any installation method from that page that works best for you.
+2. Run `gcloud auth login --update-adc` and login with your authorized
+   account. Ignore the message about the `--update-adc` flag being deprecated.
+
+Next, you'll have to specify your `rbe_instance` in your `.gclient`
+configuration to use the correct one for Chromium contributors:
+
 ```
 solutions = [
   {
     ...,
     "custom_vars": {
-      # e.g. <your instance> can be something like
-      # "projects/rbe-chromium-untrusted/instances/default_instance"
-      # if you are allowed to use Google's RBE backend.
-      "rbe_instance": <your instance>,
+      # This is the correct instance name for using Chromium's RBE service.
+      # You can only use it if you were granted access to it. If you use your
+      # own REAPI-compatible backend, you will need to change this accordingly
+      # to its requirements.
+      "rbe_instance": "projects/rbe-chromium-untrusted/instances/default_instance",
     },
   },
 ]
 ```
-and run `gclient sync`. Then, add the following GN args to your `args.gn`.
+
+and run `gclient sync`. This will regenerate the config files in
+`buildtools/reclient_cfgs` to use the `rbe_instance` that you just added to your
+`.gclient` file.
+
+Then, add the following GN args to your `args.gn`:
+
 ```
-use_remoteexec=true
-rbe_cfg_dir="../../buildtools/reclient_cfgs/linux"
+use_remoteexec = true
+rbe_cfg_dir = "../../buildtools/reclient_cfgs/linux"
 ```
 
+That's it. Remember to always use `autoninja` for building Chromium as described
+below, which handles the startup and shutdown of the reproxy daemon process
+that's required during the build, instead of directly invoking `ninja`.
+
 #### Use Goma (deprecated)
 
-Google developed the distributed compiler called
-[Goma](https://chromium.googlesource.com/infra/goma/client).
+*** note
+**Warning:** Goma is deprecated and Chromium will [remove support for building
+with Goma by end of January 2024](https://groups.google.com/a/chromium.org/g/chromium-dev/c/rajt7THxIng/m/ZoDB54wQBAAJ).
+***
 
-If you would like to use `Goma` provisioned by Google,
-please follow [Goma for Chromium contributors](https://chromium.googlesource.com/infra/goma/client/+/HEAD/doc/early-access-guide.md).
+Please use the above instructions for reclient instead. If you have any issues
+migrating to reclient, please reach out to chromium-dev@chromium.org so that we
+can address them before the shutdown.
 
-If you are a Google employee, see
-[go/building-chrome](https://goto.google.com/building-chrome) instead.
+If you need to refer to the older instructions for using Goma, you can still
+find them here: [Goma for Chromium contributors](https://chromium.googlesource.com/infra/goma/client/+/HEAD/doc/early-access-guide.md).
 
 #### Disable NaCl
 
diff --git a/docs/ui/views/overview.md b/docs/ui/views/overview.md
index e299757..a69fdcd 100644
--- a/docs/ui/views/overview.md
+++ b/docs/ui/views/overview.md
@@ -154,7 +154,7 @@
 NonClientFrameView.
 
 [BoxLayout]: https://cs.chromium.org/chromium/src/ui/views/layout/box_layout.h
-[BubbleDialogDelegateView]: https://cs.chromium.org/chromium/src/ui/views/bubble/bubble_dialog_delegate.h
+[BubbleDialogDelegateView]: https://cs.chromium.org/chromium/src/ui/views/bubble/bubble_dialog_delegate_view.h
 [ClientView]: https://cs.chromium.org/chromium/src/ui/views/window/client_view.h
 [DialogDelegate]: https://cs.chromium.org/chromium/src/ui/views/window/dialog_delegate.h
 [DialogDelegateView]: https://cs.chromium.org/chromium/src/ui/views/window/dialog_delegate.h
diff --git a/infra/config/generated/builders/build/android-build-perf-developer/gn-args.json b/infra/config/generated/builders/build/android-build-perf-developer/gn-args.json
index e9e9df8..c48c7c6d 100644
--- a/infra/config/generated/builders/build/android-build-perf-developer/gn-args.json
+++ b/infra/config/generated/builders/build/android-build-perf-developer/gn-args.json
@@ -3,12 +3,12 @@
     "builtin": {
       "gn_args": {
         "enable_nacl": false,
-        "enable_precompiled_headers": false,
         "is_component_build": true,
         "is_debug": true,
         "symbol_level": 2,
         "target_cpu": "arm64",
-        "target_os": "android"
+        "target_os": "android",
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/build-perf-android-siso/gn-args.json b/infra/config/generated/builders/build/build-perf-android-siso/gn-args.json
index d352ac6..f38aff6 100644
--- a/infra/config/generated/builders/build/build-perf-android-siso/gn-args.json
+++ b/infra/config/generated/builders/build/build-perf-android-siso/gn-args.json
@@ -8,7 +8,6 @@
         "debuggable_apks": false,
         "enable_dangling_raw_ptr_checks": true,
         "enable_dangling_raw_ptr_feature_flag": true,
-        "enable_precompiled_headers": false,
         "fail_on_android_expectations": true,
         "ffmpeg_branding": "Chrome",
         "is_component_build": false,
@@ -22,7 +21,8 @@
         "target_os": "android",
         "use_clang_coverage": true,
         "use_dummy_lastchange": true,
-        "use_remoteexec": false
+        "use_remoteexec": false,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/build-perf-linux-siso/gn-args.json b/infra/config/generated/builders/build/build-perf-linux-siso/gn-args.json
index 2107319..e4a13576 100644
--- a/infra/config/generated/builders/build/build-perf-linux-siso/gn-args.json
+++ b/infra/config/generated/builders/build/build-perf-linux-siso/gn-args.json
@@ -8,7 +8,6 @@
         "enable_backup_ref_ptr_feature_flag": true,
         "enable_dangling_raw_ptr_checks": true,
         "enable_dangling_raw_ptr_feature_flag": true,
-        "enable_precompiled_headers": false,
         "ffmpeg_branding": "Chrome",
         "is_component_build": false,
         "is_debug": false,
@@ -16,7 +15,8 @@
         "symbol_level": 0,
         "use_clang_coverage": true,
         "use_dummy_lastchange": true,
-        "use_remoteexec": false
+        "use_remoteexec": false,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/build-perf-windows-siso/gn-args.json b/infra/config/generated/builders/build/build-perf-windows-siso/gn-args.json
index bf07c2ec..62fa511b 100644
--- a/infra/config/generated/builders/build/build-perf-windows-siso/gn-args.json
+++ b/infra/config/generated/builders/build/build-perf-windows-siso/gn-args.json
@@ -6,7 +6,6 @@
         "dcheck_always_on": true,
         "enable_dangling_raw_ptr_checks": true,
         "enable_dangling_raw_ptr_feature_flag": true,
-        "enable_precompiled_headers": false,
         "enable_resource_allowlist_generation": false,
         "ffmpeg_branding": "Chrome",
         "is_component_build": false,
@@ -16,7 +15,8 @@
         "use_clang_coverage": true,
         "use_dummy_lastchange": true,
         "use_goma": false,
-        "use_remoteexec": false
+        "use_remoteexec": false,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/linux-build-perf-developer/gn-args.json b/infra/config/generated/builders/build/linux-build-perf-developer/gn-args.json
index 9efb567..befd649 100644
--- a/infra/config/generated/builders/build/linux-build-perf-developer/gn-args.json
+++ b/infra/config/generated/builders/build/linux-build-perf-developer/gn-args.json
@@ -3,10 +3,10 @@
     "builtin": {
       "gn_args": {
         "enable_nacl": false,
-        "enable_precompiled_headers": false,
         "is_component_build": true,
         "is_debug": true,
-        "symbol_level": 2
+        "symbol_level": 2,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/gn-args.json b/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/gn-args.json
index 985f8dc..06ca7c7 100644
--- a/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/gn-args.json
+++ b/infra/config/generated/builders/build/linux-chromeos-build-perf-siso/gn-args.json
@@ -8,7 +8,6 @@
         "enable_backup_ref_ptr_feature_flag": true,
         "enable_dangling_raw_ptr_checks": true,
         "enable_dangling_raw_ptr_feature_flag": true,
-        "enable_precompiled_headers": false,
         "ffmpeg_branding": "ChromeOS",
         "is_component_build": false,
         "is_debug": false,
@@ -19,7 +18,8 @@
         "use_cups": true,
         "use_dummy_lastchange": true,
         "use_goma": false,
-        "use_remoteexec": false
+        "use_remoteexec": false,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/mac-build-perf-developer/gn-args.json b/infra/config/generated/builders/build/mac-build-perf-developer/gn-args.json
index 9efb567..befd649 100644
--- a/infra/config/generated/builders/build/mac-build-perf-developer/gn-args.json
+++ b/infra/config/generated/builders/build/mac-build-perf-developer/gn-args.json
@@ -3,10 +3,10 @@
     "builtin": {
       "gn_args": {
         "enable_nacl": false,
-        "enable_precompiled_headers": false,
         "is_component_build": true,
         "is_debug": true,
-        "symbol_level": 2
+        "symbol_level": 2,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/mac-build-perf-siso/gn-args.json b/infra/config/generated/builders/build/mac-build-perf-siso/gn-args.json
index 863ac16e..84d8d97 100644
--- a/infra/config/generated/builders/build/mac-build-perf-siso/gn-args.json
+++ b/infra/config/generated/builders/build/mac-build-perf-siso/gn-args.json
@@ -7,7 +7,6 @@
         "enable_backup_ref_ptr_feature_flag": true,
         "enable_dangling_raw_ptr_checks": true,
         "enable_dangling_raw_ptr_feature_flag": true,
-        "enable_precompiled_headers": false,
         "ffmpeg_branding": "Chrome",
         "is_component_build": false,
         "is_debug": false,
@@ -16,7 +15,8 @@
         "target_cpu": "x64",
         "use_clang_coverage": true,
         "use_dummy_lastchange": true,
-        "use_remoteexec": false
+        "use_remoteexec": false,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/builders/build/win-build-perf-developer/gn-args.json b/infra/config/generated/builders/build/win-build-perf-developer/gn-args.json
index 9efb567..befd649 100644
--- a/infra/config/generated/builders/build/win-build-perf-developer/gn-args.json
+++ b/infra/config/generated/builders/build/win-build-perf-developer/gn-args.json
@@ -3,10 +3,10 @@
     "builtin": {
       "gn_args": {
         "enable_nacl": false,
-        "enable_precompiled_headers": false,
         "is_component_build": true,
         "is_debug": true,
-        "symbol_level": 2
+        "symbol_level": 2,
+        "use_siso": true
       }
     },
     "reproxy": {
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl
index 74845fbe..af49a6f 100644
--- a/infra/config/generated/testing/variants.pyl
+++ b/infra/config/generated/testing/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6149.0',
+    'description': 'Run with ash-chrome version 121.0.6151.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6149.0',
-          'revision': 'version:121.0.6149.0',
+          'location': 'lacros_version_skew_tests_v121.0.6151.0',
+          'revision': 'version:121.0.6151.0',
         },
       ],
     },
diff --git a/infra/config/gn_args/gn_args.star b/infra/config/gn_args/gn_args.star
index a28f166..f5b88352 100644
--- a/infra/config/gn_args/gn_args.star
+++ b/infra/config/gn_args/gn_args.star
@@ -910,8 +910,7 @@
 gn_args.config(
     "siso",
     args = {
-        # TODO: b/311110622 - Switch to use_siso=true.
-        "enable_precompiled_headers": False,
+        "use_siso": True,
     },
 )
 
diff --git a/infra/config/targets/lacros-version-skew-variants.json b/infra/config/targets/lacros-version-skew-variants.json
index f974e845..8e1d396 100644
--- a/infra/config/targets/lacros-version-skew-variants.json
+++ b/infra/config/targets/lacros-version-skew-variants.json
@@ -1,16 +1,16 @@
 {
   "LACROS_VERSION_SKEW_CANARY": {
     "args": [
-      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+      "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
     ],
-    "description": "Run with ash-chrome version 121.0.6149.0",
+    "description": "Run with ash-chrome version 121.0.6151.0",
     "identifier": "Lacros version skew testing ash canary",
     "swarming": {
       "cipd_packages": [
         {
           "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-          "location": "lacros_version_skew_tests_v121.0.6149.0",
-          "revision": "version:121.0.6149.0"
+          "location": "lacros_version_skew_tests_v121.0.6151.0",
+          "revision": "version:121.0.6151.0"
         }
       ]
     }
diff --git a/ios_internal b/ios_internal
index c55e94d..df56fdc 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit c55e94d4564fb697d3d83fe9fcbafaffce2e139e
+Subproject commit df56fdc8c9370dae4b8e7fc0f07d8c8b5a74d6b5
diff --git a/media/cast/encoding/external_video_encoder.cc b/media/cast/encoding/external_video_encoder.cc
index 7e605b4..534c0dc 100644
--- a/media/cast/encoding/external_video_encoder.cc
+++ b/media/cast/encoding/external_video_encoder.cc
@@ -179,7 +179,7 @@
       // uint32_t bitrates
       video_encode_accelerator_->RequestEncodingParametersChange(
           Bitrate::ConstantBitrate(base::saturated_cast<uint32_t>(bit_rate)),
-          static_cast<uint32_t>(max_frame_rate_ + 0.5));
+          static_cast<uint32_t>(max_frame_rate_ + 0.5), absl::nullopt);
     }
   }
 
diff --git a/media/fuchsia/video/fuchsia_video_encode_accelerator.cc b/media/fuchsia/video/fuchsia_video_encode_accelerator.cc
index 5c7d1c8..0ac8323 100644
--- a/media/fuchsia/video/fuchsia_video_encode_accelerator.cc
+++ b/media/fuchsia/video/fuchsia_video_encode_accelerator.cc
@@ -514,7 +514,8 @@
 
 void FuchsiaVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   // TODO(crbug.com/1373298): Implement RequestEncodingParameterChange.
   NOTIMPLEMENTED();
 }
diff --git a/media/fuchsia/video/fuchsia_video_encode_accelerator.h b/media/fuchsia/video/fuchsia_video_encode_accelerator.h
index 48bfabac..edd3f245 100644
--- a/media/fuchsia/video/fuchsia_video_encode_accelerator.h
+++ b/media/fuchsia/video/fuchsia_video_encode_accelerator.h
@@ -43,8 +43,10 @@
                   std::unique_ptr<MediaLog> media_log) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   bool IsFlushSupported() override;
   bool IsGpuFrameResizeSupported() override;
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 19890468..d8a9ce1 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -385,8 +385,8 @@
 
   if (is_win || use_vaapi) {
     sources += [
-      "vp9_svc_layers.cc",
-      "vp9_svc_layers.h",
+      "vp9_svc_layers_stateful.cc",
+      "vp9_svc_layers_stateful.h",
     ]
     configs += [ "//third_party/libvpx:libvpx_config" ]
     deps += [
@@ -653,7 +653,7 @@
   }
 
   if (is_win || use_vaapi) {
-    sources += [ "vp9_svc_layers_unittest.cc" ]
+    sources += [ "vp9_svc_layers_stateful_unittest.cc" ]
   }
 }
 
diff --git a/media/gpu/android/android_video_encode_accelerator.cc b/media/gpu/android/android_video_encode_accelerator.cc
index 78507d6..be656fa1 100644
--- a/media/gpu/android/android_video_encode_accelerator.cc
+++ b/media/gpu/android/android_video_encode_accelerator.cc
@@ -274,7 +274,8 @@
 
 void AndroidVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   // If this is changed to use variable bitrate encoding, change the mode check
   // to check that the mode matches the current mode.
   if (bitrate.mode() != Bitrate::Mode::kConstant) {
@@ -284,6 +285,11 @@
              base::NumberToString(static_cast<int>(bitrate.mode()))});
     return;
   }
+  if (size.has_value()) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update output frame size is not supported"});
+    return;
+  }
   DVLOG(3) << __PRETTY_FUNCTION__ << ": bitrate: " << bitrate.ToString()
            << ", framerate: " << framerate;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/media/gpu/android/android_video_encode_accelerator.h b/media/gpu/android/android_video_encode_accelerator.h
index a908e514..4463016 100644
--- a/media/gpu/android/android_video_encode_accelerator.h
+++ b/media/gpu/android/android_video_encode_accelerator.h
@@ -50,8 +50,10 @@
                   std::unique_ptr<MediaLog> media_log) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
 
  private:
diff --git a/media/gpu/android/ndk_video_encode_accelerator.cc b/media/gpu/android/ndk_video_encode_accelerator.cc
index b49727b6..9c95c2ee 100644
--- a/media/gpu/android/ndk_video_encode_accelerator.cc
+++ b/media/gpu/android/ndk_video_encode_accelerator.cc
@@ -345,8 +345,15 @@
 
 void NdkVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (size.has_value()) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update output frame size is not supported"});
+    return;
+  }
+
   MediaFormatPtr format(AMediaFormat_new());
 
   if (effective_framerate_ != framerate)
diff --git a/media/gpu/android/ndk_video_encode_accelerator.h b/media/gpu/android/ndk_video_encode_accelerator.h
index a037471c..22c11984 100644
--- a/media/gpu/android/ndk_video_encode_accelerator.h
+++ b/media/gpu/android/ndk_video_encode_accelerator.h
@@ -50,8 +50,10 @@
                   std::unique_ptr<MediaLog> media_log) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   bool IsFlushSupported() override;
 
diff --git a/media/gpu/mac/vt_video_encode_accelerator_mac.cc b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
index 639fad0..f683868 100644
--- a/media/gpu/mac/vt_video_encode_accelerator_mac.cc
+++ b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
@@ -520,10 +520,22 @@
 
 void VTVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
-  DVLOG(3) << __func__ << ": bitrate=" << bitrate.ToString()
-           << ": framerate=" << framerate;
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
+  std::ostringstream parameters_description;
+  parameters_description << ": bitrate=" << bitrate.ToString()
+                         << ": framerate=" << framerate;
+  if (size.has_value()) {
+    parameters_description << ": frame size=" << size->width() << "x"
+                           << size->height();
+  }
+  DVLOG(3) << __func__ << parameters_description.str();
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (size.has_value()) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update output frame size is not supported"});
+    return;
+  }
 
   if (!compression_session_) {
     NotifyErrorStatus(
@@ -723,7 +735,7 @@
     return false;
   }
 
-  RequestEncodingParametersChange(bitrate_, frame_rate_);
+  RequestEncodingParametersChange(bitrate_, frame_rate_, absl::nullopt);
   return true;
 }
 
diff --git a/media/gpu/mac/vt_video_encode_accelerator_mac.h b/media/gpu/mac/vt_video_encode_accelerator_mac.h
index 663f36a..81b7bf8 100644
--- a/media/gpu/mac/vt_video_encode_accelerator_mac.h
+++ b/media/gpu/mac/vt_video_encode_accelerator_mac.h
@@ -44,8 +44,10 @@
                   std::unique_ptr<MediaLog> media_log = nullptr) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   void Flush(FlushCallback flush_callback) override;
   bool IsFlushSupported() override;
diff --git a/media/gpu/test/video_encoder/video_encoder_client.cc b/media/gpu/test/video_encoder/video_encoder_client.cc
index 18006c4..40d63c7 100644
--- a/media/gpu/test/video_encoder/video_encoder_client.cc
+++ b/media/gpu/test/video_encoder/video_encoder_client.cc
@@ -609,7 +609,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_client_sequence_checker_);
   DVLOGF(4);
   aligned_data_helper_->UpdateFrameRate(framerate);
-  encoder_->RequestEncodingParametersChange(bitrate, framerate);
+  encoder_->RequestEncodingParametersChange(bitrate, framerate, absl::nullopt);
   base::AutoLock auto_lcok(stats_lock_);
   current_stats_.framerate = framerate;
 }
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 33fc633..2ec9dda 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -375,8 +375,10 @@
   }
 
   RequestEncodingParametersChangeTask(
-      config.bitrate, config.initial_framerate.value_or(
-                          VideoEncodeAccelerator::kDefaultFramerate));
+      config.bitrate,
+      config.initial_framerate.value_or(
+          VideoEncodeAccelerator::kDefaultFramerate),
+      absl::nullopt);
 
   // input_frame_size_ is the size of input_config of |image_processor_|.
   // On native_input_mode_, since the passed size in RequireBitstreamBuffers()
@@ -587,14 +589,15 @@
 
 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_);
 
   encoder_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
           &V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask,
-          weak_this_, bitrate, framerate));
+          weak_this_, bitrate, framerate, size));
 }
 
 void V4L2VideoEncodeAccelerator::Destroy() {
@@ -1610,10 +1613,17 @@
 
 void V4L2VideoEncodeAccelerator::RequestEncodingParametersChangeTask(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
-  if (current_bitrate_ == bitrate && current_framerate_ == framerate)
+  if (size.has_value()) {
+    SetErrorState({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                   "Update output frame size is not supported"});
     return;
+  }
+  if (current_bitrate_ == bitrate && current_framerate_ == framerate) {
+    return;
+  }
 
   VLOGF(2) << "bitrate=" << bitrate.ToString() << ", framerate=" << framerate;
   if (bitrate.mode() != current_bitrate_.mode()) {
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
index 37bb494..acb76d1 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -59,8 +59,10 @@
                   std::unique_ptr<MediaLog> media_log) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   void Flush(FlushCallback flush_callback) override;
   bool IsFlushSupported() override;
@@ -197,8 +199,10 @@
   void MaybeFlushImageProcessor();
 
   // Change encoding parameters.
-  void RequestEncodingParametersChangeTask(const Bitrate& bitrate,
-                                           uint32_t framerate);
+  void RequestEncodingParametersChangeTask(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size);
 
   // Do several initializations (e.g. set up format) on |encoder_task_runner_|.
   void InitializeTask(const Config& config);
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
index a128b37..83db6acc 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -51,7 +51,7 @@
 #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h"
 #include "media/gpu/vp8_reference_frame_vector.h"
 #include "media/gpu/vp9_reference_frame_vector.h"
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 
 namespace media {
 
@@ -995,7 +995,8 @@
 
 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_);
 
   VideoBitrateAllocation allocation;
@@ -1004,27 +1005,34 @@
       FROM_HERE,
       base::BindOnce(
           &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask,
-          encoder_weak_this_, allocation, framerate));
+          encoder_weak_this_, allocation, framerate, size));
 }
 
 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange(
     const VideoBitrateAllocation& bitrate_allocation,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_);
 
   encoder_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
           &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask,
-          encoder_weak_this_, bitrate_allocation, framerate));
+          encoder_weak_this_, bitrate_allocation, framerate, size));
 }
 
 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
     VideoBitrateAllocation bitrate_allocation,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_);
   DCHECK_NE(state_, kUninitialized);
 
+  if (size.has_value()) {
+    NotifyError({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                 "Update output frame size is not supported"});
+    return;
+  }
   if (!encoder_->UpdateRates(bitrate_allocation, framerate)) {
     VLOGF(1) << "Failed to update rates to " << bitrate_allocation.GetSumBps()
              << " " << framerate;
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.h b/media/gpu/vaapi/vaapi_video_encode_accelerator.h
index dcdcae5..a257db91 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.h
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.h
@@ -53,11 +53,14 @@
                   std::unique_ptr<MediaLog> media_log) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void RequestEncodingParametersChange(
       const VideoBitrateAllocation& bitrate_allocation,
-      uint32_t framerate) override;
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   void Flush(FlushCallback flush_callback) override;
   bool IsFlushSupported() override;
@@ -123,7 +126,8 @@
 
   void RequestEncodingParametersChangeTask(
       VideoBitrateAllocation bitrate_allocation,
-      uint32_t framerate);
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size);
 
   void DestroyTask();
   void FlushTask(FlushCallback flush_callback);
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
index a7d89112..abcc301 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator_unittest.cc
@@ -21,7 +21,7 @@
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h"
 #include "media/gpu/vp9_picture.h"
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 #include "media/video/fake_gpu_memory_buffer.h"
 #include "media/video/video_encode_accelerator.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
index 2048c93..2850988a 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
+++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
@@ -18,7 +18,7 @@
 #include "media/gpu/macros.h"
 #include "media/gpu/vaapi/vaapi_common.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 #include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
 
 namespace media {
@@ -242,8 +242,9 @@
         return false;
       }
     }
-    if (num_spatial_layers > VP9SVCLayers::kMaxSpatialLayers ||
-        num_temporal_layers > VP9SVCLayers::kMaxSupportedTemporalLayers) {
+    if (num_spatial_layers > VP9SVCLayersStateful::kMaxSpatialLayers ||
+        num_temporal_layers >
+            VP9SVCLayersStateful::kMaxSupportedTemporalLayers) {
       VLOGF(1) << "Unsupported amount of spatial/temporal layers: "
                << ", Spatial layer number: " << num_spatial_layers
                << ", Temporal layer number: " << num_temporal_layers;
@@ -259,8 +260,8 @@
       spatial_layer_resolutions.emplace_back(
           gfx::Size(spatial_layer.width, spatial_layer.height));
     }
-    svc_layers_ = std::make_unique<VP9SVCLayers>(config.spatial_layers,
-                                                 config.inter_layer_pred);
+    svc_layers_ = std::make_unique<VP9SVCLayersStateful>(
+        config.spatial_layers, config.inter_layer_pred);
 
     current_params_.error_resilident_mode = true;
   }
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
index fb661c1..7ef22321 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
+++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h
@@ -23,7 +23,7 @@
 
 namespace media {
 class VaapiWrapper;
-class VP9SVCLayers;
+class VP9SVCLayersStateful;
 
 // Wrapper for the libVPX VP9 rate controller that allows us to override methods
 // for unit testing.
@@ -129,7 +129,7 @@
   EncodeParams current_params_;
 
   Vp9ReferenceFrameVector reference_frames_;
-  std::unique_ptr<VP9SVCLayers> svc_layers_;
+  std::unique_ptr<VP9SVCLayersStateful> svc_layers_;
 
   absl::optional<std::pair<VideoBitrateAllocation, uint32_t>>
       pending_update_rates_;
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
index d28a362..1eb237a 100644
--- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
+++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
@@ -20,7 +20,7 @@
 #include "media/gpu/gpu_video_encode_accelerator_helpers.h"
 #include "media/gpu/vaapi/vaapi_common.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -469,7 +469,7 @@
                   bitrate_allocation ||
               encoder_->current_params_.framerate != framerate);
   // Since the request is pended, this is always successful and no call happens
-  // to VP9SVCLayers and RateControl.
+  // to VP9SVCLayersStateful and RateControl.
   EXPECT_TRUE(encoder_->UpdateRates(bitrate_allocation, framerate));
   EXPECT_TRUE(encoder_->pending_update_rates_.has_value());
 
@@ -515,8 +515,10 @@
     SVCInterLayerPredMode inter_layer_pred,
     size_t num_spatial_layers,
     size_t num_temporal_layers) {
-  ASSERT_TRUE(num_temporal_layers <= VP9SVCLayers::kMaxSupportedTemporalLayers);
-  ASSERT_TRUE(num_spatial_layers <= VP9SVCLayers::kMaxSupportedTemporalLayers);
+  ASSERT_TRUE(num_temporal_layers <=
+              VP9SVCLayersStateful::kMaxSupportedTemporalLayers);
+  ASSERT_TRUE(num_spatial_layers <=
+              VP9SVCLayersStateful::kMaxSupportedTemporalLayers);
   const auto spatial_layer_resolutions =
       GetDefaultSpatialLayerResolutions(num_spatial_layers);
   auto update_rates_and_encode = [this, inter_layer_pred, num_spatial_layers,
@@ -700,7 +702,7 @@
   // that it has non-zero bitrate up to the maximum supported temporal layers.
   const VideoBitrateAllocation kDefaultBitrateAllocation =
       AllocateDefaultBitrateForTesting(
-          num_spatial_layers, VP9SVCLayers::kMaxSupportedTemporalLayers,
+          num_spatial_layers, VP9SVCLayersStateful::kMaxSupportedTemporalLayers,
           kDefaultVideoEncodeAcceleratorConfig.bitrate);
   const std::vector<gfx::Size> kDefaultSpatialLayers =
       GetDefaultSpatialLayerResolutions(num_spatial_layers);
diff --git a/media/gpu/vp9_svc_layers.cc b/media/gpu/vp9_svc_layers_stateful.cc
similarity index 91%
rename from media/gpu/vp9_svc_layers.cc
rename to media/gpu/vp9_svc_layers_stateful.cc
index 2b097aa..e89856f1 100644
--- a/media/gpu/vp9_svc_layers.cc
+++ b/media/gpu/vp9_svc_layers_stateful.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 
 #include <bitset>
 
@@ -14,14 +14,16 @@
 
 namespace media {
 namespace {
-static_assert(VideoBitrateAllocation::kMaxTemporalLayers >=
-                  VP9SVCLayers::kMaxSupportedTemporalLayers,
-              "VP9SVCLayers and VideoBitrateAllocation are dimensionally "
-              "inconsistent.");
-static_assert(VideoBitrateAllocation::kMaxSpatialLayers >=
-                  VP9SVCLayers::kMaxSpatialLayers,
-              "VP9SVCLayers and VideoBitrateAllocation are dimensionally "
-              "inconsistent.");
+static_assert(
+    VideoBitrateAllocation::kMaxTemporalLayers >=
+        VP9SVCLayersStateful::kMaxSupportedTemporalLayers,
+    "VP9SVCLayersStateful and VideoBitrateAllocation are dimensionally "
+    "inconsistent.");
+static_assert(
+    VideoBitrateAllocation::kMaxSpatialLayers >=
+        VP9SVCLayersStateful::kMaxSpatialLayers,
+    "VP9SVCLayersStateful and VideoBitrateAllocation are dimensionally "
+    "inconsistent.");
 
 enum FrameFlags : uint8_t {
   kNone = 0,
@@ -41,7 +43,7 @@
 }
 }  // namespace
 
-struct VP9SVCLayers::FrameConfig {
+struct VP9SVCLayersStateful::FrameConfig {
   FrameConfig(size_t layer_index,
               FrameFlags first,
               FrameFlags second,
@@ -51,9 +53,9 @@
         temporal_up_switch_(temporal_up_switch) {}
   FrameConfig() = delete;
 
-  // VP9SVCLayers uses 2 reference frame slots for each spatial layer, and
-  // totally uses up to 6 reference frame slots. SL0 uses the first two (0, 1)
-  // slots, SL1 uses middle two (2, 3) slots, and SL2 uses last two (4, 5)
+  // VP9SVCLayersStateful uses 2 reference frame slots for each spatial layer,
+  // and totally uses up to 6 reference frame slots. SL0 uses the first two (0,
+  // 1) slots, SL1 uses middle two (2, 3) slots, and SL2 uses last two (4, 5)
   // slots.
   std::vector<uint8_t> GetRefFrameIndices(
       size_t spatial_idx,
@@ -102,9 +104,9 @@
 namespace {
 // GetTemporalLayersReferencePattern() constructs the
 // following temporal layers.
-std::vector<VP9SVCLayers::FrameConfig> GetTemporalLayersReferencePattern(
-    size_t num_temporal_layers) {
-  using FrameConfig = VP9SVCLayers::FrameConfig;
+std::vector<VP9SVCLayersStateful::FrameConfig>
+GetTemporalLayersReferencePattern(size_t num_temporal_layers) {
+  using FrameConfig = VP9SVCLayersStateful::FrameConfig;
   switch (num_temporal_layers) {
     case 1:
       // In this case, the number of spatial layers must great than 1.
@@ -137,8 +139,9 @@
 }
 }  // namespace
 
-VP9SVCLayers::VP9SVCLayers(const std::vector<SpatialLayer>& spatial_layers,
-                           SVCInterLayerPredMode inter_layer_pred)
+VP9SVCLayersStateful::VP9SVCLayersStateful(
+    const std::vector<SpatialLayer>& spatial_layers,
+    SVCInterLayerPredMode inter_layer_pred)
     : num_temporal_layers_(spatial_layers[0].num_of_temporal_layers),
       temporal_layers_reference_pattern_(
           GetTemporalLayersReferencePattern(num_temporal_layers_)),
@@ -156,10 +159,10 @@
   CHECK_LE(spatial_layer_resolutions_.size(), kMaxSpatialLayers);
 }
 
-VP9SVCLayers::~VP9SVCLayers() = default;
+VP9SVCLayersStateful::~VP9SVCLayersStateful() = default;
 
-bool VP9SVCLayers::UpdateEncodeJob(bool is_key_frame_requested,
-                                   size_t kf_period_frames) {
+bool VP9SVCLayersStateful::UpdateEncodeJob(bool is_key_frame_requested,
+                                           size_t kf_period_frames) {
   if (force_key_frame_ || is_key_frame_requested) {
     frame_num_ = 0;
     spatial_idx_ = 0;
@@ -175,7 +178,7 @@
   return frame_num_ == 0 && spatial_idx_ == 0;
 }
 
-bool VP9SVCLayers::MaybeUpdateActiveLayer(
+bool VP9SVCLayersStateful::MaybeUpdateActiveLayer(
     VideoBitrateAllocation* bitrate_allocation) {
   // Don't update active layer if current picture haven't completed SVC
   // encoding. Since the |spatial_idx_| is updated in the beginning of next
@@ -319,7 +322,7 @@
   return true;
 }
 
-void VP9SVCLayers::FillUsedRefFramesAndMetadata(
+void VP9SVCLayersStateful::FillUsedRefFramesAndMetadata(
     VP9Picture* picture,
     std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used) {
   DCHECK(picture->frame_hdr);
@@ -362,7 +365,7 @@
 
   if (spatial_idx_ == 0)
     pattern_index_ = (pattern_index_ + 1) % temporal_pattern_size_;
-  const VP9SVCLayers::FrameConfig& temporal_layers_config =
+  const VP9SVCLayersStateful::FrameConfig& temporal_layers_config =
       temporal_layers_reference_pattern_[pattern_index_];
 
   // Set the slots in reference frame pool that will be updated.
@@ -404,7 +407,7 @@
   spatial_idx_++;
 }
 
-void VP9SVCLayers::FillVp9MetadataForEncoding(
+void VP9SVCLayersStateful::FillVp9MetadataForEncoding(
     Vp9Metadata* metadata,
     const std::vector<uint8_t>& reference_frame_indices) const {
   metadata->end_of_picture =
@@ -425,7 +428,7 @@
     metadata->spatial_layer_resolutions = active_spatial_layer_resolutions_;
     // |begin_active_layer_| and |end_active_layer_| are less than
     // |spatial_layer_resolutions_.size()|, which is
-    // VP9SVCLayers::kMaxSpatialLayers at most.
+    // VP9SVCLayersStateful::kMaxSpatialLayers at most.
     metadata->begin_active_spatial_layer_index =
         base::checked_cast<uint8_t>(begin_active_layer_);
     metadata->end_active_spatial_layer_index =
@@ -479,7 +482,7 @@
 
 // Use current pattern index to update the reference frame's pattern index,
 // this is used to calculate |p_diffs|.
-void VP9SVCLayers::UpdateRefFramesPatternIndex(
+void VP9SVCLayersStateful::UpdateRefFramesPatternIndex(
     const std::vector<uint8_t>& refresh_frame_indices) {
   for (const uint8_t i : refresh_frame_indices)
     pattern_index_of_ref_frames_slots_[i] = pattern_index_;
diff --git a/media/gpu/vp9_svc_layers.h b/media/gpu/vp9_svc_layers_stateful.h
similarity index 85%
rename from media/gpu/vp9_svc_layers.h
rename to media/gpu/vp9_svc_layers_stateful.h
index 852b3c7..9fcbb6e 100644
--- a/media/gpu/vp9_svc_layers.h
+++ b/media/gpu/vp9_svc_layers_stateful.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef MEDIA_GPU_VP9_SVC_LAYERS_H_
-#define MEDIA_GPU_VP9_SVC_LAYERS_H_
+#ifndef MEDIA_GPU_VP9_SVC_LAYERS_STATEFUL_H_
+#define MEDIA_GPU_VP9_SVC_LAYERS_STATEFUL_H_
 
 #include <stdint.h>
 
@@ -23,7 +23,7 @@
 // number of temporal layers. The temporal layer sizes among spatial layers must
 // be identical. Temporal layers and spatial layers are described in
 // https://tools.ietf.org/html/draft-ietf-payload-vp9-10#section-3.
-class MEDIA_GPU_EXPORT VP9SVCLayers {
+class MEDIA_GPU_EXPORT VP9SVCLayersStateful {
  public:
   struct FrameConfig;
 
@@ -33,16 +33,16 @@
       kVp9NumRefFrames / kMaxSpatialLayers;
   static_assert(
       kMaxNumUsedRefFramesEachSpatialLayer == 2u,
-      "VP9SVCLayers uses two reference frames for each spatial layer");
+      "VP9SVCLayersStateful uses two reference frames for each spatial layer");
   constexpr static size_t kMaxNumUsedReferenceFrames =
       kMaxNumUsedRefFramesEachSpatialLayer * kMaxSpatialLayers;
   static_assert(kMaxNumUsedReferenceFrames == 6u,
-                "VP9SVCLayers uses six reference frames");
+                "VP9SVCLayersStateful uses six reference frames");
 
   using SpatialLayer = VideoEncodeAccelerator::Config::SpatialLayer;
-  explicit VP9SVCLayers(const std::vector<SpatialLayer>& spatial_layers,
-                        SVCInterLayerPredMode inter_layer_pred);
-  ~VP9SVCLayers();
+  explicit VP9SVCLayersStateful(const std::vector<SpatialLayer>& spatial_layers,
+                                SVCInterLayerPredMode inter_layer_pred);
+  ~VP9SVCLayersStateful();
 
   // Returns true if EncodeJob needs to produce key frame.
   bool UpdateEncodeJob(bool is_key_frame_requested, size_t kf_period_frames);
@@ -64,7 +64,7 @@
   }
 
  private:
-  friend class VP9SVCLayersTest;
+  friend class VP9SVCLayersStatefulTest;
 
   // Useful functions to construct refresh flag and detect reference frames
   // from the flag.
@@ -98,4 +98,4 @@
 };
 
 }  // namespace media
-#endif  // MEDIA_GPU_VP9_SVC_LAYERS_H_
+#endif  // MEDIA_GPU_VP9_SVC_LAYERS_STATEFUL_H_
diff --git a/media/gpu/vp9_svc_layers_unittest.cc b/media/gpu/vp9_svc_layers_stateful_unittest.cc
similarity index 93%
rename from media/gpu/vp9_svc_layers_unittest.cc
rename to media/gpu/vp9_svc_layers_stateful_unittest.cc
index 213aad5..3f746004 100644
--- a/media/gpu/vp9_svc_layers_unittest.cc
+++ b/media/gpu/vp9_svc_layers_stateful_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "media/gpu/vp9_svc_layers.h"
+#include "media/gpu/vp9_svc_layers_stateful.h"
 
 #include <algorithm>
 #include <array>
@@ -25,12 +25,12 @@
 constexpr gfx::Size kDefaultEncodeSize(1280, 720);
 constexpr int kSpatialLayerResolutionDenom[] = {4, 2, 1};
 
-std::vector<VP9SVCLayers::SpatialLayer> GetDefaultSVCLayers(
+std::vector<VP9SVCLayersStateful::SpatialLayer> GetDefaultSVCLayers(
     size_t num_spatial_layers,
     size_t num_temporal_layers) {
-  std::vector<VP9SVCLayers::SpatialLayer> spatial_layers;
+  std::vector<VP9SVCLayersStateful::SpatialLayer> spatial_layers;
   for (uint8_t i = 0; i < num_spatial_layers; ++i) {
-    VP9SVCLayers::SpatialLayer spatial_layer;
+    VP9SVCLayersStateful::SpatialLayer spatial_layer;
     const int denom = kSpatialLayerResolutionDenom[i];
     spatial_layer.width = kDefaultEncodeSize.width() / denom;
     spatial_layer.height = kDefaultEncodeSize.height() / denom;
@@ -52,12 +52,12 @@
 }
 }  // namespace
 
-class VP9SVCLayersTest
+class VP9SVCLayersStatefulTest
     : public ::testing::TestWithParam<
           ::testing::tuple<size_t, size_t, SVCInterLayerPredMode>> {
  public:
-  VP9SVCLayersTest() = default;
-  ~VP9SVCLayersTest() = default;
+  VP9SVCLayersStatefulTest() = default;
+  ~VP9SVCLayersStatefulTest() = default;
 
  protected:
   void VerifykSVCRefFrames(
@@ -82,7 +82,7 @@
                        size_t num_spatial_layers,
                        const Vp9Metadata& metadata);
 
-  void VerifyActiveLayer(const VP9SVCLayers& svc_layers,
+  void VerifyActiveLayer(const VP9SVCLayersStateful& svc_layers,
                          size_t expected_begin,
                          size_t expected_end) {
     EXPECT_EQ(svc_layers.begin_active_layer_, expected_begin);
@@ -90,14 +90,16 @@
   }
 
  private:
-  std::vector<uint8_t> temporal_indices_[VP9SVCLayers::kMaxSpatialLayers];
+  std::vector<uint8_t>
+      temporal_indices_[VP9SVCLayersStateful::kMaxSpatialLayers];
   uint8_t spatial_index_;
 };
 
-void VP9SVCLayersTest::VerifyStructure(bool first_frame_in_spatial_layer,
-                                       size_t num_temporal_layers,
-                                       size_t num_spatial_layers,
-                                       const Vp9Metadata& metadata) {
+void VP9SVCLayersStatefulTest::VerifyStructure(
+    bool first_frame_in_spatial_layer,
+    size_t num_temporal_layers,
+    size_t num_spatial_layers,
+    const Vp9Metadata& metadata) {
   const uint8_t temporal_index = metadata.temporal_idx;
   const uint8_t spatial_index = metadata.spatial_idx;
   // Spatial index monotonically increases modulo |num_spatial_layers|.
@@ -138,7 +140,7 @@
   }
 }
 
-void VP9SVCLayersTest::VerifykSVCRefFrames(
+void VP9SVCLayersStatefulTest::VerifykSVCRefFrames(
     const Vp9FrameHeader& frame_hdr,
     const Vp9Metadata& metadata,
     const std::array<bool, kVp9NumRefsPerFrame>& ref_frames_used,
@@ -203,7 +205,7 @@
   }
 }
 
-void VP9SVCLayersTest::VerifySmodeRefFrames(
+void VP9SVCLayersStatefulTest::VerifySmodeRefFrames(
     const Vp9FrameHeader& frame_hdr,
     const Vp9Metadata& metadata,
     const std::array<bool, kVp9NumRefsPerFrame>& ref_frames_used,
@@ -253,15 +255,15 @@
   EXPECT_EQ(ref_spatial_index, spatial_index);
 }
 
-TEST_P(VP9SVCLayersTest, ) {
+TEST_P(VP9SVCLayersStatefulTest, ) {
   const size_t num_spatial_layers = ::testing::get<0>(GetParam());
   const size_t num_temporal_layers = ::testing::get<1>(GetParam());
   const SVCInterLayerPredMode inter_layer_pred_mode =
       ::testing::get<2>(GetParam());
 
-  const std::vector<VP9SVCLayers::SpatialLayer> spatial_layers =
+  const std::vector<VP9SVCLayersStateful::SpatialLayer> spatial_layers =
       GetDefaultSVCLayers(num_spatial_layers, num_temporal_layers);
-  VP9SVCLayers svc_layers(spatial_layers, inter_layer_pred_mode);
+  VP9SVCLayersStateful svc_layers(spatial_layers, inter_layer_pred_mode);
 
   constexpr size_t kNumFramesToEncode = 32;
   Vp9ReferenceFrameVector ref_frames;
@@ -307,7 +309,7 @@
 // inter_layer_pred_mode)
 INSTANTIATE_TEST_SUITE_P(
     ,
-    VP9SVCLayersTest,
+    VP9SVCLayersStatefulTest,
     ::testing::Values(std::make_tuple(1, 2, SVCInterLayerPredMode::kOff),
                       std::make_tuple(1, 3, SVCInterLayerPredMode::kOff),
                       std::make_tuple(2, 1, SVCInterLayerPredMode::kOnKeyPic),
@@ -323,18 +325,19 @@
                       std::make_tuple(3, 2, SVCInterLayerPredMode::kOff),
                       std::make_tuple(3, 3, SVCInterLayerPredMode::kOff)));
 
-class VP9SVCLayersUpdateActiveLayerTest : public VP9SVCLayersTest {};
+class VP9SVCLayersStatefulUpdateActiveLayerTest
+    : public VP9SVCLayersStatefulTest {};
 
 // This test verifies the bitrate check in MaybeUpdateActiveLayer().
-TEST_P(VP9SVCLayersUpdateActiveLayerTest, MaybeUpdateActiveLayer) {
-  constexpr size_t kNumSpatialLayers = VP9SVCLayers::kMaxSpatialLayers;
+TEST_P(VP9SVCLayersStatefulUpdateActiveLayerTest, MaybeUpdateActiveLayer) {
+  constexpr size_t kNumSpatialLayers = VP9SVCLayersStateful::kMaxSpatialLayers;
   constexpr static size_t kNumTemporalLayers =
-      VP9SVCLayers::kMaxSupportedTemporalLayers;
+      VP9SVCLayersStateful::kMaxSupportedTemporalLayers;
   const SVCInterLayerPredMode inter_layer_pred_mode =
       ::testing::get<2>(GetParam());
-  const std::vector<VP9SVCLayers::SpatialLayer> spatial_layers =
+  const std::vector<VP9SVCLayersStateful::SpatialLayer> spatial_layers =
       GetDefaultSVCLayers(kNumSpatialLayers, kNumTemporalLayers);
-  VP9SVCLayers svc_layers(spatial_layers, inter_layer_pred_mode);
+  VP9SVCLayersStateful svc_layers(spatial_layers, inter_layer_pred_mode);
   const std::vector<gfx::Size> kSpatialLayerResolutions =
       svc_layers.active_spatial_layer_resolutions();
 
@@ -517,7 +520,7 @@
 // Pass invalid spatial and temporal layers as won't use it.
 INSTANTIATE_TEST_SUITE_P(
     ,
-    VP9SVCLayersUpdateActiveLayerTest,
+    VP9SVCLayersStatefulUpdateActiveLayerTest,
     ::testing::Values(
         std::make_tuple(-1, -1, SVCInterLayerPredMode::kOff),
         std::make_tuple(-1, -1, SVCInterLayerPredMode::kOnKeyPic)));
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
index 3b19d305..fd476975 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.cc
@@ -1011,7 +1011,8 @@
 
 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DVLOG(3) << __func__ << ": bitrate=" << bitrate.ToString()
            << ": framerate=" << framerate;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -1029,12 +1030,13 @@
       break;
   }
 
-  RequestEncodingParametersChange(allocation, framerate);
+  RequestEncodingParametersChange(allocation, framerate, size);
 }
 
 void MediaFoundationVideoEncodeAccelerator::RequestEncodingParametersChange(
     const VideoBitrateAllocation& bitrate_allocation,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DVLOG(3) << __func__ << ": bitrate=" << bitrate_allocation.GetSumBps()
            << ": framerate=" << framerate;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -1048,6 +1050,12 @@
     return;
   }
 
+  if (size.has_value()) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update output frame size is not supported"});
+    return;
+  }
+
   framerate =
       std::clamp(framerate, 1u, static_cast<uint32_t>(kMaxFrameRateNumerator));
 
diff --git a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
index 07a160c..0c3f932 100644
--- a/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
+++ b/media/gpu/windows/media_foundation_video_encode_accelerator_win.h
@@ -71,11 +71,14 @@
   void Encode(scoped_refptr<VideoFrame> frame,
               const EncodeOptions& options) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void RequestEncodingParametersChange(
       const VideoBitrateAllocation& bitrate_allocation,
-      uint32_t framerate) override;
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void Destroy() override;
   void Flush(FlushCallback flush_callback) override;
   bool IsFlushSupported() override;
diff --git a/media/mojo/clients/mojo_video_encode_accelerator.cc b/media/mojo/clients/mojo_video_encode_accelerator.cc
index 2495100..835b819 100644
--- a/media/mojo/clients/mojo_video_encode_accelerator.cc
+++ b/media/mojo/clients/mojo_video_encode_accelerator.cc
@@ -205,22 +205,24 @@
 
 void MojoVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DVLOG(2) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(vea_.is_bound());
 
-  vea_->RequestEncodingParametersChangeWithBitrate(bitrate, framerate);
+  vea_->RequestEncodingParametersChangeWithBitrate(bitrate, framerate, size);
 }
 
 void MojoVideoEncodeAccelerator::RequestEncodingParametersChange(
     const VideoBitrateAllocation& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   DVLOG(2) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(vea_.is_bound());
 
-  vea_->RequestEncodingParametersChangeWithLayers(bitrate, framerate);
+  vea_->RequestEncodingParametersChangeWithLayers(bitrate, framerate, size);
 }
 
 bool MojoVideoEncodeAccelerator::IsFlushSupported() {
diff --git a/media/mojo/clients/mojo_video_encode_accelerator.h b/media/mojo/clients/mojo_video_encode_accelerator.h
index 908e9e3e..f6d9cd9 100644
--- a/media/mojo/clients/mojo_video_encode_accelerator.h
+++ b/media/mojo/clients/mojo_video_encode_accelerator.h
@@ -47,10 +47,14 @@
   void Encode(scoped_refptr<VideoFrame> frame,
               const VideoEncoder::EncodeOptions&) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate_num) override;
-  void RequestEncodingParametersChange(const VideoBitrateAllocation& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate_num,
+      const absl::optional<gfx::Size>& size) override;
+  void RequestEncodingParametersChange(
+      const VideoBitrateAllocation& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   bool IsFlushSupported() override;
   void Flush(FlushCallback flush_callback) override;
   void Destroy() override;
diff --git a/media/mojo/clients/mojo_video_encode_accelerator_unittest.cc b/media/mojo/clients/mojo_video_encode_accelerator_unittest.cc
index 40fe480e..1c1322c 100644
--- a/media/mojo/clients/mojo_video_encode_accelerator_unittest.cc
+++ b/media/mojo/clients/mojo_video_encode_accelerator_unittest.cc
@@ -108,10 +108,26 @@
   MOCK_METHOD2(DoUseOutputBitstreamBuffer,
                void(int32_t, base::UnsafeSharedMemoryRegion*));
 
-  MOCK_METHOD2(RequestEncodingParametersChangeWithLayers,
-               void(const media::VideoBitrateAllocation&, uint32_t));
-  MOCK_METHOD2(RequestEncodingParametersChangeWithBitrate,
-               void(const media::Bitrate&, uint32_t));
+  void RequestEncodingParametersChangeWithLayers(
+      const media::VideoBitrateAllocation& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override {
+    DoRequestEncodingParametersChangeWithLayers(bitrate, framerate, size);
+  }
+  MOCK_METHOD3(DoRequestEncodingParametersChangeWithLayers,
+               void(const media::VideoBitrateAllocation&,
+                    uint32_t,
+                    const absl::optional<gfx::Size>&));
+  void RequestEncodingParametersChangeWithBitrate(
+      const media::Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override {
+    DoRequestEncodingParametersChangeWithBitrate(bitrate, framerate, size);
+  }
+  MOCK_METHOD3(DoRequestEncodingParametersChangeWithBitrate,
+               void(const media::Bitrate&,
+                    uint32_t,
+                    const absl::optional<gfx::Size>&));
 
   void IsFlushSupported(IsFlushSupportedCallback callback) override {
     DoIsFlushSupported();
@@ -290,14 +306,16 @@
   // In a real world scenario, we should go through an Initialize() prologue,
   // but we can skip that in unit testing.
 
-  EXPECT_CALL(*mock_mojo_vea(), RequestEncodingParametersChangeWithBitrate(
-                                    bitrate, kNewFramerate));
-  mojo_vea()->RequestEncodingParametersChange(bitrate, kNewFramerate);
+  EXPECT_CALL(*mock_mojo_vea(),
+              DoRequestEncodingParametersChangeWithBitrate(
+                  bitrate, kNewFramerate, testing::Eq(absl::nullopt)));
+  mojo_vea()->RequestEncodingParametersChange(bitrate, kNewFramerate,
+                                              absl::nullopt);
   base::RunLoop().RunUntilIdle();
 }
 
 // Tests that a RequestEncodingParametersChange() works with multi-dimensional
-// bitrate allocatio.
+// bitrate allocation.
 TEST_F(MojoVideoEncodeAcceleratorTest,
        EncodingParametersWithBitrateAllocation) {
   const uint32_t kNewFramerate = 321321u;
@@ -315,10 +333,68 @@
       bitrate_allocation.SetBitrate(si, ti, layer_bitrate);
     }
 
-    EXPECT_CALL(*mock_mojo_vea(), RequestEncodingParametersChangeWithLayers(
-                                      bitrate_allocation, kNewFramerate));
+    EXPECT_CALL(*mock_mojo_vea(), DoRequestEncodingParametersChangeWithLayers(
+                                      bitrate_allocation, kNewFramerate,
+                                      testing::Eq(absl::nullopt)));
     mojo_vea()->RequestEncodingParametersChange(bitrate_allocation,
-                                                kNewFramerate);
+                                                kNewFramerate, absl::nullopt);
+    base::RunLoop().RunUntilIdle();
+  }
+}
+
+// This test verifies RequestEncodingParametersChange() communication with
+// updated frame size.
+TEST_F(MojoVideoEncodeAcceleratorTest, EncodingParametersChangeWithFrameSize) {
+  std::unique_ptr<MockVideoEncodeAcceleratorClient> mock_vea_client =
+      std::make_unique<MockVideoEncodeAcceleratorClient>();
+  Initialize(mock_vea_client.get());
+
+  base::RunLoop().RunUntilIdle();
+  const uint32_t kNewFramerate = 321321u;
+  const uint32_t kNewBitrate = 123123u;
+  const gfx::Size kNewSize = gfx::Size(1280, 720);
+  Bitrate bitrate = Bitrate::ConstantBitrate(kNewBitrate);
+  EXPECT_CALL(*mock_mojo_vea(),
+              DoRequestEncodingParametersChangeWithBitrate(
+                  bitrate, kNewFramerate, testing::Optional(kNewSize)));
+  mojo_vea()->RequestEncodingParametersChange(bitrate, kNewFramerate, kNewSize);
+  base::RunLoop().RunUntilIdle();
+}
+
+// Tests that a RequestEncodingParametersChange() works with multi-dimensional
+// bitrate allocation and updated frame size.
+TEST_F(MojoVideoEncodeAcceleratorTest,
+       EncodingParametersChangeWithBitrateAllocationAndFrameSize) {
+  const uint32_t kNewFramerate = 321321u;
+  const size_t kMaxNumBitrates = VideoBitrateAllocation::kMaxSpatialLayers *
+                                 VideoBitrateAllocation::kMaxTemporalLayers;
+
+  // Verify translation of VideoBitrateAllocation into vector of bitrates for
+  // everything from empty array up to max number of layers.
+  VideoBitrateAllocation bitrate_allocation;
+  // Verify frame size from 256 x 144 to 256*kMaxSpatialLayers x
+  // 144*kMaxSpatialLayers.
+  const int kFrameSizeWidthBase = 256;
+  const int kFrameSizeHeightBase = 144;
+  gfx::Size frame_size = gfx::Size(kFrameSizeWidthBase, kFrameSizeHeightBase);
+  for (size_t i = 0; i <= kMaxNumBitrates; ++i) {
+    if (i > 0) {
+      uint32_t layer_bitrate = i * 1000;
+      const size_t si = (i - 1) / VideoBitrateAllocation::kMaxTemporalLayers;
+      const size_t ti = (i - 1) % VideoBitrateAllocation::kMaxTemporalLayers;
+      bitrate_allocation.SetBitrate(si, ti, layer_bitrate);
+    }
+
+    if (i < VideoBitrateAllocation::kMaxSpatialLayers) {
+      frame_size = gfx::Size(kFrameSizeWidthBase * (i + 1),
+                             kFrameSizeHeightBase * (i + 1));
+    }
+
+    EXPECT_CALL(*mock_mojo_vea(), DoRequestEncodingParametersChangeWithLayers(
+                                      bitrate_allocation, kNewFramerate,
+                                      testing::Optional(frame_size)));
+    mojo_vea()->RequestEncodingParametersChange(bitrate_allocation,
+                                                kNewFramerate, frame_size);
     base::RunLoop().RunUntilIdle();
   }
 }
diff --git a/media/mojo/mojom/video_encode_accelerator.mojom b/media/mojo/mojom/video_encode_accelerator.mojom
index e58de1c..32b0bfcd 100644
--- a/media/mojo/mojom/video_encode_accelerator.mojom
+++ b/media/mojo/mojom/video_encode_accelerator.mojom
@@ -219,9 +219,13 @@
   //  |bitrate_allocation| is the requested new bitrate, per spatial and
   //                       temporal layer.
   //  |framerate| is the requested new framerate, in frames per second.
+  //  |size| is the requested new input visible frame size. Clients can request
+  //         frame size change only when there is no pending frame in the
+  //         encoder.
   RequestEncodingParametersChangeWithLayers(
     VideoBitrateAllocation bitrate_allocation,
-    uint32 framerate);
+    uint32 framerate,
+    gfx.mojom.Size? size);
 
   // Request a change to the encoding parameters. This method is for use
   // with non-layered bitrates, and may make requests for constant or
@@ -231,9 +235,13 @@
   //            may be constant or variable bitrate. This should not change the
   //            encoding mode (constant -> variable or variable -> constant).
   //  |framerate| is the requested new framerate, in frames per second.
+  //  |size| is the requested new input visible frame size. Clients can request
+  //         frame size change only when there is no pending frame in the
+  //         encoder.
   RequestEncodingParametersChangeWithBitrate(
     Bitrate bitrate,
-    uint32 framerate);
+    uint32 framerate,
+    gfx.mojom.Size? size);
 
   [Sync]
   IsFlushSupported() => (bool result);
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.cc b/media/mojo/services/mojo_video_encode_accelerator_service.cc
index cfc2aff..0a629e2 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service.cc
+++ b/media/mojo/services/mojo_video_encode_accelerator_service.cc
@@ -45,6 +45,7 @@
       gpu_workarounds_(gpu_workarounds),
       gpu_device_(gpu_device),
       output_buffer_size_(0),
+      supports_frame_size_change(false),
       timestamps_(128) {
   DVLOG(1) << __func__;
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -212,38 +213,60 @@
 void MojoVideoEncodeAcceleratorService::
     RequestEncodingParametersChangeWithLayers(
         const media::VideoBitrateAllocation& bitrate_allocation,
-        uint32_t framerate) {
+        uint32_t framerate,
+        const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  TRACE_EVENT2("media",
+  std::string parameters_description = base::StringPrintf(
+      "bitrate_allocation=%s, framerate=%d, size=%s",
+      bitrate_allocation.ToString().c_str(), framerate,
+      size.has_value() ? size.value().ToString().c_str() : "nullopt");
+  TRACE_EVENT1("media",
                "MojoVideoEncodeAcceleratorService::"
                "RequestEncodingParametersChangeWithLayers",
-               "bitrate_allocation", bitrate_allocation.ToString(), "framerate",
-               framerate);
+               "parameters", parameters_description);
 
   if (!encoder_)
     return;
 
-  DVLOG(2) << __func__ << " bitrate=" << bitrate_allocation.GetSumBps()
-           << " framerate=" << framerate;
+  if (size.has_value() && !supports_frame_size_change) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update frame size is not supported"});
+    return;
+  }
 
-  encoder_->RequestEncodingParametersChange(bitrate_allocation, framerate);
+  DVLOG(2) << __func__ << " " << parameters_description;
+
+  encoder_->RequestEncodingParametersChange(bitrate_allocation, framerate,
+                                            size);
 }
 
 void MojoVideoEncodeAcceleratorService::
-    RequestEncodingParametersChangeWithBitrate(const media::Bitrate& bitrate,
-                                               uint32_t framerate) {
+    RequestEncodingParametersChangeWithBitrate(
+        const media::Bitrate& bitrate,
+        uint32_t framerate,
+        const absl::optional<gfx::Size>& size) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  TRACE_EVENT2("media",
+  std::string parameters_description = base::StringPrintf(
+      "bitrate=%s, framerate=%d, size=%s", bitrate.ToString().c_str(),
+      framerate,
+      size.has_value() ? size.value().ToString().c_str() : "nullopt");
+  TRACE_EVENT1("media",
                "MojoVideoEncodeAcceleratorService::"
                "RequestEncodingParametersChangeWithBitrate",
-               "bitrate", bitrate.ToString(), "framerate", framerate);
-  if (!encoder_)
+               "parameters", parameters_description);
+  if (!encoder_) {
     return;
+  }
 
-  DVLOG(2) << __func__ << " bitrate=" << bitrate.target_bps()
-           << " framerate=" << framerate;
+  if (size.has_value() && !supports_frame_size_change) {
+    NotifyErrorStatus({EncoderStatus::Codes::kEncoderUnsupportedConfig,
+                       "Update frame size is not supported"});
+    return;
+  }
 
-  encoder_->RequestEncodingParametersChange(bitrate, framerate);
+  DVLOG(2) << __func__ << " " << parameters_description;
+
+  encoder_->RequestEncodingParametersChange(bitrate, framerate, size);
 }
 
 void MojoVideoEncodeAcceleratorService::IsFlushSupported(
@@ -347,7 +370,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!vea_client_)
     return;
-
+  supports_frame_size_change = info.supports_frame_size_change;
   vea_client_->NotifyEncoderInfoChange(info);
 }
 
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service.h b/media/mojo/services/mojo_video_encode_accelerator_service.h
index b2517ad..2600f20 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service.h
+++ b/media/mojo/services/mojo_video_encode_accelerator_service.h
@@ -80,10 +80,12 @@
                                 base::UnsafeSharedMemoryRegion region) override;
   void RequestEncodingParametersChangeWithBitrate(
       const media::Bitrate& bitrate_allocation,
-      uint32_t framerate) override;
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void RequestEncodingParametersChangeWithLayers(
       const media::VideoBitrateAllocation& bitrate_allocation,
-      uint32_t framerate) override;
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   void IsFlushSupported(IsFlushSupportedCallback callback) override;
   void Flush(FlushCallback callback) override;
 
@@ -116,6 +118,7 @@
   // Cache of parameters for sanity verification.
   size_t output_buffer_size_;
   gfx::Size input_coded_size_;
+  bool supports_frame_size_change;
 
   base::LRUCache<int64_t, base::TimeTicks> timestamps_;
 
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc b/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
index ffcc981..7230290 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
+++ b/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
@@ -207,7 +207,7 @@
   VideoBitrateAllocation bitrate_allocation;
   bitrate_allocation.SetBitrate(0, 0, kNewBitrate);
   mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
-      bitrate_allocation, kNewFramerate);
+      bitrate_allocation, kNewFramerate, absl::nullopt);
   base::RunLoop().RunUntilIdle();
 
   ASSERT_TRUE(fake_vea());
@@ -215,6 +215,7 @@
   expected_allocation.SetBitrate(0, 0, kNewBitrate);
   EXPECT_EQ(expected_allocation,
             fake_vea()->stored_bitrate_allocations().back());
+  EXPECT_TRUE(fake_vea()->stored_frame_sizes().empty());
 }
 
 // Tests that a RequestEncodingParametersChange() ripples through correctly.
@@ -239,12 +240,55 @@
     }
 
     mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
-        bitrate_allocation, kNewFramerate);
+        bitrate_allocation, kNewFramerate, absl::nullopt);
     base::RunLoop().RunUntilIdle();
 
     ASSERT_TRUE(fake_vea());
     EXPECT_EQ(bitrate_allocation,
               fake_vea()->stored_bitrate_allocations().back());
+    EXPECT_TRUE(fake_vea()->stored_frame_sizes().empty());
+  }
+}
+
+// Tests that a RequestEncodingParametersChange() ripples through correctly.
+TEST_F(MojoVideoEncodeAcceleratorServiceTest,
+       EncodingParametersWithBitrateAllocationAndFrameSize) {
+  CreateMojoVideoEncodeAccelerator();
+  BindAndInitialize();
+
+  const uint32_t kNewFramerate = 321321u;
+  const size_t kMaxNumBitrates = VideoBitrateAllocation::kMaxSpatialLayers *
+                                 VideoBitrateAllocation::kMaxTemporalLayers;
+
+  // Verify translation of VideoBitrateAllocation into vector of bitrates for
+  // everything from empty array up to max number of layers.
+  VideoBitrateAllocation bitrate_allocation;
+  // Verify frame size from 256 x 144 to 256*kMaxSpatialLayers x
+  // 144*kMaxSpatialLayers.
+  const int kFrameSizeWidthBase = 256;
+  const int kFrameSizeHeightBase = 144;
+  gfx::Size frame_size = gfx::Size(kFrameSizeWidthBase, kFrameSizeHeightBase);
+  for (size_t i = 0; i <= kMaxNumBitrates; ++i) {
+    if (i > 0) {
+      uint32_t layer_bitrate = i * 1000;
+      const size_t si = (i - 1) / VideoBitrateAllocation::kMaxTemporalLayers;
+      const size_t ti = (i - 1) % VideoBitrateAllocation::kMaxTemporalLayers;
+      bitrate_allocation.SetBitrate(si, ti, layer_bitrate);
+    }
+
+    if (i < VideoBitrateAllocation::kMaxSpatialLayers) {
+      frame_size = gfx::Size(kFrameSizeWidthBase * (i + 1),
+                             kFrameSizeHeightBase * (i + 1));
+    }
+
+    mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
+        bitrate_allocation, kNewFramerate, frame_size);
+    base::RunLoop().RunUntilIdle();
+
+    ASSERT_TRUE(fake_vea());
+    EXPECT_EQ(bitrate_allocation,
+              fake_vea()->stored_bitrate_allocations().back());
+    EXPECT_EQ(frame_size, fake_vea()->stored_frame_sizes().back());
   }
 }
 
@@ -361,7 +405,7 @@
     media::VideoBitrateAllocation bitrate_allocation;
     bitrate_allocation.SetBitrate(0, 0, kNewBitrate);
     mojo_vea_service()->RequestEncodingParametersChangeWithLayers(
-        bitrate_allocation, kNewFramerate);
+        bitrate_allocation, kNewFramerate, absl::nullopt);
     base::RunLoop().RunUntilIdle();
   }
 }
diff --git a/media/mojo/test/mojo_video_encode_accelerator_integration_test.cc b/media/mojo/test/mojo_video_encode_accelerator_integration_test.cc
index fc8c6fdc6..3fbac5c1 100644
--- a/media/mojo/test/mojo_video_encode_accelerator_integration_test.cc
+++ b/media/mojo/test/mojo_video_encode_accelerator_integration_test.cc
@@ -331,9 +331,11 @@
   const Bitrate kNewBitrate = Bitrate::ConstantBitrate(123123u);
   const uint32_t kNewFramerate = 321321u;
 
-  mojo_vea()->RequestEncodingParametersChange(kNewBitrate, kNewFramerate);
+  mojo_vea()->RequestEncodingParametersChange(kNewBitrate, kNewFramerate,
+                                              absl::nullopt);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(kNewBitrate, fake_vea()->stored_bitrates().back());
+  EXPECT_TRUE(fake_vea()->stored_frame_sizes().empty());
 }
 
 // Tests that a RequestEncodingParametersChange() ripples through correctly.
@@ -358,10 +360,51 @@
     }
 
     mojo_vea()->RequestEncodingParametersChange(bitrate_allocation,
-                                                kNewFramerate);
+                                                kNewFramerate, absl::nullopt);
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(bitrate_allocation,
               fake_vea()->stored_bitrate_allocations().back());
+    EXPECT_TRUE(fake_vea()->stored_frame_sizes().empty());
+  }
+}
+
+// Tests that a RequestEncodingParametersChange() ripples through correctly.
+TEST_F(MojoVideoEncodeAcceleratorIntegrationTest,
+       EncodingParametersWithBitrateAllocationAndFrameSize) {
+  auto mock_vea_client = std::make_unique<MockVideoEncodeAcceleratorClient>();
+  Initialize(mock_vea_client.get());
+
+  const uint32_t kNewFramerate = 321321u;
+  const size_t kMaxNumBitrates = VideoBitrateAllocation::kMaxSpatialLayers *
+                                 VideoBitrateAllocation::kMaxTemporalLayers;
+
+  // Verify translation of VideoBitrateAllocation into vector of bitrates for
+  // everything from empty array up to max number of layers.
+  VideoBitrateAllocation bitrate_allocation;
+  // Verify frame size from 256 x 144 to 256*kMaxSpatialLayers x
+  // 144*kMaxSpatialLayers.
+  const int kFrameSizeWidthBase = 256;
+  const int kFrameSizeHeightBase = 144;
+  gfx::Size frame_size = gfx::Size(kFrameSizeWidthBase, kFrameSizeHeightBase);
+  for (size_t i = 0; i <= kMaxNumBitrates; ++i) {
+    if (i > 0) {
+      uint32_t layer_bitrate = i * 1000;
+      const size_t si = (i - 1) / VideoBitrateAllocation::kMaxTemporalLayers;
+      const size_t ti = (i - 1) % VideoBitrateAllocation::kMaxTemporalLayers;
+      bitrate_allocation.SetBitrate(si, ti, layer_bitrate);
+    }
+
+    if (i < VideoBitrateAllocation::kMaxSpatialLayers) {
+      frame_size = gfx::Size(kFrameSizeWidthBase * (i + 1),
+                             kFrameSizeHeightBase * (i + 1));
+    }
+
+    mojo_vea()->RequestEncodingParametersChange(bitrate_allocation,
+                                                kNewFramerate, frame_size);
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(bitrate_allocation,
+              fake_vea()->stored_bitrate_allocations().back());
+    EXPECT_EQ(frame_size, fake_vea()->stored_frame_sizes().back());
   }
 }
 
@@ -380,7 +423,8 @@
     // Any call to MojoVideoEncodeAccelerator here will do nothing because the
     // remote end has been torn down and needs to be re Initialize()d.
     mojo_vea()->RequestEncodingParametersChange(
-        Bitrate::ConstantBitrate(1234u) /* bitrate */, 3321 /* framerate */);
+        Bitrate::ConstantBitrate(1234u) /* bitrate */, 3321 /* framerate */,
+        absl::nullopt);
     base::RunLoop().RunUntilIdle();
   }
 }
diff --git a/media/video/fake_video_encode_accelerator.cc b/media/video/fake_video_encode_accelerator.cc
index 01185d0..fc5e76f 100644
--- a/media/video/fake_video_encode_accelerator.cc
+++ b/media/video/fake_video_encode_accelerator.cc
@@ -66,6 +66,9 @@
       base::BindOnce(&FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers,
                      weak_this_factory_.GetWeakPtr(), kMinimumInputCount,
                      config.input_visible_size, kMinimumOutputBufferSize));
+  VideoEncoderInfo encoder_info;
+  encoder_info.supports_frame_size_change = true;
+  NotifyEncoderInfoChange(encoder_info);
   return true;
 }
 
@@ -87,18 +90,26 @@
 
 void FakeVideoEncodeAccelerator::RequestEncodingParametersChange(
     const Bitrate& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   // Reject bitrate mode changes.
   if (stored_bitrates_.empty() ||
       stored_bitrates_.back().mode() == bitrate.mode()) {
     stored_bitrates_.push_back(bitrate);
   }
+  if (size.has_value()) {
+    stored_frame_sizes_.push_back(size.value());
+  }
 }
 
 void FakeVideoEncodeAccelerator::RequestEncodingParametersChange(
     const VideoBitrateAllocation& bitrate,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   stored_bitrate_allocations_.push_back(bitrate);
+  if (size.has_value()) {
+    stored_frame_sizes_.push_back(size.value());
+  }
 }
 
 void FakeVideoEncodeAccelerator::Destroy() {
diff --git a/media/video/fake_video_encode_accelerator.h b/media/video/fake_video_encode_accelerator.h
index eab1ed5..5be982b3 100644
--- a/media/video/fake_video_encode_accelerator.h
+++ b/media/video/fake_video_encode_accelerator.h
@@ -46,16 +46,23 @@
                   std::unique_ptr<MediaLog> media_log = nullptr) override;
   void Encode(scoped_refptr<VideoFrame> frame, bool force_keyframe) override;
   void UseOutputBitstreamBuffer(BitstreamBuffer buffer) override;
-  void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                       uint32_t framerate) override;
-  void RequestEncodingParametersChange(const VideoBitrateAllocation& bitrate,
-                                       uint32_t framerate) override;
+  void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
+  void RequestEncodingParametersChange(
+      const VideoBitrateAllocation& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) override;
   bool IsGpuFrameResizeSupported() override;
   void Destroy() override;
 
   const std::vector<Bitrate>& stored_bitrates() const {
     return stored_bitrates_;
   }
+  const std::vector<gfx::Size>& stored_frame_sizes() const {
+    return stored_frame_sizes_;
+  }
   const std::vector<VideoBitrateAllocation>& stored_bitrate_allocations()
       const {
     return stored_bitrate_allocations_;
@@ -99,6 +106,7 @@
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::vector<Bitrate> stored_bitrates_;
   std::vector<VideoBitrateAllocation> stored_bitrate_allocations_;
+  std::vector<gfx::Size> stored_frame_sizes_;
   bool will_initialization_succeed_;
   bool will_encoding_succeed_;
   bool resize_supported_ = false;
diff --git a/media/video/mock_video_encode_accelerator.h b/media/video/mock_video_encode_accelerator.h
index 64222d6..c034374 100644
--- a/media/video/mock_video_encode_accelerator.h
+++ b/media/video/mock_video_encode_accelerator.h
@@ -31,8 +31,10 @@
   MOCK_METHOD2(Encode,
                void(scoped_refptr<VideoFrame> frame, bool force_keyframe));
   MOCK_METHOD1(UseOutputBitstreamBuffer, void(BitstreamBuffer buffer));
-  MOCK_METHOD2(RequestEncodingParametersChange,
-               void(const Bitrate& bitrate, uint32_t framerate));
+  MOCK_METHOD3(RequestEncodingParametersChange,
+               void(const Bitrate& bitrate,
+                    uint32_t framerate,
+                    const absl::optional<gfx::Size>& size));
   MOCK_METHOD0(Destroy, void());
 
  private:
diff --git a/media/video/video_encode_accelerator.cc b/media/video/video_encode_accelerator.cc
index 9a2e15ee..67556005 100644
--- a/media/video/video_encode_accelerator.cc
+++ b/media/video/video_encode_accelerator.cc
@@ -232,9 +232,11 @@
 
 void VideoEncodeAccelerator::RequestEncodingParametersChange(
     const VideoBitrateAllocation& bitrate_allocation,
-    uint32_t framerate) {
+    uint32_t framerate,
+    const absl::optional<gfx::Size>& size) {
   RequestEncodingParametersChange(
-      Bitrate::ConstantBitrate(bitrate_allocation.GetSumBps()), framerate);
+      Bitrate::ConstantBitrate(bitrate_allocation.GetSumBps()), framerate,
+      size);
 }
 
 bool operator==(const VideoEncodeAccelerator::SupportedProfile& l,
diff --git a/media/video/video_encode_accelerator.h b/media/video/video_encode_accelerator.h
index c07ba87..cdda126 100644
--- a/media/video/video_encode_accelerator.h
+++ b/media/video/video_encode_accelerator.h
@@ -407,10 +407,14 @@
   // Parameters:
   //  |bitrate| is the requested new bitrate. The bitrate mode cannot be changed
   //  using this method and attempting to do so will result in an error.
-  //  Instead, re-create a VideoEncodeAccelerator. |framerate| is the requested
-  //  new framerate, in frames per second.
-  virtual void RequestEncodingParametersChange(const Bitrate& bitrate,
-                                               uint32_t framerate) = 0;
+  //  Instead, re-create a VideoEncodeAccelerator.
+  //  |framerate| is the requested new framerate, in frames per second.
+  //  |size| is the requested new input visible frame size. Clients can request
+  //  frame size change only when there is no pending frame in the encoder.
+  virtual void RequestEncodingParametersChange(
+      const Bitrate& bitrate,
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size) = 0;
 
   // Request a change to the encoding parameters. If not implemented, default
   // behavior is to get the sum over layers and pass to version with bitrate
@@ -418,9 +422,12 @@
   // Parameters:
   //  |bitrate| is the requested new bitrate, per spatial and temporal layer.
   //  |framerate| is the requested new framerate, in frames per second.
+  //  |size| is the requested new input visible frame size. Clients can request
+  //  frame size change only when there is no pending frame in the encoder.
   virtual void RequestEncodingParametersChange(
       const VideoBitrateAllocation& bitrate,
-      uint32_t framerate);
+      uint32_t framerate,
+      const absl::optional<gfx::Size>& size);
 
   // Destroys the encoder: all pending inputs and outputs are dropped
   // immediately and the component is freed.  This call may asynchronously free
diff --git a/media/video/video_encode_accelerator_adapter.cc b/media/video/video_encode_accelerator_adapter.cc
index fdca1a2..7152880 100644
--- a/media/video/video_encode_accelerator_adapter.cc
+++ b/media/video/video_encode_accelerator_adapter.cc
@@ -630,8 +630,6 @@
   uint32_t framerate = base::ClampRound<uint32_t>(
       options.framerate.value_or(VideoEncodeAccelerator::kDefaultFramerate));
 
-  accelerator_->RequestEncodingParametersChange(bitrate, framerate);
-
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
   if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) {
     if (options.avc.produce_annexb) {
@@ -656,6 +654,9 @@
   options_ = options;
   if (!output_cb.is_null())
     output_cb_ = std::move(output_cb);
+
+  accelerator_->RequestEncodingParametersChange(bitrate, framerate,
+                                                absl::nullopt);
   std::move(done_cb).Run(EncoderStatus::Codes::kOk);
 }
 
diff --git a/remoting/codec/webrtc_video_encoder_gpu.cc b/remoting/codec/webrtc_video_encoder_gpu.cc
index e3bd68a..0014741 100644
--- a/remoting/codec/webrtc_video_encoder_gpu.cc
+++ b/remoting/codec/webrtc_video_encoder_gpu.cc
@@ -275,7 +275,8 @@
     uint32_t bitrate_bps =
         checked_bitrate.ValueOrDefault(std::numeric_limits<uint32_t>::max());
     video_encode_accelerator_->RequestEncodingParametersChange(
-        media::Bitrate::ConstantBitrate(bitrate_bps), params.fps);
+        media::Bitrate::ConstantBitrate(bitrate_bps), params.fps,
+        absl::nullopt);
   }
   video_encode_accelerator_->Encode(video_frame, params.key_frame);
 }
diff --git a/services/accessibility/BUILD.gn b/services/accessibility/BUILD.gn
index 6b11cd7..1f7e81d6d 100644
--- a/services/accessibility/BUILD.gn
+++ b/services/accessibility/BUILD.gn
@@ -56,6 +56,8 @@
       "features/text_encoder.h",
       "features/tts_interface_binder.cc",
       "features/tts_interface_binder.h",
+      "features/user_input_interface_binder.cc",
+      "features/user_input_interface_binder.h",
       "features/user_interface_interface_binder.cc",
       "features/user_interface_interface_binder.h",
       "features/v8_bindings_utils.cc",
@@ -143,9 +145,13 @@
         "//third_party/inspector_protocol:crdtp",
       ]
       data_deps = [
+        "//mojo/public/mojom/base",
         "//services/accessibility/features/javascript:js_api_files",
         "//services/accessibility/features/mojo/test:test_support_data",
         "//services/accessibility/public/mojom:os_accessibility_service_js",
+        "//skia/public/mojom:mojom_js",
+        "//ui/events/mojom:mojom_js",
+        "//ui/gfx/geometry/mojom:mojom_js",
       ]
     }
   } else {
diff --git a/services/accessibility/assistive_technology_controller_impl.cc b/services/accessibility/assistive_technology_controller_impl.cc
index 6e1da0f..f991eb9 100644
--- a/services/accessibility/assistive_technology_controller_impl.cc
+++ b/services/accessibility/assistive_technology_controller_impl.cc
@@ -66,6 +66,12 @@
   accessibility_service_client_remote_->BindTts(std::move(tts_receiver));
 }
 
+void AssistiveTechnologyControllerImpl::BindUserInput(
+    mojo::PendingReceiver<mojom::UserInput> user_input_receiver) {
+  accessibility_service_client_remote_->BindUserInput(
+      std::move(user_input_receiver));
+}
+
 void AssistiveTechnologyControllerImpl::BindUserInterface(
     mojo::PendingReceiver<mojom::UserInterface> user_interface_receiver) {
   accessibility_service_client_remote_->BindUserInterface(
@@ -157,7 +163,6 @@
   }
   if (type == mojom::AssistiveTechnologyType::kChromeVox ||
       type == mojom::AssistiveTechnologyType::kSelectToSpeak) {
-    // TTS needs to know the type that is speaking.
     manager.ConfigureTts(this);
   }
   if (type == mojom::AssistiveTechnologyType::kChromeVox ||
@@ -172,6 +177,14 @@
   if (type == mojom::AssistiveTechnologyType::kAutoClick) {
     manager.ConfigureAutoclick(this);
   }
+  if (type == mojom::AssistiveTechnologyType::kAutoClick ||
+      type == mojom::AssistiveTechnologyType::kChromeVox ||
+      type == mojom::AssistiveTechnologyType::kDictation ||
+      type == mojom::AssistiveTechnologyType::kMagnifier ||
+      type == mojom::AssistiveTechnologyType::kSelectToSpeak ||
+      type == mojom::AssistiveTechnologyType::kSwitchAccess) {
+    manager.ConfigureUserInput(this);
+  }
   // TODO(b/262637071): Configure other bindings based on the type
   // once they are implemented.
 
diff --git a/services/accessibility/assistive_technology_controller_impl.h b/services/accessibility/assistive_technology_controller_impl.h
index 2dd923c..6a1ab3bf 100644
--- a/services/accessibility/assistive_technology_controller_impl.h
+++ b/services/accessibility/assistive_technology_controller_impl.h
@@ -16,6 +16,7 @@
 #include "services/accessibility/public/mojom/accessibility_service.mojom.h"
 #include "services/accessibility/public/mojom/autoclick.mojom-forward.h"
 #include "services/accessibility/public/mojom/file_loader.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom-forward.h"
 #include "services/accessibility/public/mojom/user_interface.mojom-forward.h"
 
 namespace ax {
@@ -56,6 +57,8 @@
   void BindSpeechRecognition(
       mojo::PendingReceiver<mojom::SpeechRecognition> sr_receiver) override;
   void BindTts(mojo::PendingReceiver<mojom::Tts> tts_receiver) override;
+  void BindUserInput(
+      mojo::PendingReceiver<mojom::UserInput> user_input_receiver) override;
   void BindUserInterface(mojo::PendingReceiver<mojom::UserInterface>
                              user_interface_receiver) override;
   void BindAccessibilityFileLoader(
diff --git a/services/accessibility/fake_service_client.cc b/services/accessibility/fake_service_client.cc
index 216fadf..a7ef97e 100644
--- a/services/accessibility/fake_service_client.cc
+++ b/services/accessibility/fake_service_client.cc
@@ -40,6 +40,11 @@
   tts_receivers_.Add(this, std::move(tts_receiver));
 }
 
+void FakeServiceClient::BindUserInput(
+    mojo::PendingReceiver<mojom::UserInput> ui_receiver) {
+  ui_receivers_.Add(this, std::move(ui_receiver));
+}
+
 void FakeServiceClient::BindUserInterface(
     mojo::PendingReceiver<mojom::UserInterface> ux_receiver) {
   ux_receivers_.Add(this, std::move(ux_receiver));
@@ -157,6 +162,14 @@
   std::move(callback).Run(std::move(voices));
 }
 
+void FakeServiceClient::SendSyntheticKeyEventForShortcutOrNavigation(
+    mojom::SyntheticKeyEventPtr key_event) {
+  key_events_.emplace_back(std::move(key_event));
+  if (synthetic_key_event_callback_) {
+    synthetic_key_event_callback_.Run();
+  }
+}
+
 void FakeServiceClient::DarkenScreen(bool darken) {
   if (darken_screen_callback_) {
     darken_screen_callback_.Run(darken);
@@ -259,6 +272,16 @@
   tts_utterance_client_->OnEvent(std::move(tts_event));
 }
 
+void FakeServiceClient::SetSyntheticKeyEventCallback(
+    base::RepeatingCallback<void()> callback) {
+  synthetic_key_event_callback_ = std::move(callback);
+}
+
+const std::vector<mojom::SyntheticKeyEventPtr>&
+FakeServiceClient::GetKeyEvents() const {
+  return key_events_;
+}
+
 void FakeServiceClient::SetDarkenScreenCallback(
     base::RepeatingCallback<void(bool darken)> callback) {
   darken_screen_callback_ = std::move(callback);
diff --git a/services/accessibility/fake_service_client.h b/services/accessibility/fake_service_client.h
index 224dc0c..f82595a0 100644
--- a/services/accessibility/fake_service_client.h
+++ b/services/accessibility/fake_service_client.h
@@ -22,6 +22,7 @@
 #include "services/accessibility/public/mojom/file_loader.mojom.h"
 #include "services/accessibility/public/mojom/speech_recognition.mojom.h"
 #include "services/accessibility/public/mojom/tts.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
 #include "services/accessibility/public/mojom/user_interface.mojom.h"
 #endif  // BUILDFLAG(SUPPORTS_OS_ACCESSIBILITY_SERVICE)
 
@@ -38,6 +39,7 @@
                           public mojom::AutoclickClient,
                           public mojom::SpeechRecognition,
                           public mojom::Tts,
+                          public mojom::UserInput,
                           public mojom::UserInterface,
 #endif
                           public mojom::AutomationClient {
@@ -62,6 +64,8 @@
   void BindSpeechRecognition(
       mojo::PendingReceiver<ax::mojom::SpeechRecognition> sr_receiver) override;
   void BindTts(mojo::PendingReceiver<ax::mojom::Tts> tts_receiver) override;
+  void BindUserInput(
+      mojo::PendingReceiver<ax::mojom::UserInput> ui_receiver) override;
   void BindUserInterface(
       mojo::PendingReceiver<ax::mojom::UserInterface> ux_receiver) override;
 
@@ -87,6 +91,10 @@
   void IsSpeaking(IsSpeakingCallback callback) override;
   void GetVoices(GetVoicesCallback callback) override;
 
+  // ax::mojom::UserInput:
+  void SendSyntheticKeyEventForShortcutOrNavigation(
+      ax::mojom::SyntheticKeyEventPtr key_event) override;
+
   // ax::mojom::UserInterface:
   void DarkenScreen(bool darken) override;
   void OpenSettingsSubpage(const std::string& subpage) override;
@@ -123,6 +131,9 @@
           callback);
   void SendTtsUtteranceEvent(mojom::TtsEventPtr tts_event);
 
+  void SetSyntheticKeyEventCallback(base::RepeatingCallback<void()> callback);
+  const std::vector<ax::mojom::SyntheticKeyEventPtr>& GetKeyEvents() const;
+
   bool UserInterfaceIsBound() const;
   void SetDarkenScreenCallback(
       base::RepeatingCallback<void(bool darken)> callback);
@@ -162,6 +173,10 @@
   mojo::ReceiverSet<mojom::Tts> tts_receivers_;
   mojo::Remote<ax::mojom::TtsUtteranceClient> tts_utterance_client_;
 
+  base::RepeatingCallback<void()> synthetic_key_event_callback_;
+  mojo::ReceiverSet<mojom::UserInput> ui_receivers_;
+  std::vector<ax::mojom::SyntheticKeyEventPtr> key_events_;
+
   base::RepeatingCallback<void(bool darken)> darken_screen_callback_;
   base::RepeatingCallback<void(const std::string& subpage)>
       open_settings_subpage_callback_;
diff --git a/services/accessibility/features/DEPS b/services/accessibility/features/DEPS
index 5f33e08..f8cb734 100644
--- a/services/accessibility/features/DEPS
+++ b/services/accessibility/features/DEPS
@@ -1,15 +1,7 @@
 include_rules = [
   "+gin",
-  "+ui/accessibility/ax_event.h",
-  "+ui/accessibility/ax_node_id_forward.h",
-  "+ui/accessibility/ax_node_position.h",
-  "+ui/accessibility/ax_relative_bounds.h",
-  "+ui/accessibility/ax_tree_id.h",
-  "+ui/accessibility/ax_tree_update.h",
-  "+ui/accessibility/platform/automation/automation_tree_manager_owner.h",
-  "+ui/accessibility/platform/automation/automation_v8_bindings.h",
-  "+ui/accessibility/platform/automation/automation_v8_router.h",
-  "+ui/accessibility/platform/automation/automation_api_util.h",
+  "+ui/accessibility",
+  "+ui/events",
   "+third_party/blink/public/mojom/devtools",
   "+third_party/inspector_protocol/crdtp",
   "+v8/include",
diff --git a/services/accessibility/features/atp_js_api_test.cc b/services/accessibility/features/atp_js_api_test.cc
index 370dc07..f14d20a 100644
--- a/services/accessibility/features/atp_js_api_test.cc
+++ b/services/accessibility/features/atp_js_api_test.cc
@@ -17,9 +17,13 @@
 #include "services/accessibility/public/mojom/accessibility_service.mojom.h"
 #include "services/accessibility/public/mojom/speech_recognition.mojom.h"
 #include "services/accessibility/public/mojom/tts.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
 #include "services/accessibility/public/mojom/user_interface.mojom-shared.h"
 #include "services/accessibility/public/mojom/user_interface.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/mojom/event_constants.mojom-shared.h"
 
 namespace ax {
 
@@ -514,10 +518,15 @@
     // permissions so we load support JS within the test.
     return std::vector<std::string>{
         "services/accessibility/features/mojo/test/mojom_test_support.js",
+        "mojo/public/mojom/base/time.mojom-lite.js",
         "skia/public/mojom/skcolor.mojom-lite.js",
         "ui/gfx/geometry/mojom/geometry.mojom-lite.js",
+        "ui/latency/mojom/latency_info.mojom-lite.js",
+        "ui/events/mojom/event_constants.mojom-lite.js",
+        "ui/events/mojom/event.mojom-lite.js",
         "services/accessibility/public/mojom/"
         "assistive_technology_type.mojom-lite.js",
+        "services/accessibility/public/mojom/user_input.mojom-lite.js",
         "services/accessibility/public/mojom/user_interface.mojom-lite.js",
         "services/accessibility/features/javascript/chrome_event.js",
         "services/accessibility/features/javascript/accessibility_private.js",
@@ -837,6 +846,116 @@
   WaitForJSTestComplete();
 }
 
+TEST_F(AccessibilityPrivateJSApiTest,
+       SendSyntheticKeyEventForShortcutOrNavigation) {
+  base::RunLoop waiter;
+
+  client_->SetSyntheticKeyEventCallback(
+      base::BindLambdaForTesting([&waiter, this]() {
+        const std::vector<mojom::SyntheticKeyEventPtr>& events =
+            client_->GetKeyEvents();
+        if (events.size() < 2) {
+          return;
+        }
+
+        ASSERT_EQ(events.size(), 2u);
+
+        auto& press_event = events[0];
+        ASSERT_EQ(press_event->type, ui::mojom::EventType::KEY_PRESSED);
+        ASSERT_EQ(press_event->key_data->key_code, ui::VKEY_X);
+        // TODO(b/307553499): Update SyntheticKeyEvent to use dom_code and
+        // dom_key.
+        ASSERT_EQ(press_event->key_data->dom_code, 0u);
+        ASSERT_EQ(press_event->key_data->dom_key, 0);
+        ASSERT_FALSE(press_event->key_data->is_char);
+        ASSERT_EQ(press_event->flags, ui::EF_NONE);
+
+        auto& release_event = events[1];
+        ASSERT_EQ(release_event->type, ui::mojom::EventType::KEY_RELEASED);
+        ASSERT_EQ(release_event->key_data->key_code, ui::VKEY_X);
+        // TODO(b/307553499): Update SyntheticKeyEvent to use dom_code and
+        // dom_key.
+        ASSERT_EQ(release_event->key_data->dom_code, 0u);
+        ASSERT_EQ(release_event->key_data->dom_key, 0);
+        ASSERT_FALSE(release_event->key_data->is_char);
+        ASSERT_EQ(release_event->flags, ui::EF_NONE);
+
+        waiter.Quit();
+      }));
+
+  ExecuteJS(R"JS(
+    chrome.accessibilityPrivate.sendSyntheticKeyEvent(
+        {type: 'keydown', keyCode: /*X=*/ 88});
+    chrome.accessibilityPrivate.sendSyntheticKeyEvent(
+        {type: 'keyup', keyCode: /*X=*/ 88});
+  )JS");
+  waiter.Run();
+}
+
+TEST_F(AccessibilityPrivateJSApiTest,
+       SendSyntheticKeyEventForShortcutOrNavigationWithModifiers) {
+  base::RunLoop waiter;
+
+  client_->SetSyntheticKeyEventCallback(base::BindLambdaForTesting([&waiter,
+                                                                    this]() {
+    const std::vector<mojom::SyntheticKeyEventPtr>& events =
+        client_->GetKeyEvents();
+    if (events.size() < 2) {
+      return;
+    }
+
+    ASSERT_EQ(events.size(), 2u);
+
+    auto& press_event = events[0];
+    ASSERT_EQ(press_event->type, ui::mojom::EventType::KEY_PRESSED);
+    ASSERT_EQ(press_event->key_data->key_code, ui::VKEY_ESCAPE);
+    // TODO(b/307553499): Update SyntheticKeyEvent to use dom_code and  dom_key.
+    ASSERT_EQ(press_event->key_data->dom_code, 0u);
+    ASSERT_EQ(press_event->key_data->dom_key, 0);
+    ASSERT_FALSE(press_event->key_data->is_char);
+    ASSERT_EQ(press_event->flags, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
+                                      ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+
+    auto& release_event = events[1];
+    ASSERT_EQ(release_event->type, ui::mojom::EventType::KEY_RELEASED);
+    ASSERT_EQ(release_event->key_data->key_code, ui::VKEY_ESCAPE);
+    // TODO(b/307553499): Update SyntheticKeyEvent to use dom_code and dom_key.
+    ASSERT_EQ(release_event->key_data->dom_code, 0u);
+    ASSERT_EQ(release_event->key_data->dom_key, 0);
+    ASSERT_FALSE(release_event->key_data->is_char);
+    ASSERT_EQ(release_event->flags, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
+                                        ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+
+    waiter.Quit();
+  }));
+
+  ExecuteJS(R"JS(
+    chrome.accessibilityPrivate.sendSyntheticKeyEvent({
+      type: 'keydown',
+      keyCode: /*ESC=*/ 27,
+      modifiers: {
+        alt: true,
+        ctrl: true,
+        search: true,
+        shift: true,
+      },
+    });
+
+    chrome.accessibilityPrivate.sendSyntheticKeyEvent({
+      type: 'keyup',
+      keyCode: /*ESC=*/ 27,
+      modifiers: {
+        alt: true,
+        ctrl: true,
+        search: true,
+        shift: true,
+      },
+    });
+  )JS");
+
+  waiter.Run();
+}
+
 class SpeechRecognitionJSApiTest : public AtpJSApiTest {
  public:
   SpeechRecognitionJSApiTest() = default;
diff --git a/services/accessibility/features/javascript/accessibility_private.js b/services/accessibility/features/javascript/accessibility_private.js
index 402c14a..0b95130 100644
--- a/services/accessibility/features/javascript/accessibility_private.js
+++ b/services/accessibility/features/javascript/accessibility_private.js
@@ -58,6 +58,12 @@
     BELOW_ACCESSIBILITY_BUBBLES: 'belowAccessibilityBubbles',
   };
 
+  /** @enum {string} */
+  SyntheticKeyboardEventType = {
+    KEYUP: 'keyup',
+    KEYDOWN: 'keydown',
+  };
+
   constructor() {
     // This is a singleton.
     console.assert(!chrome.accessibilityPrivate);
@@ -88,11 +94,25 @@
 
     // Private members.
 
+    this.userInputRemote_ = null;
     this.userInterfaceRemote_ = null;
     this.autoclickRemote_ = null;
   }
 
   /**
+   * Load user input remote on-demand. Not every consumer of
+   * AccessibilityPrivate will need this; this way we don't need to load the
+   * generated JS bindings for UserInput for every consumer.
+   * @return {!ax.mojom.UserInputRemote}
+   */
+  getUserInputRemote_() {
+    if (!this.userInputRemote_) {
+      this.userInputRemote_ = ax.mojom.UserInput.getRemote();
+    }
+    return this.userInputRemote_;
+  }
+
+  /**
    * Load user interface remote on-demand. Not every consumer of
    * AccessibilityPrivate will need this; this way we don't need
    * to load the generated JS bindings for UserInterface for
@@ -119,6 +139,56 @@
   }
 
   /**
+   * Sends the given synthetic key event.
+   * Synthetic key events are only used for simulated keyboard navigation, and
+   * do not support internationalization. Any text entry should be done via IME.
+   *
+   * @param {!chrome.accessibilityPrivate.SyntheticKeyboardEvent} keyEvent
+   * @param {boolean} useRewriters (Deprecated)
+   */
+  sendSyntheticKeyEvent(keyEvent, useRewriters) {
+    let mojomKeyEvent = new ax.mojom.SyntheticKeyEvent();
+    switch (keyEvent.type) {
+      case this.SyntheticKeyboardEventType.KEYDOWN:
+        mojomKeyEvent.type = ui.mojom.EventType.KEY_PRESSED;
+        break;
+      case this.SyntheticKeyboardEventType.KEYUP:
+        mojomKeyEvent.type = ui.mojom.EventType.KEY_RELEASED;
+        break;
+      default:
+        console.error('Unknown key event type', keyEvent.type);
+        return;
+    }
+
+    mojomKeyEvent.keyData = new ui.mojom.KeyData();
+    mojomKeyEvent.keyData.keyCode = keyEvent.keyCode;
+    // TODO(b/307553499): Update SyntheticKeyEvent to use dom_code and dom_key.
+    mojomKeyEvent.keyData.domCode = 0;
+    mojomKeyEvent.keyData.domKey = 0;
+    mojomKeyEvent.keyData.isChar = false;
+
+    mojomKeyEvent.flags = ui.mojom.EVENT_FLAG_NONE;
+
+    if (keyEvent.modifiers) {
+      if (keyEvent.modifiers.alt) {
+        mojomKeyEvent.flags |= ui.mojom.EVENT_FLAG_ALT_DOWN;
+      }
+      if (keyEvent.modifiers.ctrl) {
+        mojomKeyEvent.flags |= ui.mojom.EVENT_FLAG_CONTROL_DOWN;
+      }
+      if (keyEvent.modifiers.search) {
+        mojomKeyEvent.flags |= ui.mojom.EVENT_FLAG_COMMAND_DOWN;
+      }
+      if (keyEvent.modifiers.shift) {
+        mojomKeyEvent.flags |= ui.mojom.EVENT_FLAG_SHIFT_DOWN;
+      }
+    }
+
+    this.getUserInputRemote_().sendSyntheticKeyEventForShortcutOrNavigation(
+        mojomKeyEvent);
+  }
+
+  /**
    * Darkens or undarkens the screen.
    * @param {boolean} darken
    */
diff --git a/services/accessibility/features/user_input_interface_binder.cc b/services/accessibility/features/user_input_interface_binder.cc
new file mode 100644
index 0000000..a73d4a55
--- /dev/null
+++ b/services/accessibility/features/user_input_interface_binder.cc
@@ -0,0 +1,28 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/accessibility/features/user_input_interface_binder.h"
+
+#include "services/accessibility/public/mojom/accessibility_service.mojom.h"
+#include "services/accessibility/public/mojom/user_input.mojom.h"
+
+namespace ax {
+
+UserInputInterfaceBinder::UserInputInterfaceBinder(
+    mojom::AccessibilityServiceClient* ax_service_client)
+    : ax_service_client_(ax_service_client) {}
+
+UserInputInterfaceBinder::~UserInputInterfaceBinder() = default;
+
+bool UserInputInterfaceBinder::MatchesInterface(
+    const std::string& interface_name) {
+  return interface_name == "ax.mojom.UserInput";
+}
+
+void UserInputInterfaceBinder::BindReceiver(
+    mojo::GenericPendingReceiver receiver) {
+  ax_service_client_->BindUserInput(receiver.As<ax::mojom::UserInput>());
+}
+
+}  // namespace ax
diff --git a/services/accessibility/features/user_input_interface_binder.h b/services/accessibility/features/user_input_interface_binder.h
new file mode 100644
index 0000000..3f30370cc
--- /dev/null
+++ b/services/accessibility/features/user_input_interface_binder.h
@@ -0,0 +1,36 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_ACCESSIBILITY_FEATURES_USER_INPUT_INTERFACE_BINDER_H_
+#define SERVICES_ACCESSIBILITY_FEATURES_USER_INPUT_INTERFACE_BINDER_H_
+
+#include "services/accessibility/features/interface_binder.h"
+#include "services/accessibility/public/mojom/accessibility_service.mojom.h"
+
+namespace ax {
+
+// Bind one end of a mojom UserInput pipe hosted in Javascript to the
+// AccessibilityServiceClient that connects back to the main OS process.
+class UserInputInterfaceBinder : public InterfaceBinder {
+ public:
+  explicit UserInputInterfaceBinder(
+      mojom::AccessibilityServiceClient* ax_service_client);
+  ~UserInputInterfaceBinder() override;
+  UserInputInterfaceBinder(const UserInputInterfaceBinder&) = delete;
+  UserInputInterfaceBinder& operator=(const UserInputInterfaceBinder&) = delete;
+
+  // InterfaceBinder:
+  bool MatchesInterface(const std::string& interface_name) override;
+  void BindReceiver(mojo::GenericPendingReceiver receiver) override;
+
+ private:
+  // The caller must ensure the client outlives `this`. Here this is guaranteed
+  // because the client is always a `AssistiveTechnologyControllerImpl`, which
+  // transitively owns `this` via `V8Manager`.
+  raw_ptr<mojom::AccessibilityServiceClient> ax_service_client_;
+};
+
+}  // namespace ax
+
+#endif  // SERVICES_ACCESSIBILITY_FEATURES_USER_INPUT_INTERFACE_BINDER_H_
diff --git a/services/accessibility/features/v8_manager.cc b/services/accessibility/features/v8_manager.cc
index b3c0f4f..0a20f4c 100644
--- a/services/accessibility/features/v8_manager.cc
+++ b/services/accessibility/features/v8_manager.cc
@@ -26,6 +26,7 @@
 #include "services/accessibility/features/speech_recognition_interface_binder.h"
 #include "services/accessibility/features/sync_os_state_api_bindings.h"
 #include "services/accessibility/features/tts_interface_binder.h"
+#include "services/accessibility/features/user_input_interface_binder.h"
 #include "services/accessibility/features/user_interface_interface_binder.h"
 #include "services/accessibility/features/v8_bindings_utils.h"
 #include "services/accessibility/public/mojom/accessibility_service.mojom-forward.h"
@@ -283,11 +284,20 @@
       std::make_unique<TtsInterfaceBinder>(ax_service_client));
 }
 
+void V8Manager::ConfigureUserInput(
+    mojom::AccessibilityServiceClient* ax_service_client) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(b/262637071): load the AccessibilityPrivate JS shim into V8 using
+  // v8_env_.AsyncCall if it isn't already loaded.
+  interface_binders_.push_back(
+      std::make_unique<UserInputInterfaceBinder>(ax_service_client));
+}
+
 void V8Manager::ConfigureUserInterface(
     mojom::AccessibilityServiceClient* ax_service_client) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // TODO(b/262637071): load the AccessibilityPrivate JS shim into V8 using
-  // v8_env_.AsyncCall.
+  // v8_env_.AsyncCall if it isn't already loaded.
   interface_binders_.push_back(
       std::make_unique<UserInterfaceInterfaceBinder>(ax_service_client));
 }
diff --git a/services/accessibility/features/v8_manager.h b/services/accessibility/features/v8_manager.h
index 6a906ae..46e59ca9 100644
--- a/services/accessibility/features/v8_manager.h
+++ b/services/accessibility/features/v8_manager.h
@@ -143,6 +143,7 @@
   void ConfigureSpeechRecognition(
       mojom::AccessibilityServiceClient* ax_service_client);
   void ConfigureTts(mojom::AccessibilityServiceClient* ax_service_client);
+  void ConfigureUserInput(mojom::AccessibilityServiceClient* ax_service_client);
   void ConfigureUserInterface(
       mojom::AccessibilityServiceClient* ax_service_client);
 
diff --git a/services/accessibility/public/mojom/BUILD.gn b/services/accessibility/public/mojom/BUILD.gn
index 5637a8b4..1225a2e 100644
--- a/services/accessibility/public/mojom/BUILD.gn
+++ b/services/accessibility/public/mojom/BUILD.gn
@@ -45,25 +45,33 @@
       "file_loader.mojom",
       "speech_recognition.mojom",
       "tts.mojom",
+      "user_input.mojom",
       "user_interface.mojom",
     ]
     public_deps = [
       ":assistive_technology_type",
       "//mojo/public/mojom/base",
       "//skia/public/mojom:mojom",
+      "//ui/events/mojom:mojom",
       "//ui/gfx/geometry/mojom",
+      "//ui/latency/mojom:mojom",
     ]
   }
 
   group("os_accessibility_service_js") {
     testonly = true
     data = [
+      "$root_gen_dir/mojo/public/mojom/base/time.mojom-lite.js",
       "$root_gen_dir/skia/public/mojom/skcolor.mojom-lite.js",
+      "$root_gen_dir/ui/events/mojom/event_constants.mojom-lite.js",
+      "$root_gen_dir/ui/events/mojom/event.mojom-lite.js",
       "$root_gen_dir/ui/gfx/geometry/mojom/geometry.mojom-lite.js",
+      "$root_gen_dir/ui/latency/mojom/latency_info.mojom-lite.js",
       "$target_gen_dir/assistive_technology_type.mojom-lite.js",
       "$target_gen_dir/autoclick.mojom-lite.js",
       "$target_gen_dir/speech_recognition.mojom-lite.js",
       "$target_gen_dir/tts.mojom-lite.js",
+      "$target_gen_dir/user_input.mojom-lite.js",
       "$target_gen_dir/user_interface.mojom-lite.js",
     ]
     deps = [
diff --git a/services/accessibility/public/mojom/OWNERS b/services/accessibility/public/mojom/OWNERS
index 08850f4..f486cf5 100644
--- a/services/accessibility/public/mojom/OWNERS
+++ b/services/accessibility/public/mojom/OWNERS
@@ -1,2 +1,5 @@
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/services/accessibility/public/mojom/accessibility_service.mojom b/services/accessibility/public/mojom/accessibility_service.mojom
index c3c9a81..2359160b 100644
--- a/services/accessibility/public/mojom/accessibility_service.mojom
+++ b/services/accessibility/public/mojom/accessibility_service.mojom
@@ -14,6 +14,8 @@
 [EnableIf=supports_os_accessibility_service]
 import "third_party/blink/public/mojom/devtools/devtools_agent.mojom";
 [EnableIf=supports_os_accessibility_service]
+import "services/accessibility/public/mojom/user_input.mojom";
+[EnableIf=supports_os_accessibility_service]
 import "services/accessibility/public/mojom/user_interface.mojom";
 [EnableIf=supports_os_accessibility_service]
 import "services/accessibility/public/mojom/assistive_technology_type.mojom";
@@ -95,6 +97,11 @@
   [EnableIf=supports_os_accessibility_service]
   BindTts(pending_receiver<Tts> tts_receiver);
 
+  // Binds to a User Input client implemented in the main OS process,
+  // called by the service.
+  [EnableIf=supports_os_accessibility_service]
+  BindUserInput(pending_receiver<UserInput> user_input_receiver);
+
   // Binds to a User Interface client implemented in the main OS process,
   // called by the service.
   [EnableIf=supports_os_accessibility_service]
diff --git a/services/accessibility/public/mojom/user_input.mojom b/services/accessibility/public/mojom/user_input.mojom
new file mode 100644
index 0000000..5bbcfad
--- /dev/null
+++ b/services/accessibility/public/mojom/user_input.mojom
@@ -0,0 +1,30 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module ax.mojom;
+
+import "ui/events/mojom/event.mojom";
+import "ui/events/mojom/event_constants.mojom";
+
+// Represents a synthetic key event.
+struct SyntheticKeyEvent {
+  // The type of key event, either key press or key release.
+  ui.mojom.EventType type;
+
+  // The key code for the key event.
+  ui.mojom.KeyData key_data;
+
+  // Any modifier keys that are held down.
+  int32 flags;
+};
+
+// Provides a means of synthetic user input. Implemented in the main OS browser
+// process and called from Accessibility Service javascript in V8.
+//
+// Synthetic key events are only used for simulated keyboard navigation, and
+// do not support internationalization. Any text entry should be done via IME.
+interface UserInput {
+  // Sends a synthetic key event.
+  SendSyntheticKeyEventForShortcutOrNavigation(SyntheticKeyEvent key_event);
+};
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 9eb5a07..c1e5ec4 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -6122,9 +6122,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6134,8 +6134,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -6272,9 +6272,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6284,8 +6284,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index ab7bd0b..3127de471 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -20593,9 +20593,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20605,8 +20605,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -20743,9 +20743,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -20755,8 +20755,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 2d6ee910..25ca7b5d 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -43731,9 +43731,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43742,8 +43742,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -43881,9 +43881,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43892,8 +43892,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -45205,9 +45205,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45216,8 +45216,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -45355,9 +45355,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -45366,8 +45366,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -46065,9 +46065,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -46076,8 +46076,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 9781238..8ee2c7c 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -16312,12 +16312,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16327,8 +16327,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
@@ -16482,12 +16482,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.filter;../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 121.0.6149.0",
+        "description": "Run with ash-chrome version 121.0.6151.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16497,8 +16497,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v121.0.6149.0",
-              "revision": "version:121.0.6149.0"
+              "location": "lacros_version_skew_tests_v121.0.6151.0",
+              "revision": "version:121.0.6151.0"
             }
           ],
           "dimensions": {
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 74845fbe..af49a6f 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -70,16 +70,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'identifier': 'Lacros version skew testing ash canary',
-    'description': 'Run with ash-chrome version 121.0.6149.0',
+    'description': 'Run with ash-chrome version 121.0.6151.0',
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6149.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v121.0.6151.0/test_ash_chrome',
     ],
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v121.0.6149.0',
-          'revision': 'version:121.0.6149.0',
+          'location': 'lacros_version_skew_tests_v121.0.6151.0',
+          'revision': 'version:121.0.6151.0',
         },
       ],
     },
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index 3701449..62cabe43 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -1031,7 +1031,7 @@
   friend class WhitespaceAttacherTest;
   friend class StyleCascadeTest;
   friend class StyleImageCacheTest;
-  FRIEND_TEST_ALL_PREFIXES(NGBlockChildIteratorTest, DeleteNodeWhileIteration);
+  FRIEND_TEST_ALL_PREFIXES(BlockChildIteratorTest, DeleteNodeWhileIteration);
 
   HeapHashSet<Member<TextTrack>> text_tracks_;
   Member<Element> vtt_originating_element_;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 8817d325..cfa49cc 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2075,7 +2075,7 @@
 
   Vector<PhysicalRect> outline_rects = layout_object->OutlineRects(
       nullptr, PhysicalOffset(),
-      layout_object->StyleRef().OutlineRectsShouldIncludeBlockVisualOverflow());
+      layout_object->StyleRef().OutlineRectsShouldIncludeBlockInkOverflow());
   for (auto& r : outline_rects) {
     PhysicalRect physical_rect = layout_object->LocalToAbsoluteRect(r);
     gfx::Rect absolute_rect =
diff --git a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
index 069e780..816971f 100644
--- a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -223,7 +223,8 @@
                IsMenuList(first_letter_text_layout_object)) {
       return nullptr;
     } else if (first_letter_text_layout_object->IsFlexibleBox() ||
-               first_letter_text_layout_object->IsLayoutGrid()) {
+               first_letter_text_layout_object->IsLayoutGrid() ||
+               first_letter_text_layout_object->IsMathML()) {
       first_letter_text_layout_object =
           first_letter_text_layout_object->NextSibling();
     } else if (!first_letter_text_layout_object->IsInline() &&
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
index c4bcfaa..366fce8 100644
--- a/third_party/blink/renderer/core/html/anchor_element_metrics.cc
+++ b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -129,7 +129,7 @@
 // overflows.
 gfx::Rect AbsoluteElementBoundingBoxRect(const LayoutObject& layout_object) {
   Vector<PhysicalRect> rects = layout_object.OutlineRects(
-      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, PhysicalOffset(), OutlineType::kIncludeBlockInkOverflow);
   return ToEnclosingRect(layout_object.LocalToAbsoluteRect(UnionRect(rects)));
 }
 
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.cc b/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.cc
index 10d7062e5..20bc0e9a 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.cc
@@ -78,7 +78,7 @@
   return MinMaxSizesResult(sizes, depends_on_block_constraints);
 }
 
-const NGLayoutResult* CustomLayoutAlgorithm::Layout() {
+const LayoutResult* CustomLayoutAlgorithm::Layout() {
   DCHECK(!IsBreakInside(GetBreakToken()));
 
   if (!Node().IsCustomLayoutLoaded())
@@ -206,7 +206,7 @@
   return BlockLayoutAlgorithm(params_).ComputeMinMaxSizes(input);
 }
 
-const NGLayoutResult* CustomLayoutAlgorithm::FallbackLayout() {
+const LayoutResult* CustomLayoutAlgorithm::FallbackLayout() {
   return BlockLayoutAlgorithm(params_).Layout();
 }
 
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.h b/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.h
index 53c90ba8..0c17e72 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_algorithm.h
@@ -19,12 +19,12 @@
   explicit CustomLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
  private:
   void AddAnyOutOfFlowPositionedChildren(LayoutInputNode* child);
   MinMaxSizesResult FallbackMinMaxSizes(const MinMaxSizesFloatInput&) const;
-  const NGLayoutResult* FallbackLayout();
+  const LayoutResult* FallbackLayout();
 
   const LayoutAlgorithmParams& params_;
 };
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc b/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
index f08fed3..18b7879 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
@@ -14,7 +14,7 @@
 CustomLayoutFragment::CustomLayoutFragment(
     CustomLayoutChild* child,
     CustomLayoutToken* token,
-    const NGLayoutResult* layout_result,
+    const LayoutResult* layout_result,
     const LogicalSize& size,
     const absl::optional<LayoutUnit> baseline,
     v8::Isolate* isolate)
@@ -30,7 +30,7 @@
     layout_worklet_world_v8_data_.Reset(isolate, data->Deserialize(isolate));
 }
 
-const NGLayoutResult& CustomLayoutFragment::GetLayoutResult() const {
+const LayoutResult& CustomLayoutFragment::GetLayoutResult() const {
   DCHECK(layout_result_);
   return *layout_result_;
 }
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h b/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
index fe44d8f..b477855 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
@@ -16,7 +16,7 @@
 class CustomLayoutChild;
 class LayoutBox;
 class LayoutInputNode;
-class NGLayoutResult;
+class LayoutResult;
 class ScriptState;
 class ScriptValue;
 struct LogicalSize;
@@ -37,7 +37,7 @@
  public:
   CustomLayoutFragment(CustomLayoutChild*,
                        CustomLayoutToken*,
-                       const NGLayoutResult*,
+                       const LayoutResult*,
                        const LogicalSize& size,
                        const absl::optional<LayoutUnit> baseline,
                        v8::Isolate*);
@@ -58,7 +58,7 @@
 
   ScriptValue data(ScriptState*) const;
 
-  const NGLayoutResult& GetLayoutResult() const;
+  const LayoutResult& GetLayoutResult() const;
   const LayoutInputNode& GetLayoutNode() const;
 
   bool IsValid() const { return token_->IsValid(); }
@@ -83,7 +83,7 @@
   // that the last layout on the child wasn't with the same inputs, and force a
   // layout again.
 
-  Member<const NGLayoutResult> layout_result_;
+  Member<const LayoutResult> layout_result_;
 
   // The inline and block size on this object should never change.
   const double inline_size_;
diff --git a/third_party/blink/renderer/core/layout/custom/custom_layout_work_task.cc b/third_party/blink/renderer/core/layout/custom/custom_layout_work_task.cc
index b5a26cd..428c39807 100644
--- a/third_party/blink/renderer/core/layout/custom/custom_layout_work_task.cc
+++ b/third_party/blink/renderer/core/layout/custom/custom_layout_work_task.cc
@@ -141,7 +141,7 @@
 
   LogicalBoxFragment fragment(
       parent_space.GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
 
   resolver_->Resolve(MakeGarbageCollected<CustomLayoutFragment>(
       child_, token_, std::move(result), fragment.Size(),
diff --git a/third_party/blink/renderer/core/layout/exclusions/exclusion_space.h b/third_party/blink/renderer/core/layout/exclusions/exclusion_space.h
index 6025cb98..df54d35a 100644
--- a/third_party/blink/renderer/core/layout/exclusions/exclusion_space.h
+++ b/third_party/blink/renderer/core/layout/exclusions/exclusion_space.h
@@ -702,7 +702,7 @@
     exclusion_space_->MoveDerivedGeometry(*other.exclusion_space_);
   }
 
-  // This produces a new exclusion space for a |NGLayoutResult| which is being
+  // This produces a new exclusion space for a |LayoutResult| which is being
   // re-used for caching purposes.
   //
   // It takes:
diff --git a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc
index 98e0e68..bf5c3b5 100644
--- a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.cc
@@ -806,7 +806,7 @@
           child_style.BoxSizingForAspectRatio(), cross_size);
     };
 
-    const NGLayoutResult* layout_result = nullptr;
+    const LayoutResult* layout_result = nullptr;
     auto IntrinsicBlockSizeFunc =
         [&](MinMaxSizesType type = MinMaxSizesType::kIntrinsic) -> LayoutUnit {
       if (type == MinMaxSizesType::kContent && child.HasAspectRatio() &&
@@ -1052,26 +1052,26 @@
   return min_max.ClampSizeToMinAndMax(main_axis_size);
 }
 
-const NGLayoutResult* FlexLayoutAlgorithm::Layout() {
+const LayoutResult* FlexLayoutAlgorithm::Layout() {
   auto* result = LayoutInternal();
   switch (result->Status()) {
-    case NGLayoutResult::kNeedsEarlierBreak:
+    case LayoutResult::kNeedsEarlierBreak:
       // If we found a good break somewhere inside this block, re-layout and
       // break at that location.
       return RelayoutAndBreakEarlierForFlex(result);
-    case NGLayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges:
+    case LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges:
       return RelayoutIgnoringChildScrollbarChanges();
-    case NGLayoutResult::kDisableFragmentation:
+    case LayoutResult::kDisableFragmentation:
       DCHECK(GetConstraintSpace().HasBlockFragmentation());
       return RelayoutWithoutFragmentation<FlexLayoutAlgorithm>();
-    case NGLayoutResult::kNeedsRelayoutWithRowCrossSizeChanges:
+    case LayoutResult::kNeedsRelayoutWithRowCrossSizeChanges:
       return RelayoutWithNewRowSizes();
     default:
       return result;
   }
 }
 
-const NGLayoutResult*
+const LayoutResult*
 FlexLayoutAlgorithm::RelayoutIgnoringChildScrollbarChanges() {
   DCHECK(!ignore_child_scrollbar_changes_);
   LayoutAlgorithmParams params(
@@ -1082,8 +1082,8 @@
   return algorithm.Layout();
 }
 
-const NGLayoutResult* FlexLayoutAlgorithm::RelayoutAndBreakEarlierForFlex(
-    const NGLayoutResult* previous_result) {
+const LayoutResult* FlexLayoutAlgorithm::RelayoutAndBreakEarlierForFlex(
+    const LayoutResult* previous_result) {
   DCHECK(previous_result->GetEarlyBreak());
   LayoutAlgorithmParams params(
       Node(), container_builder_.InitialFragmentGeometry(),
@@ -1095,7 +1095,7 @@
   return RelayoutAndBreakEarlier(&algorithm_with_break);
 }
 
-const NGLayoutResult* FlexLayoutAlgorithm::LayoutInternal() {
+const LayoutResult* FlexLayoutAlgorithm::LayoutInternal() {
   // Freezing the scrollbars for the sub-tree shouldn't be strictly necessary,
   // but we do this just in case we trigger an unstable layout.
   absl::optional<PaintLayerScrollableArea::FreezeScrollbarsScope>
@@ -1138,10 +1138,11 @@
 
   if (!IsBreakInside(GetBreakToken())) {
     ApplyFinalAlignmentAndReversals(&flex_line_outputs);
-    NGLayoutResult::EStatus status = GiveItemsFinalPositionAndSize(
+    LayoutResult::EStatus status = GiveItemsFinalPositionAndSize(
         &flex_line_outputs, &row_break_between_outputs);
-    if (status != NGLayoutResult::kSuccess)
+    if (status != LayoutResult::kSuccess) {
       return container_builder_.Abort(status);
+    }
   }
 
   LayoutUnit previously_consumed_block_size;
@@ -1159,11 +1160,12 @@
               .ClampNegativeToZero();
     }
 
-    NGLayoutResult::EStatus status =
+    LayoutResult::EStatus status =
         GiveItemsFinalPositionAndSizeForFragmentation(
             &flex_line_outputs, &row_break_between_outputs, &break_before_row);
-    if (status != NGLayoutResult::kSuccess)
+    if (status != LayoutResult::kSuccess) {
       return container_builder_.Abort(status);
+    }
 
     intrinsic_block_size_ = ClampIntrinsicBlockSize(
         GetConstraintSpace(), Node(), GetBreakToken(), BorderScrollbarPadding(),
@@ -1194,10 +1196,10 @@
         FragmentainerSpaceLeft(GetConstraintSpace()), &container_builder_);
     if (break_status != BreakStatus::kContinue) {
       if (break_status == BreakStatus::kNeedsEarlierBreak) {
-        return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+        return container_builder_.Abort(LayoutResult::kNeedsEarlierBreak);
       }
       DCHECK_EQ(break_status, BreakStatus::kDisableFragmentation);
-      return container_builder_.Abort(NGLayoutResult::kDisableFragmentation);
+      return container_builder_.Abort(LayoutResult::kDisableFragmentation);
     }
   } else {
 #if DCHECK_IS_ON()
@@ -1330,11 +1332,11 @@
         flex_item.layout_result_ = flex_item.ng_input_node_.Layout(
             child_space, nullptr /*break token*/);
         // TODO(layout-dev): Handle abortions caused by block fragmentation.
-        DCHECK_EQ(flex_item.layout_result_->Status(), NGLayoutResult::kSuccess);
+        DCHECK_EQ(flex_item.layout_result_->Status(), LayoutResult::kSuccess);
         flex_item.cross_axis_size_ =
             is_horizontal_flow_
-                ? flex_item.layout_result_->PhysicalFragment().Size().height
-                : flex_item.layout_result_->PhysicalFragment().Size().width;
+                ? flex_item.layout_result_->GetPhysicalFragment().Size().height
+                : flex_item.layout_result_->GetPhysicalFragment().Size().width;
       }
     }
     // cross_axis_offset is updated in each iteration of the loop, for passing
@@ -1407,7 +1409,7 @@
   }
 }
 
-NGLayoutResult::EStatus FlexLayoutAlgorithm::GiveItemsFinalPositionAndSize(
+LayoutResult::EStatus FlexLayoutAlgorithm::GiveItemsFinalPositionAndSize(
     HeapVector<NGFlexLine>* flex_line_outputs,
     Vector<EBreakBetween>* row_break_between_outputs) {
   DCHECK(!IsBreakInside(GetBreakToken()));
@@ -1441,7 +1443,7 @@
   }
 
   BaselineAccumulator baseline_accumulator(Style());
-  NGLayoutResult::EStatus status = NGLayoutResult::kSuccess;
+  LayoutResult::EStatus status = LayoutResult::kSuccess;
 
   for (wtf_size_t flex_line_idx = 0; flex_line_idx < flex_line_outputs->size();
        ++flex_line_idx) {
@@ -1461,7 +1463,7 @@
 
       LogicalOffset offset = flex_item.offset.ToLogicalOffset(is_column_);
 
-      const NGLayoutResult* layout_result = nullptr;
+      const LayoutResult* layout_result = nullptr;
       if (DoesItemStretch(flex_item.ng_input_node)) {
         ConstraintSpace child_space = BuildSpaceForLayout(
             flex_item.ng_input_node, flex_item.main_axis_final_size,
@@ -1517,7 +1519,7 @@
       }
 
       const auto& physical_fragment =
-          To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+          To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
 
       const auto writing_direction = GetConstraintSpace().GetWritingDirection();
       LogicalBoxFragment fragment(writing_direction, physical_fragment);
@@ -1533,8 +1535,8 @@
 
       if (PropagateFlexItemInfo(item, flex_line_idx, offset,
                                 physical_fragment.Size()) ==
-          NGLayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges) {
-        status = NGLayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
+          LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges) {
+        status = LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
       }
     }
   }
@@ -1558,7 +1560,7 @@
   return status;
 }
 
-NGLayoutResult::EStatus
+LayoutResult::EStatus
 FlexLayoutAlgorithm::GiveItemsFinalPositionAndSizeForFragmentation(
     HeapVector<NGFlexLine>* flex_line_outputs,
     Vector<EBreakBetween>* row_break_between_outputs,
@@ -1574,7 +1576,7 @@
   Vector<bool> has_inflow_child_break_inside_line(flex_line_outputs->size(),
                                                   false);
   bool needs_earlier_break_in_column = false;
-  NGLayoutResult::EStatus status = NGLayoutResult::kSuccess;
+  LayoutResult::EStatus status = LayoutResult::kSuccess;
   LayoutUnit fragmentainer_space = FragmentainerSpaceLeft(GetConstraintSpace());
 
   HeapVector<FlexColumnBreakInfo> column_break_info;
@@ -1741,7 +1743,7 @@
           if (!last_item_in_line)
             item_iterator.NextLine();
         } else if (last_item_in_line) {
-          DCHECK_EQ(status, NGLayoutResult::kSuccess);
+          DCHECK_EQ(status, LayoutResult::kSuccess);
           break;
         }
         last_line_idx_to_process_first_child_ = flex_line_idx;
@@ -1797,7 +1799,7 @@
         flex_item->ng_input_node, flex_item->main_axis_final_size,
         /* override_inline_size */ absl::nullopt, line_cross_size_for_stretch,
         offset.block_offset, min_block_size_should_encompass_intrinsic_size);
-    const NGLayoutResult* layout_result = flex_item->ng_input_node.Layout(
+    const LayoutResult* layout_result = flex_item->ng_input_node.Layout(
         child_space, item_break_token, early_break_in_child);
 
     BreakStatus break_status = BreakStatus::kContinue;
@@ -1832,12 +1834,12 @@
             } else {
               *break_before_row = FlexBreakTokenData::kAtStartOfBreakBeforeRow;
             }
-            DCHECK_EQ(status, NGLayoutResult::kSuccess);
+            DCHECK_EQ(status, LayoutResult::kSuccess);
             break;
           }
           *break_before_row = FlexBreakTokenData::kNotBreakBeforeRow;
           if (row_break_status == BreakStatus::kNeedsEarlierBreak) {
-            status = NGLayoutResult::kNeedsEarlierBreak;
+            status = LayoutResult::kNeedsEarlierBreak;
             break;
           }
           DCHECK_EQ(row_break_status, BreakStatus::kContinue);
@@ -1885,7 +1887,7 @@
           item_iterator.NextLine();
         continue;
       }
-      status = NGLayoutResult::kNeedsEarlierBreak;
+      status = LayoutResult::kNeedsEarlierBreak;
       break;
     }
 
@@ -1900,7 +1902,7 @@
         if (!last_item_in_line)
           item_iterator.NextLine();
       } else if (last_item_in_line) {
-        DCHECK_EQ(status, NGLayoutResult::kSuccess);
+        DCHECK_EQ(status, LayoutResult::kSuccess);
         break;
       }
       last_line_idx_to_process_first_child_ = flex_line_idx;
@@ -1908,7 +1910,7 @@
     }
 
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
 
     LogicalBoxFragment fragment(GetConstraintSpace().GetWritingDirection(),
                                 physical_fragment);
@@ -2020,12 +2022,13 @@
   }
 
   if (needs_earlier_break_in_column ||
-      status == NGLayoutResult::kNeedsEarlierBreak)
-    return NGLayoutResult::kNeedsEarlierBreak;
+      status == LayoutResult::kNeedsEarlierBreak) {
+    return LayoutResult::kNeedsEarlierBreak;
+  }
 
   if (!row_cross_size_updates_.empty()) {
     DCHECK(!is_column_);
-    return NGLayoutResult::kNeedsRelayoutWithRowCrossSizeChanges;
+    return LayoutResult::kNeedsRelayoutWithRowCrossSizeChanges;
   }
 
   if (!container_builder_.HasInflowChildBreakInside() &&
@@ -2046,13 +2049,13 @@
   return status;
 }
 
-NGLayoutResult::EStatus FlexLayoutAlgorithm::PropagateFlexItemInfo(
+LayoutResult::EStatus FlexLayoutAlgorithm::PropagateFlexItemInfo(
     FlexItem* flex_item,
     wtf_size_t flex_line_idx,
     LogicalOffset offset,
     PhysicalSize fragment_size) {
   DCHECK(flex_item);
-  NGLayoutResult::EStatus status = NGLayoutResult::kSuccess;
+  LayoutResult::EStatus status = LayoutResult::kSuccess;
 
   if (UNLIKELY(layout_info_for_devtools_)) {
     // If this is a "devtools layout", execution speed isn't critical but we
@@ -2082,13 +2085,13 @@
   if (!ignore_child_scrollbar_changes_) {
     if (flex_item->scrollbars_ !=
         ComputeScrollbarsForNonAnonymous(flex_item->ng_input_node_))
-      status = NGLayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
+      status = LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
 
     // The flex-item scrollbars may not have changed, but an descendant's
     // scrollbars might have causing the min/max sizes to be incorrect.
     if (flex_item->depends_on_min_max_sizes_ &&
         flex_item->ng_input_node_.GetLayoutBox()->IntrinsicLogicalWidthsDirty())
-      status = NGLayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
+      status = LayoutResult::kNeedsRelayoutWithNoChildScrollbarChanges;
   } else {
     DCHECK_EQ(flex_item->scrollbars_,
               ComputeScrollbarsForNonAnonymous(flex_item->ng_input_node_));
@@ -2417,9 +2420,8 @@
   bool breakable_at_start_of_container = IsBreakableAtStartOfResumedContainer(
       GetConstraintSpace(), container_builder_, is_first_for_row);
   BreakAppeal appeal_before = CalculateBreakAppealBefore(
-      GetConstraintSpace(), NGLayoutResult::EStatus::kSuccess,
-      row_break_between, has_container_separation,
-      breakable_at_start_of_container);
+      GetConstraintSpace(), LayoutResult::EStatus::kSuccess, row_break_between,
+      has_container_separation, breakable_at_start_of_container);
 
   // Attempt to move past the break point, and if we can do that, also assess
   // the appeal of breaking there, even if we didn't.
@@ -2508,7 +2510,7 @@
       item_expansion;
 }
 
-const NGLayoutResult* FlexLayoutAlgorithm::RelayoutWithNewRowSizes() {
+const LayoutResult* FlexLayoutAlgorithm::RelayoutWithNewRowSizes() {
   // We shouldn't update the row cross-sizes more than once per fragmentainer.
   DCHECK(!cross_size_adjustments_);
 
diff --git a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h
index bb03c8c..e7163993 100644
--- a/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/flex/flex_layout_algorithm.h
@@ -27,13 +27,13 @@
       const HashMap<wtf_size_t, LayoutUnit>* cross_size_adjustments = nullptr);
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
  private:
-  const NGLayoutResult* RelayoutIgnoringChildScrollbarChanges();
-  const NGLayoutResult* RelayoutAndBreakEarlierForFlex(
-      const NGLayoutResult* previous_result);
-  const NGLayoutResult* LayoutInternal();
+  const LayoutResult* RelayoutIgnoringChildScrollbarChanges();
+  const LayoutResult* RelayoutAndBreakEarlierForFlex(
+      const LayoutResult* previous_result);
+  const LayoutResult* LayoutInternal();
 
   void PlaceFlexItems(
       HeapVector<NGFlexLine>* flex_line_outputs,
@@ -89,17 +89,17 @@
       HeapVector<Member<LayoutBox>>* oof_children = nullptr);
   void ApplyFinalAlignmentAndReversals(
       HeapVector<NGFlexLine>* flex_line_outputs);
-  NGLayoutResult::EStatus GiveItemsFinalPositionAndSize(
+  LayoutResult::EStatus GiveItemsFinalPositionAndSize(
       HeapVector<NGFlexLine>* flex_line_outputs,
       Vector<EBreakBetween>* row_break_between_outputs);
-  NGLayoutResult::EStatus GiveItemsFinalPositionAndSizeForFragmentation(
+  LayoutResult::EStatus GiveItemsFinalPositionAndSizeForFragmentation(
       HeapVector<NGFlexLine>* flex_line_outputs,
       Vector<EBreakBetween>* row_break_between_outputs,
       FlexBreakTokenData::FlexBreakBeforeRow* break_before_row);
-  NGLayoutResult::EStatus PropagateFlexItemInfo(FlexItem* flex_item,
-                                                wtf_size_t flex_line_idx,
-                                                LogicalOffset offset,
-                                                PhysicalSize fragment_size);
+  LayoutResult::EStatus PropagateFlexItemInfo(FlexItem* flex_item,
+                                              wtf_size_t flex_line_idx,
+                                              LogicalOffset offset,
+                                              PhysicalSize fragment_size);
   void LayoutColumnReverse(LayoutUnit main_axis_content_size);
 
   // This is same method as FlexItem but we need that logic before FlexItem is
@@ -168,7 +168,7 @@
   // If a flex item expands past the row cross-size as a result of
   // fragmentation, we will abort and re-run layout with the appropriate row
   // cross-size adjustments.
-  const NGLayoutResult* RelayoutWithNewRowSizes();
+  const LayoutResult* RelayoutWithNewRowSizes();
 
   // Used to determine when to allow an item to expand as a result of
   // fragmentation.
diff --git a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc
index 7a90e0a..98a16dfe 100644
--- a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.cc
@@ -181,7 +181,7 @@
   DCHECK(layout_result_);
   LogicalBoxFragment baseline_fragment(
       baseline_writing_direction_,
-      To<NGPhysicalBoxFragment>(layout_result_->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(layout_result_->GetPhysicalFragment()));
 
   const auto font_baseline = algorithm_->StyleRef().GetFontBaseline();
   LayoutUnit baseline =
diff --git a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h
index d8cad0b..65bd1eb 100644
--- a/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h
+++ b/third_party/blink/renderer/core/layout/flex/flexible_box_algorithm.h
@@ -175,7 +175,7 @@
   // The above fields are used by the flex algorithm. The following fields, by
   // contrast, are just convenient storage.
   BlockNode ng_input_node_;
-  Member<const NGLayoutResult> layout_result_;
+  Member<const LayoutResult> layout_result_;
   absl::optional<LayoutUnit> max_content_contribution_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
index 2671984..f21f6f77 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.cc
@@ -204,16 +204,16 @@
 
 }  // namespace
 
-const NGLayoutResult* GridLayoutAlgorithm::Layout() {
+const LayoutResult* GridLayoutAlgorithm::Layout() {
   const auto* result = LayoutInternal();
-  if (result->Status() == NGLayoutResult::kDisableFragmentation) {
+  if (result->Status() == LayoutResult::kDisableFragmentation) {
     DCHECK(GetConstraintSpace().HasBlockFragmentation());
     return RelayoutWithoutFragmentation<GridLayoutAlgorithm>();
   }
   return result;
 }
 
-const NGLayoutResult* GridLayoutAlgorithm::LayoutInternal() {
+const LayoutResult* GridLayoutAlgorithm::LayoutInternal() {
   PaintLayerScrollableArea::DelayScrollOffsetClampScope delay_clamp_scope;
 
   LayoutUnit intrinsic_block_size;
@@ -320,7 +320,7 @@
         node, constraint_space, border_padding.block_end,
         FragmentainerSpaceLeft(constraint_space), &container_builder_);
     if (status == BreakStatus::kDisableFragmentation) {
-      return container_builder_.Abort(NGLayoutResult::kDisableFragmentation);
+      return container_builder_.Abort(LayoutResult::kDisableFragmentation);
     }
     DCHECK_EQ(status, BreakStatus::kContinue);
   } else {
@@ -999,7 +999,7 @@
 
 namespace {
 
-const NGLayoutResult* LayoutGridItemForMeasure(
+const LayoutResult* LayoutGridItemForMeasure(
     const GridItemData& grid_item,
     const ConstraintSpace& constraint_space,
     SizingConstraint sizing_constraint) {
@@ -1012,7 +1012,7 @@
   // TODO(ikilpatrick): For subgrid, ideally we don't want to disable side
   // effects as it may impact performance significantly; this issue can be
   // avoided by introducing additional cache slots (see crbug.com/1272533).
-  absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+  absl::optional<DisableLayoutSideEffectsScope> disable_side_effects;
   if (!node.GetLayoutBox()->NeedsLayout() &&
       (sizing_constraint != SizingConstraint::kLayout ||
        grid_item.is_subgridded_to_parent_grid)) {
@@ -1203,7 +1203,7 @@
     if (is_for_columns)
       grid_item->is_sizing_dependent_on_block_size = true;
 
-    const NGLayoutResult* result = nullptr;
+    const LayoutResult* result = nullptr;
     if (space.AvailableSize().inline_size == kIndefiniteSize) {
       // If we are orthogonal grid item, resolving against an indefinite size,
       // set our inline size to our max-content contribution size.
@@ -1221,7 +1221,7 @@
 
     LogicalBoxFragment baseline_fragment(
         grid_item->BaselineWritingDirection(track_direction),
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
 
     if (grid_item->IsBaselineAligned(track_direction)) {
       CalculateBaselineShim(
@@ -1633,7 +1633,7 @@
         grid_item.BaselineWritingDirection(track_direction);
     const LogicalBoxFragment baseline_fragment(
         baseline_writing_direction,
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
 
     const bool has_synthesized_baseline =
         !baseline_fragment.FirstBaseline().has_value();
@@ -3569,7 +3569,7 @@
 
     auto* result = grid_item.node.Layout(space);
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
     LogicalBoxFragment fragment(container_writing_direction, physical_fragment);
 
     auto BaselineOffset = [&](GridTrackSizingDirection track_direction,
@@ -3670,14 +3670,14 @@
   DISALLOW_NEW();
 
  public:
-  ResultAndOffsets(const NGLayoutResult* result,
+  ResultAndOffsets(const LayoutResult* result,
                    LogicalOffset offset,
                    LogicalOffset relative_offset)
       : result(result), offset(offset), relative_offset(relative_offset) {}
 
   void Trace(Visitor* visitor) const { visitor->Trace(result); }
 
-  Member<const NGLayoutResult> result;
+  Member<const LayoutResult> result;
   LogicalOffset offset;
   LogicalOffset relative_offset;
 };
@@ -3864,7 +3864,7 @@
           // Although we know that this item isn't going to fit here, we're
           // inside balanced multicol, so we need to figure out how much more
           // fragmentainer space we'd need to fit more content.
-          NGDisableSideEffectsScope disable_side_effects;
+          DisableLayoutSideEffectsScope disable_side_effects;
           auto* result = grid_item.node.Layout(space, break_token);
           PropagateSpaceShortage(constraint_space, result,
                                  fragment_relative_block_offset,
@@ -3877,7 +3877,7 @@
         continue;
 
       auto* result = grid_item.node.Layout(space, break_token);
-      DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+      DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
       result_and_offsets.emplace_back(
           result,
           LogicalOffset(item_placement_data.offset.inline_offset,
@@ -3886,7 +3886,7 @@
 
       const LogicalBoxFragment fragment(
           container_writing_direction,
-          To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+          To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
       baseline_accumulator.Accumulate(grid_item, fragment,
                                       fragment_relative_block_offset);
 
@@ -3966,7 +3966,7 @@
         }
 
         LayoutUnit item_expansion;
-        if (result->PhysicalFragment().GetBreakToken()) {
+        if (result->GetPhysicalFragment().GetBreakToken()) {
           // This item may have a break, and will want to expand into the next
           // fragmentainer, (causing the row to expand into the next
           // fragmentainer). We can't use the size of the fragment, as we don't
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
index 96793613..97fb52052c 100644
--- a/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/grid/grid_layout_algorithm.h
@@ -38,7 +38,7 @@
  public:
   explicit GridLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const GridSizingSubtree& sizing_subtree);
@@ -75,7 +75,7 @@
       HeapVector<Member<LayoutBox>>* oof_children = nullptr) const;
   GridSizingTree BuildGridSizingTreeIgnoringChildren() const;
 
-  const NGLayoutResult* LayoutInternal();
+  const LayoutResult* LayoutInternal();
 
   LayoutUnit Baseline(const GridLayoutData& layout_data,
                       const GridItemData& grid_item,
diff --git a/third_party/blink/renderer/core/layout/inline/fragment_item.cc b/third_party/blink/renderer/core/layout/inline/fragment_item.cc
index c68000f..64748cc 100644
--- a/third_party/blink/renderer/core/layout/inline/fragment_item.cc
+++ b/third_party/blink/renderer/core/layout/inline/fragment_item.cc
@@ -167,8 +167,8 @@
   }
 
   if (line_item.layout_result) {
-    const NGPhysicalBoxFragment& box_fragment =
-        To<NGPhysicalBoxFragment>(line_item.layout_result->PhysicalFragment());
+    const auto& box_fragment = To<NGPhysicalBoxFragment>(
+        line_item.layout_result->GetPhysicalFragment());
     new (this) FragmentItem(box_fragment, line_item.ResolvedDirection());
     return;
   }
diff --git a/third_party/blink/renderer/core/layout/inline/fragment_item_test.cc b/third_party/blink/renderer/core/layout/inline/fragment_item_test.cc
index b531f15..a049bae 100644
--- a/third_party/blink/renderer/core/layout/inline/fragment_item_test.cc
+++ b/third_party/blink/renderer/core/layout/inline/fragment_item_test.cc
@@ -480,7 +480,7 @@
   )HTML");
   auto* target = To<LayoutBlockFlow>(GetLayoutObjectByElementId("target"));
   Vector<PhysicalRect> rects = target->OutlineRects(
-      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, PhysicalOffset(), OutlineType::kIncludeBlockInkOverflow);
   EXPECT_THAT(rects,
               testing::ElementsAre(
                   PhysicalRect(0, 0, 200, 10),   // <div id="target">
diff --git a/third_party/blink/renderer/core/layout/inline/fragment_items.cc b/third_party/blink/renderer/core/layout/inline/fragment_items.cc
index 904301ee..e7dfc84 100644
--- a/third_party/blink/renderer/core/layout/inline/fragment_items.cc
+++ b/third_party/blink/renderer/core/layout/inline/fragment_items.cc
@@ -71,7 +71,7 @@
 }
 
 void FragmentItems::FinalizeAfterLayout(
-    const HeapVector<Member<const NGLayoutResult>, 1>& results,
+    const HeapVector<Member<const LayoutResult>, 1>& results,
     LayoutBlockFlow& container) {
   struct LastItem {
     const FragmentItem* item;
@@ -94,7 +94,7 @@
 
   for (const auto& result : results) {
     const auto& fragment =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
     const FragmentItems* fragment_items = fragment.Items();
     if (UNLIKELY(!fragment_items)) {
       may_be_non_contiguous_ifc = true;
@@ -250,7 +250,7 @@
     const PhysicalLineBoxFragment& line_box_fragment = *item.LineBoxFragment();
 
     // Abort if the line propagated its descendants to outside of the line.
-    // They are propagated through NGLayoutResult, which we don't cache.
+    // They are propagated through LayoutResult, which we don't cache.
     if (line_box_fragment.HasPropagatedDescendants())
       return &item;
 
diff --git a/third_party/blink/renderer/core/layout/inline/fragment_items.h b/third_party/blink/renderer/core/layout/inline/fragment_items.h
index b309d5e..e08265a 100644
--- a/third_party/blink/renderer/core/layout/inline/fragment_items.h
+++ b/third_party/blink/renderer/core/layout/inline/fragment_items.h
@@ -68,7 +68,7 @@
   // Associate |FragmentItem|s with |LayoutObject|s and finalize the items
   // (set which ones are the first / last for the LayoutObject).
   static void FinalizeAfterLayout(
-      const HeapVector<Member<const NGLayoutResult>, 1>& results,
+      const HeapVector<Member<const LayoutResult>, 1>& results,
       LayoutBlockFlow& container);
 
   // Disassociate |FragmentItem|s with |LayoutObject|s. And more.
diff --git a/third_party/blink/renderer/core/layout/inline/initial_letter_utils.cc b/third_party/blink/renderer/core/layout/inline/initial_letter_utils.cc
index ae31db93..85b4d94 100644
--- a/third_party/blink/renderer/core/layout/inline/initial_letter_utils.cc
+++ b/third_party/blink/renderer/core/layout/inline/initial_letter_utils.cc
@@ -255,8 +255,8 @@
       line_box->begin(), line_box->end(),
       [](const auto& line_item) { return line_item.IsInitialLetterBox(); });
 
-  const auto& initial_letter_box_fragment =
-      *To<NGPhysicalBoxFragment>(initial_letter_line_item->PhysicalFragment());
+  const auto& initial_letter_box_fragment = *To<NGPhysicalBoxFragment>(
+      initial_letter_line_item->GetPhysicalFragment());
 
   DCHECK(initial_letter_box_fragment.IsInitialLetterBox());
   DCHECK(!initial_letter_box_fragment.Style().InitialLetter().IsNormal());
diff --git a/third_party/blink/renderer/core/layout/inline/inline_box_state.cc b/third_party/blink/renderer/core/layout/inline/inline_box_state.cc
index f53a081..e5532bc 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_box_state.cc
@@ -795,7 +795,7 @@
     DCHECK_GT(end, start);
     LogicalLineItem* child = &(*line_box)[start];
     DCHECK(box_data.item->ShouldCreateBoxFragment());
-    const NGLayoutResult* box_fragment =
+    const LayoutResult* box_fragment =
         box_data.CreateBoxFragment(space, line_box, is_opaque);
     if (child->IsPlaceholder()) {
       child->layout_result = std::move(box_fragment);
@@ -814,7 +814,7 @@
   box_data_list_.clear();
 }
 
-const NGLayoutResult* InlineLayoutStateStack::BoxData::CreateBoxFragment(
+const LayoutResult* InlineLayoutStateStack::BoxData::CreateBoxFragment(
     const ConstraintSpace& space,
     LogicalLineItems* line_box,
     bool is_opaque) {
@@ -874,13 +874,12 @@
 
     // Propagate any OOF-positioned descendants from any atomic-inlines, etc.
     if (child.layout_result) {
+      const ComputedStyle& child_style = child.GetPhysicalFragment()->Style();
       box.PropagateFromLayoutResultAndFragment(
           *child.layout_result,
           child.rect.offset - rect.offset -
-              ComputeRelativeOffsetForInline(space,
-                                             child.PhysicalFragment()->Style()),
-          ComputeRelativeOffsetForOOFInInline(
-              space, child.PhysicalFragment()->Style()));
+              ComputeRelativeOffsetForInline(space, child_style),
+          ComputeRelativeOffsetForOOFInInline(space, child_style));
     }
 
     // |FragmentItems| has a flat list of all descendants, except
diff --git a/third_party/blink/renderer/core/layout/inline/inline_box_state.h b/third_party/blink/renderer/core/layout/inline/inline_box_state.h
index 7d70dbf..b9847fc 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_box_state.h
@@ -294,9 +294,9 @@
 
     void UpdateFragmentEdges(Vector<BoxData, 4>& list);
 
-    const NGLayoutResult* CreateBoxFragment(const ConstraintSpace&,
-                                            LogicalLineItems*,
-                                            bool is_opaque = false);
+    const LayoutResult* CreateBoxFragment(const ConstraintSpace&,
+                                          LogicalLineItems*,
+                                          bool is_opaque = false);
   };
 
   // Update start/end of the first BoxData found at |index|.
diff --git a/third_party/blink/renderer/core/layout/inline/inline_item.h b/third_party/blink/renderer/core/layout/inline/inline_item.h
index 885316b..0c95c0d 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_item.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_item.h
@@ -43,7 +43,7 @@
     kBidiControl
   };
 
-  enum NGCollapseType {
+  enum CollapseType {
     // No collapsible spaces.
     kNotCollapsible,
     // This item is opaque to whitespace collapsing.
@@ -192,10 +192,10 @@
   const Font& FontWithSvgScaling() const;
 
   // Get or set the whitespace collapse type at the end of this item.
-  NGCollapseType EndCollapseType() const {
-    return static_cast<NGCollapseType>(end_collapse_type_);
+  CollapseType EndCollapseType() const {
+    return static_cast<CollapseType>(end_collapse_type_);
   }
-  void SetEndCollapseType(NGCollapseType type) {
+  void SetEndCollapseType(CollapseType type) {
     // |kText| can set any types.
     DCHECK(Type() == InlineItem::kText ||
            // |kControl| and |kBlockInInline| are always |kCollapsible|.
@@ -222,7 +222,7 @@
   // Whether the end collapsible space run contains a newline.
   // Valid only when kCollapsible or kCollapsed.
   bool IsEndCollapsibleNewline() const { return is_end_collapsible_newline_; }
-  void SetEndCollapseType(NGCollapseType type, bool is_newline) {
+  void SetEndCollapseType(CollapseType type, bool is_newline) {
     SetEndCollapseType(type);
     is_end_collapsible_newline_ = is_newline;
   }
@@ -276,7 +276,7 @@
   InlineItemType type_;
   unsigned text_type_ : 3;          // TextItemType
   unsigned style_variant_ : 2;      // StyleVariant
-  unsigned end_collapse_type_ : 2;  // NGCollapseType
+  unsigned end_collapse_type_ : 2;  // CollapseType
   unsigned bidi_level_ : 8;         // UBiDiLevel is defined as uint8_t.
   // |segment_data_| is valid only for |type_ == InlineItem::kText|.
   unsigned segment_data_ : InlineItemSegment::kSegmentDataBits;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_item_result.h b/third_party/blink/renderer/core/layout/inline/inline_item_result.h
index b4a5292..a56f65a 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_item_result.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_item_result.h
@@ -21,7 +21,7 @@
 namespace blink {
 
 class InlineItem;
-class NGLayoutResult;
+class LayoutResult;
 class ShapeResult;
 class ShapeResultView;
 struct PositionedFloat;
@@ -88,8 +88,8 @@
   // This field may be set even when this item is not hyphenated.
   HyphenResult hyphen;
 
-  // NGLayoutResult for atomic inline items.
-  Member<const NGLayoutResult> layout_result;
+  // LayoutResult for atomic inline items.
+  Member<const LayoutResult> layout_result;
 
   // PositionedFloat for floating inline items. Should only be present for
   // positioned floats (not unpositioned). It indicates where it was placed
diff --git a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc
index c44a5ee..a06a630 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_items_builder.cc
@@ -622,7 +622,7 @@
   // loop through the rest of runs.
 
   unsigned start_offset;
-  InlineItem::NGCollapseType end_collapse = InlineItem::kNotCollapsible;
+  InlineItem::CollapseType end_collapse = InlineItem::kNotCollapsible;
   unsigned i = 0;
   UChar c = string[i];
   bool space_run_has_newline = false;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.cc
index e7b31fd..b264f58 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.cc
@@ -290,8 +290,9 @@
   // Just clear |NeedsLayout| flags. Culled inline boxes do not need paint
   // invalidations. If this object produces box fragments,
   // |InlineBoxStateStack| takes care of invalidations.
-  if (!NGDisableSideEffectsScope::IsDisabled())
+  if (!DisableLayoutSideEffectsScope::IsDisabled()) {
     item.GetLayoutObject()->ClearNeedsLayoutWithoutPaintInvalidation();
+  }
   return box;
 }
 
@@ -756,8 +757,9 @@
 
   DCHECK(item.GetLayoutObject());
   DCHECK(item.GetLayoutObject()->IsText());
-  if (!NGDisableSideEffectsScope::IsDisabled())
+  if (!DisableLayoutSideEffectsScope::IsDisabled()) {
     item.GetLayoutObject()->ClearNeedsLayoutWithFullPaintInvalidation();
+  }
 
   if (UNLIKELY(!item_result->Length())) {
     // Empty or fully collapsed text isn't needed for layout, but needs
@@ -826,7 +828,7 @@
                                  baseline_type_);
 }
 
-// Place a NGLayoutResult into the line box.
+// Place a LayoutResult into the line box.
 void InlineLayoutAlgorithm::PlaceLayoutResult(InlineItemResult* item_result,
                                               LogicalLineItems* line_box,
                                               InlineBoxState* box,
@@ -838,7 +840,7 @@
   FontHeight metrics =
       LogicalBoxFragment(GetConstraintSpace().GetWritingDirection(),
                          To<NGPhysicalBoxFragment>(
-                             item_result->layout_result->PhysicalFragment()))
+                             item_result->layout_result->GetPhysicalFragment()))
           .BaselineMetrics(item_result->margins, baseline_type_);
   if (box)
     box->metrics.Unite(metrics);
@@ -860,15 +862,15 @@
   DCHECK(layout_object->IsAnonymous());
   DCHECK(!layout_object->IsInline());
   DCHECK(item_result->layout_result);
-  const NGLayoutResult& result = *item_result->layout_result;
+  const LayoutResult& result = *item_result->layout_result;
   const auto& box_fragment =
-      To<NGPhysicalBoxFragment>(result.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result.GetPhysicalFragment());
   LogicalBoxFragment fragment(GetConstraintSpace().GetWritingDirection(),
                               box_fragment);
 
   // Setup |container_builder_|. Set it up here instead of in |CreateLine|,
   // because there should be only one block-in-inline, and we need data from the
-  // |NGLayoutResult|.
+  // |LayoutResult|.
   container_builder_.SetIsBlockInInline();
   container_builder_.SetInlineSize(fragment.InlineSize());
 
@@ -1070,8 +1072,9 @@
 
     // Skip any children which aren't positioned floats.
     if (!child.layout_result ||
-        !child.layout_result->PhysicalFragment().IsFloating())
+        !child.layout_result->GetPhysicalFragment().IsFloating()) {
       continue;
+    }
 
     LayoutUnit block_offset =
         child.bfc_offset.block_offset - bfc_block_offset + baseline_adjustment;
@@ -1079,7 +1082,7 @@
     // We need to manually account for the flipped-lines writing mode here :(.
     if (IsFlippedLinesWritingMode(GetConstraintSpace().GetWritingMode())) {
       LogicalFragment fragment(GetConstraintSpace().GetWritingDirection(),
-                               child.layout_result->PhysicalFragment());
+                               child.layout_result->GetPhysicalFragment());
 
       block_offset = -fragment.BlockSize() - block_offset;
     }
@@ -1092,7 +1095,7 @@
 void InlineLayoutAlgorithm::PlaceRelativePositionedItems(
     LogicalLineItems* line_box) {
   for (auto& child : *line_box) {
-    const auto* physical_fragment = child.PhysicalFragment();
+    const auto* physical_fragment = child.GetPhysicalFragment();
     if (!physical_fragment)
       continue;
     child.rect.offset += ComputeRelativeOffsetForInline(
@@ -1360,7 +1363,7 @@
   return true;
 }
 
-const NGLayoutResult* InlineLayoutAlgorithm::Layout() {
+const LayoutResult* InlineLayoutAlgorithm::Layout() {
   const auto& constraint_space = GetConstraintSpace();
   ExclusionSpace initial_exclusion_space(constraint_space.GetExclusionSpace());
 
@@ -1516,7 +1519,7 @@
     const auto* block_in_inline_result = line_info.BlockInInlineLayoutResult();
     if (block_in_inline_result) {
       if (UNLIKELY(block_in_inline_result->Status() !=
-                   NGLayoutResult::kSuccess)) {
+                   LayoutResult::kSuccess)) {
         items_builder->ReleaseCurrentLogicalLineItems();
         return block_in_inline_result;
       }
@@ -1546,8 +1549,7 @@
       if (container_builder_.GetAdjoiningObjectTypes() &&
           bfc_block_offset != constraint_space.ExpectedBfcBlockOffset()) {
         items_builder->ReleaseCurrentLogicalLineItems();
-        return container_builder_.Abort(
-            NGLayoutResult::kBfcBlockOffsetResolved);
+        return container_builder_.Abort(LayoutResult::kBfcBlockOffsetResolved);
       }
     }
 
@@ -1691,8 +1693,7 @@
       }
     } else {
       if (!AddAnyClearanceAfterLine(line_info)) {
-        return container_builder_.Abort(
-            NGLayoutResult::kOutOfFragmentainerSpace);
+        return container_builder_.Abort(LayoutResult::kOutOfFragmentainerSpace);
       }
       container_builder_.SetBlockSize(container_builder_.LineHeight());
 
@@ -1718,9 +1719,9 @@
 
   DCHECK(items_builder);
   container_builder_.PropagateChildrenData(*line_box);
-  const NGLayoutResult* layout_result = container_builder_.ToLineBoxFragment();
-  items_builder->AssociateLogicalLineItems(line_box,
-                                           layout_result->PhysicalFragment());
+  const LayoutResult* layout_result = container_builder_.ToLineBoxFragment();
+  items_builder->AssociateLogicalLineItems(
+      line_box, layout_result->GetPhysicalFragment());
   line_break_strategy.DidCreateLine(is_end_paragraph);
   return layout_result;
 }
diff --git a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.h b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.h
index 5d8d57b..6f9f24f6 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm.h
@@ -54,7 +54,7 @@
                   LineInfo*,
                   LogicalLineItems* line_box);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override {
     NOTREACHED();
diff --git a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm_test.cc
index 484ca79..65c8226c 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_layout_algorithm_test.cc
@@ -189,21 +189,21 @@
       block_flow, block_flow->Style(), constraint_space,
       block_flow->Style()->GetWritingDirection());
   SimpleInlineChildLayoutContext context(inline_node, &container_builder);
-  const NGLayoutResult* layout_result =
+  const LayoutResult* layout_result =
       inline_node.Layout(constraint_space, nullptr, nullptr, &context);
-  const auto& line1 = layout_result->PhysicalFragment();
+  const auto& line1 = layout_result->GetPhysicalFragment();
   EXPECT_TRUE(line1.GetBreakToken());
 
   // Perform 2nd layout with the break token from the 1st line.
-  const NGLayoutResult* layout_result2 = inline_node.Layout(
+  const LayoutResult* layout_result2 = inline_node.Layout(
       constraint_space, line1.GetBreakToken(), nullptr, &context);
-  const auto& line2 = layout_result2->PhysicalFragment();
+  const auto& line2 = layout_result2->GetPhysicalFragment();
   EXPECT_TRUE(line2.GetBreakToken());
 
   // Perform 3rd layout with the break token from the 2nd line.
-  const NGLayoutResult* layout_result3 = inline_node.Layout(
+  const LayoutResult* layout_result3 = inline_node.Layout(
       constraint_space, line2.GetBreakToken(), nullptr, &context);
-  const auto& line3 = layout_result3->PhysicalFragment();
+  const auto& line3 = layout_result3->GetPhysicalFragment();
   EXPECT_FALSE(line3.GetBreakToken());
 }
 
@@ -384,7 +384,7 @@
   EXPECT_EQ(0, layout_result->BfcLineOffset());
 
   const auto& fragment =
-      To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
   EXPECT_EQ(fragment.ContentOffset(), PhysicalOffset(5, 10));
   PhysicalOffset line_offset = fragment.Children()[0].Offset();
   EXPECT_EQ(line_offset, PhysicalOffset(5, 10));
@@ -455,7 +455,7 @@
                         ->item(0)
                         ->GetLayoutObject())
           ->GetSingleCachedLayoutResult()
-          ->PhysicalFragment();
+          ->GetPhysicalFragment();
 
   auto* body_fragment =
       To<NGPhysicalBoxFragment>(html_fragment.Children()[0].get());
diff --git a/third_party/blink/renderer/core/layout/inline/inline_node.cc b/third_party/blink/renderer/core/layout/inline/inline_node.cc
index f774f6e..2f470c2 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_node.cc
+++ b/third_party/blink/renderer/core/layout/inline/inline_node.cc
@@ -1609,7 +1609,7 @@
   }
 }
 
-const NGLayoutResult* InlineNode::Layout(
+const LayoutResult* InlineNode::Layout(
     const ConstraintSpace& constraint_space,
     const BreakToken* break_token,
     const ColumnSpannerPath* column_spanner_path,
diff --git a/third_party/blink/renderer/core/layout/inline/inline_node.h b/third_party/blink/renderer/core/layout/inline/inline_node.h
index 4f56121..f95c8ef7 100644
--- a/third_party/blink/renderer/core/layout/inline/inline_node.h
+++ b/third_party/blink/renderer/core/layout/inline/inline_node.h
@@ -20,7 +20,7 @@
 class ColumnSpannerPath;
 class ConstraintSpace;
 class InlineChildLayoutContext;
-class NGLayoutResult;
+class LayoutResult;
 class OffsetMapping;
 struct InlineItemsData;
 struct SvgTextContentRange;
@@ -36,10 +36,10 @@
     return To<LayoutBlockFlow>(box_.Get());
   }
 
-  const NGLayoutResult* Layout(const ConstraintSpace&,
-                               const BreakToken*,
-                               const ColumnSpannerPath*,
-                               InlineChildLayoutContext* context) const;
+  const LayoutResult* Layout(const ConstraintSpace&,
+                             const BreakToken*,
+                             const ColumnSpannerPath*,
+                             InlineChildLayoutContext* context) const;
 
   // Computes the value of min-content and max-content for this anonymous block
   // box. min-content is the inline size when lines wrap at every break
diff --git a/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.cc
index 889ae2c..146b742d 100644
--- a/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.cc
@@ -51,13 +51,13 @@
       // An accumulated relative offset is applied to an OOF once it reaches its
       // inline container. Subtract out the relative offset to avoid adding it
       // twice.
+      const ComputedStyle& child_style = child.GetPhysicalFragment()->Style();
       PropagateFromLayoutResultAndFragment(
           *child.layout_result,
           child.Offset() -
-              ComputeRelativeOffsetForInline(GetConstraintSpace(),
-                                             child.PhysicalFragment()->Style()),
-          ComputeRelativeOffsetForOOFInInline(
-              GetConstraintSpace(), child.PhysicalFragment()->Style()));
+              ComputeRelativeOffsetForInline(GetConstraintSpace(), child_style),
+          ComputeRelativeOffsetForOOFInInline(GetConstraintSpace(),
+                                              child_style));
 
       // Skip over any children, the information should have already been
       // propagated into this layout result.
@@ -78,14 +78,13 @@
   MoveOutOfFlowDescendantCandidatesToDescendants();
 }
 
-const NGLayoutResult* LineBoxFragmentBuilder::ToLineBoxFragment() {
+const LayoutResult* LineBoxFragmentBuilder::ToLineBoxFragment() {
   writing_direction_.SetWritingMode(ToLineWritingMode(GetWritingMode()));
 
   const auto* fragment = PhysicalLineBoxFragment::Create(this);
 
-  return MakeGarbageCollected<NGLayoutResult>(
-      NGLayoutResult::LineBoxFragmentBuilderPassKey(), std::move(fragment),
-      this);
+  return MakeGarbageCollected<LayoutResult>(
+      LayoutResult::LineBoxFragmentBuilderPassKey(), std::move(fragment), this);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.h b/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.h
index b58d17cb..089973b 100644
--- a/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/inline/line_box_fragment_builder.h
@@ -94,7 +94,7 @@
   }
 
   // Creates the fragment. Can only be called once.
-  const NGLayoutResult* ToLineBoxFragment();
+  const LayoutResult* ToLineBoxFragment();
 
  private:
   absl::optional<LayoutUnit> line_box_bfc_block_offset_;
@@ -105,7 +105,7 @@
   PhysicalLineBoxFragment::LineBoxType line_box_type_;
   TextDirection base_direction_;
 
-  friend class NGLayoutResult;
+  friend class LayoutResult;
   friend class PhysicalLineBoxFragment;
 };
 
diff --git a/third_party/blink/renderer/core/layout/inline/line_breaker.cc b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
index 35a3c4d9..ce35e47 100644
--- a/third_party/blink/renderer/core/layout/inline/line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/inline/line_breaker.cc
@@ -2597,7 +2597,7 @@
                                 baseline_algorithm_type);
 
     const auto& physical_box_fragment = To<NGPhysicalBoxFragment>(
-        item_result->layout_result->PhysicalFragment());
+        item_result->layout_result->GetPhysicalFragment());
     item_result->inline_size =
         LogicalFragment(constraint_space_.GetWritingDirection(),
                         physical_box_fragment)
@@ -2721,18 +2721,18 @@
     BlockNode block_node(To<LayoutBox>(item.GetLayoutObject()));
     const ColumnSpannerPath* spanner_path_for_child =
         FollowColumnSpannerPath(column_spanner_path_, block_node);
-    const NGLayoutResult* layout_result =
+    const LayoutResult* layout_result =
         block_node.Layout(constraint_space_, block_break_token,
                           /* early_break */ nullptr, spanner_path_for_child);
     line_info->SetBlockInInlineLayoutResult(layout_result);
 
     // Early exit if the layout didn't succeed.
-    if (layout_result->Status() != NGLayoutResult::kSuccess) {
+    if (layout_result->Status() != LayoutResult::kSuccess) {
       state_ = LineBreakState::kDone;
       return;
     }
 
-    const NGPhysicalFragment& fragment = layout_result->PhysicalFragment();
+    const auto& fragment = layout_result->GetPhysicalFragment();
     item_result->inline_size =
         LogicalFragment(constraint_space_.GetWritingDirection(), fragment)
             .InlineSize();
@@ -2741,7 +2741,7 @@
     item_result->layout_result = layout_result;
 
     if (const auto* outgoing_block_break_token = To<BlockBreakToken>(
-            layout_result->PhysicalFragment().GetBreakToken())) {
+            layout_result->GetPhysicalFragment().GetBreakToken())) {
       // The block broke inside. If the block itself fits, but some content
       // inside overflowed, we now need to enter a parallel flow, i.e. resume
       // the block-in-inline in the next fragmentainer, but continue layout of
@@ -3659,13 +3659,13 @@
   if (resume_block_in_inline_in_same_flow_) {
     const auto* block_in_inline = line_info.BlockInInlineLayoutResult();
     DCHECK(block_in_inline);
-    if (UNLIKELY(block_in_inline->Status() != NGLayoutResult::kSuccess)) {
+    if (UNLIKELY(block_in_inline->Status() != LayoutResult::kSuccess)) {
       return nullptr;
     }
     // Look for a break token inside the block-in-inline, so that we can add it
     // to the inline break token that we're about to create.
     const auto& block_in_inline_fragment =
-        To<NGPhysicalBoxFragment>(block_in_inline->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(block_in_inline->GetPhysicalFragment());
     sub_break_token = block_in_inline_fragment.GetBreakToken();
   }
 
diff --git a/third_party/blink/renderer/core/layout/inline/line_info.h b/third_party/blink/renderer/core/layout/inline/line_info.h
index 127604f..b74d2e9 100644
--- a/third_party/blink/renderer/core/layout/inline/line_info.h
+++ b/third_party/blink/renderer/core/layout/inline/line_info.h
@@ -198,10 +198,10 @@
   bool NeedsAccurateEndPosition() const { return needs_accurate_end_position_; }
 
   // The block-in-inline layout result.
-  const NGLayoutResult* BlockInInlineLayoutResult() const {
+  const LayoutResult* BlockInInlineLayoutResult() const {
     return block_in_inline_layout_result_;
   }
-  void SetBlockInInlineLayoutResult(const NGLayoutResult* layout_result) {
+  void SetBlockInInlineLayoutResult(const LayoutResult* layout_result) {
     block_in_inline_layout_result_ = std::move(layout_result);
   }
 
@@ -262,7 +262,7 @@
   const InlineBreakToken* break_token_ = nullptr;
   HeapVector<Member<const BreakToken>> parallel_flow_break_tokens_;
 
-  const NGLayoutResult* block_in_inline_layout_result_ = nullptr;
+  const LayoutResult* block_in_inline_layout_result_ = nullptr;
 
   absl::optional<LayoutUnit> minimum_space_shortage_;
 
diff --git a/third_party/blink/renderer/core/layout/inline/line_truncator.cc b/third_party/blink/renderer/core/layout/inline/line_truncator.cc
index b3eaa86b..b49d9d9 100644
--- a/third_party/blink/renderer/core/layout/inline/line_truncator.cc
+++ b/third_party/blink/renderer/core/layout/inline/line_truncator.cc
@@ -406,10 +406,10 @@
 void LineTruncator::HideChild(LogicalLineItem* child) {
   DCHECK(child->HasInFlowFragment());
 
-  if (const NGLayoutResult* layout_result = child->layout_result) {
+  if (const LayoutResult* layout_result = child->layout_result) {
     // Need to propagate OOF descendants in this inline-block child.
     const auto& fragment =
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
     if (fragment.HasOutOfFlowPositionedDescendants())
       return;
 
diff --git a/third_party/blink/renderer/core/layout/inline/logical_line_item.cc b/third_party/blink/renderer/core/layout/inline/logical_line_item.cc
index 651c696e..1ef0f43 100644
--- a/third_party/blink/renderer/core/layout/inline/logical_line_item.cc
+++ b/third_party/blink/renderer/core/layout/inline/logical_line_item.cc
@@ -12,16 +12,18 @@
 const LayoutObject* LogicalLineItem::GetLayoutObject() const {
   if (inline_item)
     return inline_item->GetLayoutObject();
-  if (const NGPhysicalFragment* fragment = PhysicalFragment())
+  if (const auto* fragment = GetPhysicalFragment()) {
     return fragment->GetLayoutObject();
+  }
   return nullptr;
 }
 
 LayoutObject* LogicalLineItem::GetMutableLayoutObject() const {
   if (inline_item)
     return inline_item->GetLayoutObject();
-  if (const NGPhysicalFragment* fragment = PhysicalFragment())
+  if (const auto* fragment = GetPhysicalFragment()) {
     return fragment->GetMutableLayoutObject();
+  }
   return nullptr;
 }
 
@@ -32,8 +34,9 @@
 }
 
 const ComputedStyle* LogicalLineItem::Style() const {
-  if (const auto* fragment = PhysicalFragment())
+  if (const auto* fragment = GetPhysicalFragment()) {
     return &fragment->Style();
+  }
   if (inline_item)
     return inline_item->Style();
   return nullptr;
@@ -46,8 +49,9 @@
   stream << " inline_size=" << item.inline_size;
   if (item.inline_item)
     stream << " " << item.inline_item->ToString().Utf8().c_str();
-  if (item.PhysicalFragment())
-    stream << " Fragment=" << *item.PhysicalFragment();
+  if (item.GetPhysicalFragment()) {
+    stream << " Fragment=" << *item.GetPhysicalFragment();
+  }
   if (item.GetLayoutObject())
     stream << " LayoutObject=" << *item.GetLayoutObject();
   stream << ")";
@@ -71,11 +75,12 @@
   return nullptr;
 }
 
-const NGLayoutResult* LogicalLineItems::BlockInInlineLayoutResult() const {
+const LayoutResult* LogicalLineItems::BlockInInlineLayoutResult() const {
   for (const LogicalLineItem& item : *this) {
     if (item.layout_result &&
-        item.layout_result->PhysicalFragment().IsBlockInInline())
+        item.layout_result->GetPhysicalFragment().IsBlockInInline()) {
       return item.layout_result.Get();
+    }
   }
   return nullptr;
 }
diff --git a/third_party/blink/renderer/core/layout/inline/logical_line_item.h b/third_party/blink/renderer/core/layout/inline/logical_line_item.h
index 044c03a..72f369e 100644
--- a/third_party/blink/renderer/core/layout/inline/logical_line_item.h
+++ b/third_party/blink/renderer/core/layout/inline/logical_line_item.h
@@ -18,7 +18,7 @@
 namespace blink {
 
 class LayoutObject;
-class NGLayoutResult;
+class LayoutResult;
 
 // This class represents an item in a line, after line break, but still mutable
 // and in the logical coordinate system.
@@ -34,8 +34,8 @@
   // Crete a bidi control. A bidi control does not have a fragment, but has
   // bidi level and affects bidi reordering.
   explicit LogicalLineItem(UBiDiLevel bidi_level) : bidi_level(bidi_level) {}
-  // Create an in-flow |NGLayoutResult|.
-  LogicalLineItem(const NGLayoutResult* layout_result,
+  // Create an in-flow |LayoutResult|.
+  LogicalLineItem(const LayoutResult* layout_result,
                   const LogicalRect& rect,
                   unsigned children_count,
                   UBiDiLevel bidi_level)
@@ -43,7 +43,7 @@
         rect(rect),
         children_count(children_count),
         bidi_level(bidi_level) {}
-  LogicalLineItem(const NGLayoutResult* layout_result,
+  LogicalLineItem(const LayoutResult* layout_result,
                   LogicalOffset offset,
                   LayoutUnit inline_size,
                   unsigned children_count,
@@ -139,7 +139,7 @@
         item_index(item_index),
         bidi_level(bidi_level) {}
   // Create a positioned float.
-  LogicalLineItem(const NGLayoutResult* layout_result,
+  LogicalLineItem(const LayoutResult* layout_result,
                   BfcOffset bfc_offset,
                   UBiDiLevel bidi_level)
       : layout_result(layout_result),
@@ -147,18 +147,18 @@
         bidi_level(bidi_level) {}
 
   bool IsFloating() const {
-    return layout_result && layout_result->PhysicalFragment().IsFloating();
+    return layout_result && layout_result->GetPhysicalFragment().IsFloating();
   }
   bool IsInitialLetterBox() const {
     return layout_result &&
-           layout_result->PhysicalFragment().IsInitialLetterBox();
+           layout_result->GetPhysicalFragment().IsInitialLetterBox();
   }
   bool IsInlineBox() const {
-    return layout_result && layout_result->PhysicalFragment().IsInlineBox();
+    return layout_result && layout_result->GetPhysicalFragment().IsInlineBox();
   }
   bool HasInFlowFragment() const {
-    return inline_item ||
-           (layout_result && !layout_result->PhysicalFragment().IsFloating());
+    return inline_item || (layout_result &&
+                           !layout_result->GetPhysicalFragment().IsFloating());
   }
   bool HasInFlowOrFloatingFragment() const {
     return inline_item || layout_result || layout_object;
@@ -181,9 +181,12 @@
     // Skip all inline boxes. Fragments for inline boxes maybe created earlier
     // if they have no children.
     if (layout_result) {
-      DCHECK(layout_result->PhysicalFragment().GetLayoutObject());
-      if (layout_result->PhysicalFragment().GetLayoutObject()->IsLayoutInline())
+      DCHECK(layout_result->GetPhysicalFragment().GetLayoutObject());
+      if (layout_result->GetPhysicalFragment()
+              .GetLayoutObject()
+              ->IsLayoutInline()) {
         return true;
+      }
     }
     return false;
   }
@@ -195,9 +198,9 @@
   const LogicalSize& Size() const { return rect.size; }
   LogicalSize MarginSize() const { return {inline_size, Size().block_size}; }
 
-  const NGPhysicalFragment* PhysicalFragment() const {
+  const NGPhysicalFragment* GetPhysicalFragment() const {
     if (layout_result)
-      return &layout_result->PhysicalFragment();
+      return &layout_result->GetPhysicalFragment();
     return nullptr;
   }
   const LayoutObject* GetLayoutObject() const;
@@ -226,7 +229,7 @@
   // Data to create a generated text fragment.
   String text_content;
 
-  Member<const NGLayoutResult> layout_result;
+  Member<const LayoutResult> layout_result;
 
   // Ellipsis does not have |InlineItem|, but built from |LayoutObject| and
   // |StyleVariant|.
@@ -307,7 +310,7 @@
   LogicalLineItem* FirstInFlowChild();
   LogicalLineItem* LastInFlowChild();
 
-  const NGLayoutResult* BlockInInlineLayoutResult() const;
+  const LayoutResult* BlockInInlineLayoutResult() const;
 
   // Add a child. Accepts all constructor arguments for |LogicalLineItem|.
   template <class... Args>
@@ -319,7 +322,7 @@
     children_.insert(index, item);
   }
   void InsertChild(unsigned index,
-                   const NGLayoutResult* layout_result,
+                   const LayoutResult* layout_result,
                    const LogicalRect& rect,
                    unsigned children_count) {
     WillInsertChild(index);
diff --git a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
index 5a325b5..62391b51 100644
--- a/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
+++ b/third_party/blink/renderer/core/layout/inline/ruby_utils.cc
@@ -101,7 +101,7 @@
   if (!item.layout_result)
     return overhang;
 
-  const auto& column_fragment = item.layout_result->PhysicalFragment();
+  const auto& column_fragment = item.layout_result->GetPhysicalFragment();
 
   const ComputedStyle* ruby_text_style = nullptr;
   for (const auto& child_link : column_fragment.PostLayoutChildren()) {
@@ -208,7 +208,7 @@
       return LayoutUnit();
   }
   InlineItemResult& atomic_inline_item = (*items)[i];
-  if (!atomic_inline_item.layout_result->PhysicalFragment().IsRubyColumn()) {
+  if (!atomic_inline_item.layout_result->GetPhysicalFragment().IsRubyColumn()) {
     return LayoutUnit();
   }
   if (atomic_inline_item.pending_end_overhang <= LayoutUnit())
@@ -258,7 +258,7 @@
             item_over, item_under, *style, *item.shape_result);
       }
     } else {
-      const auto* fragment = item.PhysicalFragment();
+      const auto* fragment = item.GetPhysicalFragment();
       if (fragment && fragment->IsRubyColumn()) {
         PhysicalRect rect =
             To<NGPhysicalBoxFragment>(fragment)->ComputeRubyEmHeightBox();
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index b22060d9..50b6dc40 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -716,7 +716,7 @@
 void LayoutBlock::AddOutlineRects(OutlineRectCollector& collector,
                                   OutlineInfo* info,
                                   const PhysicalOffset& additional_offset,
-                                  NGOutlineType include_block_overflows) const {
+                                  OutlineType include_block_overflows) const {
   NOT_DESTROYED();
 #if DCHECK_IS_ON()
   // TODO(crbug.com/987836): enable this DCHECK universally.
@@ -732,7 +732,7 @@
     collector.AddRect(PhysicalRect(additional_offset, Size()));
   }
 
-  if (ShouldIncludeBlockVisualOverflow(include_block_overflows) &&
+  if (ShouldIncludeBlockInkOverflow(include_block_overflows) &&
       !HasNonVisibleOverflow() && !HasControlClip()) {
     AddOutlineRectsForNormalChildren(collector, additional_offset,
                                      include_block_overflows);
@@ -808,7 +808,7 @@
 
 RecalcScrollableOverflowResult LayoutBlock::RecalcScrollableOverflow() {
   NOT_DESTROYED();
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
   return RecalcScrollableOverflowNG();
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h
index a8265ca..11cb37d 100644
--- a/third_party/blink/renderer/core/layout/layout_block.h
+++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -233,7 +233,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const override;
+                       OutlineType) const override;
 
   // TODO(jchaffraix): We should rename this function as inline-flex and
   // inline-grid as also covered.
diff --git a/third_party/blink/renderer/core/layout/layout_block_test.cc b/third_party/blink/renderer/core/layout/layout_block_test.cc
index 2a343ba..ef4c3c5 100644
--- a/third_party/blink/renderer/core/layout/layout_block_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_test.cc
@@ -122,7 +122,7 @@
       GetDocument().getElementById(AtomicString("target"));
   auto* target = To<LayoutBlockFlow>(target_element->GetLayoutObject());
   EXPECT_TRUE(target->GetSingleCachedLayoutResult()
-                  ->PhysicalFragment()
+                  ->GetPhysicalFragment()
                   .HasOutOfFlowFragmentChild());
 
   // Remove layout containment. This should cause |contained| to now be
@@ -131,11 +131,11 @@
                                AtomicString("contain:style"));
   UpdateAllLifecyclePhasesForTest();
   EXPECT_FALSE(target->GetSingleCachedLayoutResult()
-                   ->PhysicalFragment()
+                   ->GetPhysicalFragment()
                    .HasOutOfFlowFragmentChild());
   const LayoutView* view = GetDocument().GetLayoutView();
   EXPECT_TRUE(view->GetSingleCachedLayoutResult()
-                  ->PhysicalFragment()
+                  ->GetPhysicalFragment()
                   .HasOutOfFlowFragmentChild());
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 172531f5..bd1c4b7 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -137,7 +137,7 @@
   LayoutUnit intrinsic_logical_widths_initial_block_size;
   Member<void*> min_max_sizes_cache;
   Member<void*> result;
-  HeapVector<Member<const NGLayoutResult>, 1> layout_results;
+  HeapVector<Member<const LayoutResult>, 1> layout_results;
   wtf_size_t first_fragment_item_index_;
   Member<void*> members[2];
 };
@@ -512,9 +512,9 @@
     ClearFirstInlineFragmentItemIndex();
   }
   if (measure_result_)
-    measure_result_->PhysicalFragment().LayoutObjectWillBeDestroyed();
+    measure_result_->GetPhysicalFragment().LayoutObjectWillBeDestroyed();
   for (auto result : layout_results_)
-    result->PhysicalFragment().LayoutObjectWillBeDestroyed();
+    result->GetPhysicalFragment().LayoutObjectWillBeDestroyed();
 }
 
 void LayoutBox::InsertedIntoTree() {
@@ -916,7 +916,7 @@
   DCHECK(previous_result);
   auto space = previous_result->GetConstraintSpaceForCaching();
   DCHECK_EQ(space.GetWritingMode(), StyleRef().GetWritingMode());
-  const NGLayoutResult* result = BlockNode(this).Layout(space);
+  const LayoutResult* result = BlockNode(this).Layout(space);
   GetDocument().GetFrame()->GetInputMethodController().DidLayoutSubtree(*this);
 
   if (IsOutOfFlowPositioned()) {
@@ -932,8 +932,9 @@
   // this technique to detect size-changes, etc if we wanted to expand this
   // optimization.
   const auto& previous_fragment =
-      To<NGPhysicalBoxFragment>(previous_result->PhysicalFragment());
-  const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(previous_result->GetPhysicalFragment());
+  const auto& fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   if (previous_fragment.FirstBaseline() != fragment.FirstBaseline() ||
       previous_fragment.LastBaseline() != fragment.LastBaseline() ||
       fragment.HasPropagatedLayoutObjects()) {
@@ -1458,7 +1459,7 @@
 void LayoutBox::AddOutlineRects(OutlineRectCollector& collector,
                                 OutlineInfo* info,
                                 const PhysicalOffset& additional_offset,
-                                NGOutlineType) const {
+                                OutlineType) const {
   NOT_DESTROYED();
   collector.AddRect(PhysicalRect(additional_offset, Size()));
   if (info)
@@ -2560,8 +2561,9 @@
     const NGPhysicalBoxFragment& fragment) const {
   wtf_size_t index = 0;
   for (const auto& result : layout_results_) {
-    if (&result->PhysicalFragment() == &fragment)
+    if (&result->GetPhysicalFragment() == &fragment) {
       return index;
+    }
     ++index;
   }
   return kNotFound;
@@ -2572,14 +2574,14 @@
   return IndexOf(fragment) != kNotFound;
 }
 
-void LayoutBox::SetCachedLayoutResult(const NGLayoutResult* result,
+void LayoutBox::SetCachedLayoutResult(const LayoutResult* result,
                                       wtf_size_t index) {
   NOT_DESTROYED();
   if (result->GetConstraintSpaceForCaching().CacheSlot() ==
       LayoutResultCacheSlot::kMeasure) {
-    DCHECK(!result->PhysicalFragment().GetBreakToken());
-    DCHECK(
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment()).IsOnlyForNode());
+    DCHECK(!result->GetPhysicalFragment().GetBreakToken());
+    DCHECK(To<NGPhysicalBoxFragment>(result->GetPhysicalFragment())
+               .IsOnlyForNode());
     DCHECK_EQ(index, 0u);
     // We don't early return here, when setting the "measure" result we also
     // set the "layout" result.
@@ -2611,12 +2613,11 @@
   SetLayoutResult(result, index);
 }
 
-void LayoutBox::SetLayoutResult(const NGLayoutResult* result,
-                                wtf_size_t index) {
+void LayoutBox::SetLayoutResult(const LayoutResult* result, wtf_size_t index) {
   NOT_DESTROYED();
-  DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
   const auto& box_fragment =
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
 
   if (index != WTF::kNotFound && layout_results_.size() > index) {
     if (layout_results_.size() > index + 1) {
@@ -2659,10 +2660,11 @@
   }
 }
 
-void LayoutBox::AppendLayoutResult(const NGLayoutResult* result) {
-  const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+void LayoutBox::AppendLayoutResult(const LayoutResult* result) {
+  const auto& fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   // |layout_results_| is particularly critical when side effects are disabled.
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
   layout_results_.push_back(std::move(result));
   InvalidateCachedGeometry();
   CheckDidAddFragment(*this, fragment);
@@ -2671,15 +2673,16 @@
     FragmentCountOrSizeDidChange();
 }
 
-void LayoutBox::ReplaceLayoutResult(const NGLayoutResult* result,
+void LayoutBox::ReplaceLayoutResult(const LayoutResult* result,
                                     wtf_size_t index) {
   NOT_DESTROYED();
   DCHECK_LE(index, layout_results_.size());
-  const NGLayoutResult* old_result = layout_results_[index];
+  const LayoutResult* old_result = layout_results_[index];
   if (old_result == result)
     return;
-  const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
-  const auto& old_fragment = old_result->PhysicalFragment();
+  const auto& fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
+  const auto& old_fragment = old_result->GetPhysicalFragment();
   bool got_new_fragment = &old_fragment != &fragment;
   if (got_new_fragment) {
     if (HasFragmentItems()) {
@@ -2693,7 +2696,7 @@
     }
   }
   // |layout_results_| is particularly critical when side effects are disabled.
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
   layout_results_[index] = std::move(result);
   InvalidateCachedGeometry();
   CheckDidAddFragment(*this, fragment, index);
@@ -2708,7 +2711,7 @@
 
 void LayoutBox::FinalizeLayoutResults() {
   DCHECK(!layout_results_.empty());
-  DCHECK(!layout_results_.back()->PhysicalFragment().GetBreakToken());
+  DCHECK(!layout_results_.back()->GetPhysicalFragment().GetBreakToken());
 #if EXPENSIVE_DCHECKS_ARE_ON()
   CheckMayHaveFragmentItems();
 #endif
@@ -2730,7 +2733,7 @@
   while (container && container->PhysicalFragmentCount() &&
          !container->NeedsLayout()) {
     for (auto& result : container->layout_results_)
-      result = NGLayoutResult::CloneWithPostLayoutFragments(*result);
+      result = LayoutResult::CloneWithPostLayoutFragments(*result);
     container = container->ContainingNGBox();
   }
 
@@ -2752,7 +2755,7 @@
   for (wtf_size_t i = results_to_keep; i < layout_results_.size(); i++)
     InvalidateItems(*layout_results_[i]);
   // |layout_results_| is particularly critical when side effects are disabled.
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
   if (layout_results_.size() > 1)
     FragmentCountOrSizeDidChange();
   layout_results_.Shrink(results_to_keep);
@@ -2782,11 +2785,11 @@
   }
 }
 
-void LayoutBox::InvalidateItems(const NGLayoutResult& result) {
+void LayoutBox::InvalidateItems(const LayoutResult& result) {
   NOT_DESTROYED();
   // Invalidate if inline |DisplayItemClient|s will be destroyed.
   const auto& box_fragment =
-      To<NGPhysicalBoxFragment>(result.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result.GetPhysicalFragment());
   if (!box_fragment.HasItems())
     return;
 #if DCHECK_IS_ON()
@@ -2800,19 +2803,19 @@
   ObjectPaintInvalidator(*this).SlowSetPaintingLayerNeedsRepaint();
 }
 
-const NGLayoutResult* LayoutBox::GetCachedLayoutResult(
+const LayoutResult* LayoutBox::GetCachedLayoutResult(
     const BlockBreakToken* break_token) const {
   NOT_DESTROYED();
   wtf_size_t index = FragmentIndex(break_token);
   if (index >= layout_results_.size())
     return nullptr;
-  const NGLayoutResult* result = layout_results_[index];
-  DCHECK(!result->PhysicalFragment().IsLayoutObjectDestroyedOrMoved() ||
+  const LayoutResult* result = layout_results_[index];
+  DCHECK(!result->GetPhysicalFragment().IsLayoutObjectDestroyedOrMoved() ||
          BeingDestroyed());
   return result;
 }
 
-const NGLayoutResult* LayoutBox::GetCachedMeasureResult() const {
+const LayoutResult* LayoutBox::GetCachedMeasureResult() const {
   NOT_DESTROYED();
   if (!measure_result_)
     return nullptr;
@@ -2833,34 +2836,37 @@
 
   // TODO(mstensho): Measure-results can never fragment, can they? This check
   // could probably be removed.
-  if (!To<NGPhysicalBoxFragment>(measure_result_->PhysicalFragment())
-           .IsOnlyForNode())
+  if (!To<NGPhysicalBoxFragment>(measure_result_->GetPhysicalFragment())
+           .IsOnlyForNode()) {
     return nullptr;
+  }
 
   return measure_result_.Get();
 }
 
-const NGLayoutResult* LayoutBox::GetSingleCachedLayoutResult() const {
+const LayoutResult* LayoutBox::GetSingleCachedLayoutResult() const {
   DCHECK_LE(layout_results_.size(), 1u);
   return GetCachedLayoutResult(nullptr);
 }
 
-const NGLayoutResult* LayoutBox::GetLayoutResult(wtf_size_t i) const {
+const LayoutResult* LayoutBox::GetLayoutResult(wtf_size_t i) const {
   NOT_DESTROYED();
   return layout_results_[i].Get();
 }
 
 const NGPhysicalBoxFragment&
 LayoutBox::NGPhysicalFragmentList::Iterator::operator*() const {
-  return To<NGPhysicalBoxFragment>((*iterator_)->PhysicalFragment());
+  return To<NGPhysicalBoxFragment>((*iterator_)->GetPhysicalFragment());
 }
 
 const NGPhysicalBoxFragment& LayoutBox::NGPhysicalFragmentList::front() const {
-  return To<NGPhysicalBoxFragment>(layout_results_.front()->PhysicalFragment());
+  return To<NGPhysicalBoxFragment>(
+      layout_results_.front()->GetPhysicalFragment());
 }
 
 const NGPhysicalBoxFragment& LayoutBox::NGPhysicalFragmentList::back() const {
-  return To<NGPhysicalBoxFragment>(layout_results_.back()->PhysicalFragment());
+  return To<NGPhysicalBoxFragment>(
+      layout_results_.back()->GetPhysicalFragment());
 }
 
 const FragmentData* LayoutBox::FragmentDataFromPhysicalFragment(
@@ -3236,7 +3242,7 @@
     OutlineInfo info;
     Vector<PhysicalRect> outline_rects =
         OutlineRects(&info, PhysicalOffset(),
-                     style.OutlineRectsShouldIncludeBlockVisualOverflow());
+                     style.OutlineRectsShouldIncludeBlockInkOverflow());
     PhysicalRect rect = UnionRect(outline_rects);
     bool outline_affected = rect.size != Size();
     SetOutlineMayBeAffectedByDescendants(outline_affected);
@@ -3275,7 +3281,7 @@
   // scrollable-overflow to determine the final scrollable-overflow.
   for (const auto& layout_result : layout_results_) {
     const auto& fragment =
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
 
     // In order to correctly unite the overflow, we need to shift an individual
     // fragment's scrollable-overflow by previously consumed block-size so far.
@@ -3364,7 +3370,7 @@
   if (rebuild_fragment_tree || should_recalculate_scrollable_overflow) {
     for (auto& layout_result : layout_results_) {
       const auto& fragment =
-          To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+          To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
       absl::optional<PhysicalRect> scrollable_overflow;
 
       // Recalculate our scrollable-overflow if a child had its
@@ -3427,7 +3433,7 @@
   RecalcScrollableOverflowResult result;
   for (auto& layout_result : layout_results_) {
     const auto& fragment =
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
     if (fragment.HasItems()) {
       for (InlineCursor cursor(fragment); cursor; cursor.MoveToNext()) {
         const NGPhysicalBoxFragment* child =
@@ -3800,7 +3806,7 @@
   if (results.size() == 0) {
     return PhysicalSize();
   }
-  const auto& first_fragment = results[0]->PhysicalFragment();
+  const auto& first_fragment = results[0]->GetPhysicalFragment();
   if (results.size() == 1u) {
     return first_fragment.Size();
   }
@@ -3809,7 +3815,7 @@
   LogicalSize size;
   for (const auto& result : results) {
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
     LogicalSize fragment_logical_size =
         converter.ToLogical(physical_fragment.Size());
     if (physical_fragment.IsFirstForNode()) {
@@ -4286,7 +4292,7 @@
 #if EXPENSIVE_DCHECKS_ARE_ON()
 template <typename Function>
 void AssertSameDataOnLayoutResults(
-    const LayoutBox::NGLayoutResultList& layout_results,
+    const LayoutBox::LayoutResultList& layout_results,
     Function func) {
   // When an out-of-flow box is fragmented, the position fallback results on all
   // fragments should be the same.
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index aea34d48..64af571 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -51,10 +51,10 @@
 class CustomLayoutChild;
 class EarlyBreak;
 class LayoutMultiColumnSpannerPlaceholder;
-class NGLayoutResult;
+class LayoutResult;
 class ShapeOutsideInfo;
 class WritingModeConverter;
-enum class NGLayoutCacheStatus;
+enum class LayoutCacheStatus;
 struct FragmentGeometry;
 struct NonOverflowingScrollRange;
 struct PaintInfo;
@@ -337,7 +337,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const override;
+                       OutlineType) const override;
 
   // Use this with caution! No type checking is done!
   LayoutBox* PreviousSiblingBox() const;
@@ -620,9 +620,9 @@
   void ClearFirstInlineFragmentItemIndex() final;
   void SetFirstInlineFragmentItemIndex(wtf_size_t) final;
 
-  void InvalidateItems(const NGLayoutResult&);
+  void InvalidateItems(const LayoutResult&);
 
-  void SetCachedLayoutResult(const NGLayoutResult*, wtf_size_t index);
+  void SetCachedLayoutResult(const LayoutResult*, wtf_size_t index);
 
   // Store one layout result (with its physical fragment) at the specified
   // index.
@@ -642,17 +642,17 @@
   // until we're done, as deleting entries will trigger unnecessary paint
   // invalidation. With any luck, we'll end up with the same number of results
   // as the last time, so that paint invalidation might not be necessary.
-  void SetLayoutResult(const NGLayoutResult*, wtf_size_t index);
+  void SetLayoutResult(const LayoutResult*, wtf_size_t index);
 
   // Append one layout result at the end.
-  void AppendLayoutResult(const NGLayoutResult*);
+  void AppendLayoutResult(const LayoutResult*);
 
   // Replace a specific layout result. Also perform finalization if it's the
   // last result (see FinalizeLayoutResults()), but this function does not
   // delete any (old) results following this one. Callers should generally use
   // SetLayoutResult() instead of this one, unless they have good reasons not
   // to.
-  void ReplaceLayoutResult(const NGLayoutResult*, wtf_size_t index);
+  void ReplaceLayoutResult(const LayoutResult*, wtf_size_t index);
 
   void ShrinkLayoutResults(wtf_size_t results_to_keep);
 
@@ -671,12 +671,12 @@
     SetShouldDoFullPaintInvalidation();
   }
 
-  const NGLayoutResult* GetCachedLayoutResult(const BlockBreakToken*) const;
-  const NGLayoutResult* GetCachedMeasureResult() const;
+  const LayoutResult* GetCachedLayoutResult(const BlockBreakToken*) const;
+  const LayoutResult* GetCachedMeasureResult() const;
 
   // Call in situations where we know that there's at most one fragment. A
   // DCHECK will fail if there are multiple fragments.
-  const NGLayoutResult* GetSingleCachedLayoutResult() const;
+  const LayoutResult* GetSingleCachedLayoutResult() const;
 
   // Returns the last layout result for this block flow with the given
   // constraint space and break token, or null if it is not up-to-date or
@@ -688,20 +688,20 @@
   // |out_cache_status| indicates what type of layout pass is required.
   //
   // TODO(ikilpatrick): Move this function into BlockNode.
-  const NGLayoutResult* CachedLayoutResult(
+  const LayoutResult* CachedLayoutResult(
       const ConstraintSpace&,
       const BlockBreakToken*,
       const EarlyBreak*,
       const ColumnSpannerPath*,
       absl::optional<FragmentGeometry>* initial_fragment_geometry,
-      NGLayoutCacheStatus* out_cache_status);
+      LayoutCacheStatus* out_cache_status);
 
-  using NGLayoutResultList = HeapVector<Member<const NGLayoutResult>, 1>;
+  using LayoutResultList = HeapVector<Member<const LayoutResult>, 1>;
   class NGPhysicalFragmentList {
     STACK_ALLOCATED();
 
    public:
-    explicit NGPhysicalFragmentList(const NGLayoutResultList& layout_results)
+    explicit NGPhysicalFragmentList(const LayoutResultList& layout_results)
         : layout_results_(layout_results) {}
 
     wtf_size_t Size() const { return layout_results_.size(); }
@@ -724,7 +724,7 @@
       using pointer = NGPhysicalBoxFragment*;
       using reference = NGPhysicalBoxFragment&;
 
-      explicit Iterator(const NGLayoutResultList::const_iterator& iterator)
+      explicit Iterator(const LayoutResultList::const_iterator& iterator)
           : iterator_(iterator) {}
 
       const NGPhysicalBoxFragment& operator*() const;
@@ -747,7 +747,7 @@
       }
 
      private:
-      NGLayoutResultList::const_iterator iterator_;
+      LayoutResultList::const_iterator iterator_;
     };
 
     Iterator begin() const { return Iterator(layout_results_.begin()); }
@@ -757,15 +757,15 @@
     const NGPhysicalBoxFragment& back() const;
 
    private:
-    const NGLayoutResultList& layout_results_;
+    const LayoutResultList& layout_results_;
   };
 
   NGPhysicalFragmentList PhysicalFragments() const {
     NOT_DESTROYED();
     return NGPhysicalFragmentList(layout_results_);
   }
-  const NGLayoutResult* GetLayoutResult(wtf_size_t i) const;
-  const NGLayoutResultList& GetLayoutResults() const {
+  const LayoutResult* GetLayoutResult(wtf_size_t i) const;
+  const LayoutResultList& GetLayoutResults() const {
     NOT_DESTROYED();
     return layout_results_;
   }
@@ -1501,8 +1501,8 @@
   LayoutUnit intrinsic_logical_widths_initial_block_size_;
   Member<MinMaxSizesCache> min_max_sizes_cache_;
 
-  Member<const NGLayoutResult> measure_result_;
-  NGLayoutResultList layout_results_;
+  Member<const LayoutResult> measure_result_;
+  LayoutResultList layout_results_;
 
   // LayoutBoxUtils is used for the LayoutNG code querying protected methods on
   // this class, e.g. determining the static-position of OOF elements.
diff --git a/third_party/blink/renderer/core/layout/layout_box_hot.cc b/third_party/blink/renderer/core/layout/layout_box_hot.cc
index adf1264..e42ecc7 100644
--- a/third_party/blink/renderer/core/layout/layout_box_hot.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_hot.cc
@@ -67,15 +67,15 @@
   return HasScrollableOverflowX() || HasScrollableOverflowY();
 }
 
-const NGLayoutResult* LayoutBox::CachedLayoutResult(
+const LayoutResult* LayoutBox::CachedLayoutResult(
     const ConstraintSpace& new_space,
     const BlockBreakToken* break_token,
     const EarlyBreak* early_break,
     const ColumnSpannerPath* column_spanner_path,
     absl::optional<FragmentGeometry>* initial_fragment_geometry,
-    NGLayoutCacheStatus* out_cache_status) {
+    LayoutCacheStatus* out_cache_status) {
   NOT_DESTROYED();
-  *out_cache_status = NGLayoutCacheStatus::kNeedsLayout;
+  *out_cache_status = LayoutCacheStatus::kNeedsLayout;
 
   if (SelfNeedsFullLayout()) {
     return nullptr;
@@ -84,7 +84,7 @@
   const bool use_layout_cache_slot =
       new_space.CacheSlot() == LayoutResultCacheSlot::kLayout &&
       !layout_results_.empty();
-  const NGLayoutResult* cached_layout_result =
+  const LayoutResult* cached_layout_result =
       use_layout_cache_slot ? GetCachedLayoutResult(break_token)
                             : GetCachedMeasureResult();
 
@@ -98,13 +98,13 @@
     return nullptr;
   }
 
-  DCHECK_EQ(cached_layout_result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(cached_layout_result->Status(), LayoutResult::kSuccess);
 
   // Set our initial temporary cache status to "hit".
-  NGLayoutCacheStatus cache_status = NGLayoutCacheStatus::kHit;
+  LayoutCacheStatus cache_status = LayoutCacheStatus::kHit;
 
   const NGPhysicalBoxFragment& physical_fragment =
-      To<NGPhysicalBoxFragment>(cached_layout_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(cached_layout_result->GetPhysicalFragment());
 
   // No fun allowed for repeated content.
   if ((physical_fragment.GetBreakToken() &&
@@ -121,7 +121,7 @@
       !is_blocked_by_display_lock && ChildNeedsFullLayout();
 
   if (NeedsSimplifiedLayoutOnly()) {
-    cache_status = NGLayoutCacheStatus::kNeedsSimplifiedLayout;
+    cache_status = LayoutCacheStatus::kNeedsSimplifiedLayout;
   } else if (child_needs_layout) {
     // If we have inline children - we can potentially reuse some of the lines.
     if (!ChildrenInline()) {
@@ -150,18 +150,19 @@
       return nullptr;
     }
 
-    cache_status = NGLayoutCacheStatus::kCanReuseLines;
+    cache_status = LayoutCacheStatus::kCanReuseLines;
   }
 
   BlockNode node(this);
-  NGLayoutCacheStatus size_cache_status = CalculateSizeBasedLayoutCacheStatus(
+  LayoutCacheStatus size_cache_status = CalculateSizeBasedLayoutCacheStatus(
       node, break_token, *cached_layout_result, new_space,
       initial_fragment_geometry);
 
   // If our size may change (or we know a descendants size may change), we miss
   // the cache.
-  if (size_cache_status == NGLayoutCacheStatus::kNeedsLayout)
+  if (size_cache_status == LayoutCacheStatus::kNeedsLayout) {
     return nullptr;
+  }
 
   if (cached_layout_result->HasOrthogonalFallbackSizeDescendant() &&
       View()->AffectedByResizedInitialContainingBlock(*cached_layout_result)) {
@@ -176,18 +177,19 @@
   // since it will be used to iteration the invalid children when running
   // simplified layout.
   if (!physical_fragment.ChildrenValid() &&
-      (size_cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout ||
-       cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout)) {
+      (size_cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout ||
+       cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout)) {
     return nullptr;
   }
 
   // Update our temporary cache status, if the size cache check indicated we
   // might need simplified layout.
-  if (size_cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
-      cache_status == NGLayoutCacheStatus::kHit)
-    cache_status = NGLayoutCacheStatus::kNeedsSimplifiedLayout;
+  if (size_cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout &&
+      cache_status == LayoutCacheStatus::kHit) {
+    cache_status = LayoutCacheStatus::kNeedsSimplifiedLayout;
+  }
 
-  if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout) {
+  if (cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout) {
     // Only allow simplified layout for non-replaced boxes.
     if (IsLayoutReplaced())
       return nullptr;
@@ -251,11 +253,12 @@
       // sibling.
       // The "simplified" layout algorithm doesn't have the required logic to
       // shift any added exclusions within the output exclusion space.
-      if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout ||
-          cache_status == NGLayoutCacheStatus::kCanReuseLines)
+      if (cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout ||
+          cache_status == LayoutCacheStatus::kCanReuseLines) {
         return nullptr;
+      }
 
-      DCHECK_EQ(cache_status, NGLayoutCacheStatus::kHit);
+      DCHECK_EQ(cache_status, LayoutCacheStatus::kHit);
 
       if (!MaySkipLayoutWithinBlockFormattingContext(
               *cached_layout_result, new_space, &bfc_block_offset,
@@ -269,8 +272,9 @@
       // Sometimes we perform simplified layout on a block-flow which is just
       // growing in block-size. When fragmentation is present we can't hit the
       // cache for these cases as we may grow past the fragmentation line.
-      if (cache_status != NGLayoutCacheStatus::kHit)
+      if (cache_status != LayoutCacheStatus::kHit) {
         return nullptr;
+      }
 
       // Miss the cache if we have nested multicol containers inside that also
       // have OOF descendants. OOFs in nested multicol containers are handled in
@@ -425,7 +429,7 @@
 
           // Check if we have content which might cross the fragmentation line.
           //
-          // NOTE: It's fine to use NGLayoutResult::BlockSizeForFragmentation()
+          // NOTE: It's fine to use LayoutResult::BlockSizeForFragmentation()
           // directly here, rather than the helper BlockSizeForFragmentation()
           // in ng_fragmentation_utils.cc, since what the latter does shouldn't
           // matter, since we're not monolithic content
@@ -467,31 +471,34 @@
     }
 
     // Simplified layout doesn't support fragmented nodes.
-    if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout)
+    if (cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout) {
       return nullptr;
+    }
   }
 
   // We've performed all of the cache checks at this point. If we need
   // "simplified" layout then abort now.
   *out_cache_status = cache_status;
-  if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout ||
-      cache_status == NGLayoutCacheStatus::kCanReuseLines)
+  if (cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout ||
+      cache_status == LayoutCacheStatus::kCanReuseLines) {
     return cached_layout_result;
+  }
 
   physical_fragment.CheckType();
 
-  DCHECK_EQ(*out_cache_status, NGLayoutCacheStatus::kHit);
+  DCHECK_EQ(*out_cache_status, LayoutCacheStatus::kHit);
 
   // For example, for elements with a transform change we can re-use the cached
   // result but we still need to recalculate the scrollable overflow.
   if (use_layout_cache_slot && !is_blocked_by_display_lock &&
       NeedsScrollableOverflowRecalc()) {
 #if DCHECK_IS_ON()
-    const NGLayoutResult* cloned_cached_layout_result =
-        NGLayoutResult::CloneWithPostLayoutFragments(*cached_layout_result);
+    const LayoutResult* cloned_cached_layout_result =
+        LayoutResult::CloneWithPostLayoutFragments(*cached_layout_result);
 #endif
-    if (!NGDisableSideEffectsScope::IsDisabled())
+    if (!DisableLayoutSideEffectsScope::IsDisabled()) {
       RecalcScrollableOverflow();
+    }
 
     // We need to update the cached layout result, as the call to
     // RecalcScrollableOverflow() might have modified it.
@@ -540,12 +547,14 @@
     return cached_layout_result;
   }
 
-  const NGLayoutResult* new_result = MakeGarbageCollected<NGLayoutResult>(
+  const auto* new_result = MakeGarbageCollected<LayoutResult>(
       *cached_layout_result, new_space, end_margin_strut, bfc_line_offset,
       bfc_block_offset, block_offset_delta);
 
-  if (needs_cached_result_update && !NGDisableSideEffectsScope::IsDisabled())
+  if (needs_cached_result_update &&
+      !DisableLayoutSideEffectsScope::IsDisabled()) {
     SetCachedLayoutResult(new_result, FragmentIndex(break_token));
+  }
 
   return new_result;
 }
@@ -553,7 +562,7 @@
 const NGPhysicalBoxFragment* LayoutBox::GetPhysicalFragment(
     wtf_size_t i) const {
   NOT_DESTROYED();
-  return &To<NGPhysicalBoxFragment>(layout_results_[i]->PhysicalFragment());
+  return &To<NGPhysicalBoxFragment>(layout_results_[i]->GetPhysicalFragment());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
index 0ef217c3..3786a7d 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -349,7 +349,7 @@
 void LayoutBoxModelObject::AddOutlineRectsForNormalChildren(
     OutlineRectCollector& collector,
     const PhysicalOffset& additional_offset,
-    NGOutlineType include_block_overflows) const {
+    OutlineType include_block_overflows) const {
   NOT_DESTROYED();
   for (LayoutObject* child = SlowFirstChild(); child;
        child = child->NextSibling()) {
@@ -367,7 +367,7 @@
     const LayoutObject& descendant,
     OutlineRectCollector& collector,
     const PhysicalOffset& additional_offset,
-    NGOutlineType include_block_overflows) const {
+    OutlineType include_block_overflows) const {
   NOT_DESTROYED();
   if (descendant.IsText()) {
     return;
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h
index 92f5135..668e44fb 100644
--- a/third_party/blink/renderer/core/layout/layout_box_model_object.h
+++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -404,7 +404,7 @@
 
   void AddOutlineRectsForNormalChildren(OutlineRectCollector&,
                                         const PhysicalOffset& additional_offset,
-                                        NGOutlineType) const;
+                                        OutlineType) const;
 
   void UpdateCanCompositeBackgroundAttachmentFixed(
       bool enable_composited_background_attachment_fixed);
@@ -424,7 +424,7 @@
   void AddOutlineRectsForDescendant(const LayoutObject& descendant,
                                     OutlineRectCollector&,
                                     const PhysicalOffset& additional_offset,
-                                    NGOutlineType) const;
+                                    OutlineType) const;
 
   void StyleWillChange(StyleDifference,
                        const ComputedStyle& new_style) override;
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_flow_thread.cc
index 5a79923..8c2e1db 100644
--- a/third_party/blink/renderer/core/layout/layout_flow_thread.cc
+++ b/third_party/blink/renderer/core/layout/layout_flow_thread.cc
@@ -182,7 +182,7 @@
     OutlineRectCollector& collector,
     OutlineInfo* info,
     const PhysicalOffset& additional_offset,
-    NGOutlineType include_block_overflows) const {
+    OutlineType include_block_overflows) const {
   NOT_DESTROYED();
   Vector<PhysicalRect> rects_in_flowthread;
   UnionOutlineRectCollector flow_collector;
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.h b/third_party/blink/renderer/core/layout/layout_flow_thread.h
index 7b7634e..80a4d05 100644
--- a/third_party/blink/renderer/core/layout/layout_flow_thread.h
+++ b/third_party/blink/renderer/core/layout/layout_flow_thread.h
@@ -123,7 +123,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const override;
+                       OutlineType) const override;
 
   void Paint(const PaintInfo& paint_info) const final;
 
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
index cf454ae..99e04a7 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -525,7 +525,7 @@
     MapCoordinatesFlags flags) const {
   NOT_DESTROYED();
   Vector<PhysicalRect> rects = OutlineRects(
-      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, PhysicalOffset(), OutlineType::kIncludeBlockInkOverflow);
   PhysicalRect rect = UnionRect(rects);
   // When empty LayoutInline is not culled, |rect| is empty but |rects| is not.
   if (rect.IsEmpty())
@@ -757,14 +757,14 @@
       // rects for children and continuations.
       AddOutlineRectsForNormalChildren(
           collector, PhysicalOffset(),
-          style.OutlineRectsShouldIncludeBlockVisualOverflow());
+          style.OutlineRectsShouldIncludeBlockInkOverflow());
     } else {
       // In non-standard mode, because the difference in
       // LayoutBlock::minLineHeightForReplacedObject(),
       // linesVisualOverflowBoundingBox() may not cover outline rects of lines
       // containing replaced objects.
       AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                      style.OutlineRectsShouldIncludeBlockVisualOverflow());
+                      style.OutlineRectsShouldIncludeBlockInkOverflow());
     }
     if (!collector.Rect().IsEmpty()) {
       PhysicalRect outline_rect = collector.Rect();
@@ -883,11 +883,10 @@
       PaintInvalidationReason::kImage);
 }
 
-void LayoutInline::AddOutlineRects(
-    OutlineRectCollector& collector,
-    OutlineInfo* info,
-    const PhysicalOffset& additional_offset,
-    NGOutlineType include_block_overflows) const {
+void LayoutInline::AddOutlineRects(OutlineRectCollector& collector,
+                                   OutlineInfo* info,
+                                   const PhysicalOffset& additional_offset,
+                                   OutlineType include_block_overflows) const {
   NOT_DESTROYED();
 #if DCHECK_IS_ON()
   // TODO(crbug.com/987836): enable this DCHECK universally.
@@ -931,7 +930,7 @@
   NOT_DESTROYED();
   UnionOutlineRectCollector collector;
   AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                  NGOutlineType::kIncludeBlockVisualOverflow);
+                  OutlineType::kIncludeBlockInkOverflow);
 
   return gfx::RectF(FlipForWritingMode(collector.Rect().ToLayoutRect()));
 }
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h
index 3be5b60..84f7c3e 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -164,7 +164,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const override;
+                       OutlineType) const override;
 
   bool AlwaysCreateLineBoxes() const {
     NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/layout_inline_test.cc b/third_party/blink/renderer/core/layout/layout_inline_test.cc
index 0b8579f1..40f1894 100644
--- a/third_party/blink/renderer/core/layout/layout_inline_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline_test.cc
@@ -465,7 +465,7 @@
   )HTML");
 
   auto rects = GetLayoutObjectByElementId("target")->OutlineRects(
-      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, PhysicalOffset(), OutlineType::kIncludeBlockInkOverflow);
 
   EXPECT_THAT(
       rects, UnorderedElementsAre(PhysicalRect(0, 0, 100, 20),   // 'SPAN0'
@@ -501,7 +501,7 @@
   auto* target = GetLayoutObjectByElementId("target");
   auto rects =
       target->OutlineRects(nullptr, target->FirstFragment().PaintOffset(),
-                           NGOutlineType::kIncludeBlockVisualOverflow);
+                           OutlineType::kIncludeBlockInkOverflow);
   EXPECT_THAT(rects, UnorderedElementsAre(
                          PhysicalRect(180, 0, 20, 120),     // 'INLINE'
                          PhysicalRect(160, 0, 20, 80),      // 'TEXT'
@@ -536,7 +536,7 @@
   auto* target = GetLayoutObjectByElementId("target");
   auto rects =
       target->OutlineRects(nullptr, target->FirstFragment().PaintOffset(),
-                           NGOutlineType::kIncludeBlockVisualOverflow);
+                           OutlineType::kIncludeBlockInkOverflow);
   EXPECT_THAT(rects, UnorderedElementsAre(
                          PhysicalRect(180, 0, 20, 100),   // 'SPAN0'
                          PhysicalRect(140, 0, 40, 400),   // div DIV1
@@ -569,7 +569,7 @@
   )HTML");
 
   auto rects = GetLayoutObjectByElementId("target")->OutlineRects(
-      nullptr, PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, PhysicalOffset(), OutlineType::kIncludeBlockInkOverflow);
 
   EXPECT_THAT(rects, UnorderedElementsAre(
                          PhysicalRect(0, 0, 120, 20),     // 'INLINE'
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 5c6438b..d62897f 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -1265,7 +1265,7 @@
   }
 
   // We need a previous layout result to begin layout at a subtree root.
-  const NGLayoutResult* layout_result = box->GetCachedLayoutResult(nullptr);
+  const LayoutResult* layout_result = box->GetCachedLayoutResult(nullptr);
   if (!layout_result) {
     return false;
   }
@@ -1307,7 +1307,7 @@
   }
 
   // Make sure our fragment is safe to use.
-  const NGPhysicalFragment& fragment = layout_result->PhysicalFragment();
+  const auto& fragment = layout_result->GetPhysicalFragment();
   if (fragment.IsLayoutObjectDestroyedOrMoved()) {
     return false;
   }
@@ -1533,22 +1533,22 @@
 
 // LayoutNG has different OOF-positioned handling compared to the existing
 // layout system. To correctly determine the static-position of the object,
-// LayoutNG "bubbles" up the static-position inside the NGLayoutResult.
-// See: |NGLayoutResult::OutOfFlowPositionedDescendants()|.
+// LayoutNG "bubbles" up the static-position inside the LayoutResult.
+// See: |LayoutResult::OutOfFlowPositionedDescendants()|.
 //
 // Column spanners also have a bubbling mechanism, and therefore also need to
 // mark ancestors between the element itself and the containing block (the
 // multicol container).
 //
 // Whenever an OOF-positioned object is added/removed we need to invalidate
-// layout for all the layout objects which may have stored a NGLayoutResult
+// layout for all the layout objects which may have stored a LayoutResult
 // with this object contained in that list.
 //
 // In the future it may be possible to optimize this, e.g.
 //  - For the removal case, add a pass which modifies the layout result to
 //    remove the OOF-positioned descendant.
 //  - For the adding case, if the OOF-positioned doesn't require a
-//    static-position, simply insert the object up the NGLayoutResult chain with
+//    static-position, simply insert the object up the LayoutResult chain with
 //    an invalid static-position.
 void LayoutObject::MarkParentForSpannerOrOutOfFlowPositionedChange() {
   NOT_DESTROYED();
@@ -1575,7 +1575,7 @@
     object = object->Parent();
   }
   // Finally mark the parent block for layout. This will mark everything which
-  // has an OOF-positioned object or column spanner in a NGLayoutResult as
+  // has an OOF-positioned object or column spanner in a LayoutResult as
   // needing layout.
   if (object)
     object->SetChildNeedsLayout();
@@ -4971,7 +4971,7 @@
 }
 
 Vector<PhysicalRect> LayoutObject::CollectOutlineRectsAndAdvance(
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     AccompaniedFragmentIterator& iterator) const {
   NOT_DESTROYED();
   Vector<PhysicalRect> outline_rects;
@@ -5018,7 +5018,7 @@
 Vector<PhysicalRect> LayoutObject::OutlineRects(
     OutlineInfo* info,
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type) const {
+    OutlineType outline_type) const {
   NOT_DESTROYED();
   VectorOutlineRectCollector collector;
   AddOutlineRects(collector, info, additional_offset, outline_type);
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 2435203..10b08f1 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2850,7 +2850,7 @@
   // |iterator|. This method will also advance |iterator| to the next
   // FragmentData (and therefore also next fragmentainer), if any.
   Vector<PhysicalRect> CollectOutlineRectsAndAdvance(
-      NGOutlineType,
+      OutlineType,
       AccompaniedFragmentIterator& iterator) const;
 
   struct OutlineInfo {
@@ -2885,7 +2885,7 @@
   // in the same space as the physical rects returned.
   Vector<PhysicalRect> OutlineRects(OutlineInfo*,
                                     const PhysicalOffset& additional_offset,
-                                    NGOutlineType) const;
+                                    OutlineType) const;
 
   // Collects rectangles that the outline of this object would be drawing along
   // the outside of, even if the object isn't styled with a outline for now.
@@ -2894,7 +2894,7 @@
   virtual void AddOutlineRects(OutlineRectCollector&,
                                OutlineInfo*,
                                const PhysicalOffset& additional_offset,
-                               NGOutlineType) const {
+                               OutlineType) const {
     NOT_DESTROYED();
   }
 
diff --git a/third_party/blink/renderer/core/layout/layout_text_combine_test.cc b/third_party/blink/renderer/core/layout/layout_text_combine_test.cc
index 9ae63b2..54a713a 100644
--- a/third_party/blink/renderer/core/layout/layout_text_combine_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_text_combine_test.cc
@@ -718,14 +718,14 @@
   const auto& sample1 = *GetLayoutObjectByElementId("t1");
   VectorOutlineRectCollector collector;
   sample1.AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                          NGOutlineType::kDontIncludeBlockVisualOverflow);
+                          OutlineType::kDontIncludeBlockInkOverflow);
   Vector<PhysicalRect> standard_outlines1 = collector.TakeRects();
   EXPECT_THAT(
       standard_outlines1,
       ElementsAre(PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 200))));
 
   sample1.AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                          NGOutlineType::kIncludeBlockVisualOverflow);
+                          OutlineType::kIncludeBlockInkOverflow);
   Vector<PhysicalRect> focus_outlines1 = collector.TakeRects();
   EXPECT_THAT(
       focus_outlines1,
@@ -741,14 +741,14 @@
   // Sample 1 without text-combine-upright:all
   const auto& sample2 = *GetLayoutObjectByElementId("t2");
   sample2.AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                          NGOutlineType::kDontIncludeBlockVisualOverflow);
+                          OutlineType::kDontIncludeBlockInkOverflow);
   Vector<PhysicalRect> standard_outlines2 = collector.TakeRects();
   EXPECT_THAT(
       standard_outlines2,
       ElementsAre(PhysicalRect(PhysicalOffset(0, 0), PhysicalSize(150, 100))));
 
   sample1.AddOutlineRects(collector, nullptr, PhysicalOffset(),
-                          NGOutlineType::kIncludeBlockVisualOverflow);
+                          OutlineType::kIncludeBlockInkOverflow);
   Vector<PhysicalRect> focus_outlines2 = collector.TakeRects();
   EXPECT_THAT(
       focus_outlines2,
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index f98f47c..3b53a22 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -987,13 +987,13 @@
 }
 
 bool LayoutView::AffectedByResizedInitialContainingBlock(
-    const NGLayoutResult& layout_result) {
+    const LayoutResult& layout_result) {
   NOT_DESTROYED();
   if (!initial_containing_block_resize_handled_list_) {
     return false;
   }
   const LayoutObject* layout_object =
-      layout_result.PhysicalFragment().GetLayoutObject();
+      layout_result.GetPhysicalFragment().GetLayoutObject();
   DCHECK(layout_object);
   auto add_result =
       initial_containing_block_resize_handled_list_->insert(layout_object);
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h
index a84b065..c28a267 100644
--- a/third_party/blink/renderer/core/layout/layout_view.h
+++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -268,7 +268,7 @@
   // Return true if re-laying out the specified node (as a cached layout result)
   // with a new initial containing block size. Subsequent calls for the same
   // node within the same lifecycle update will return false.
-  bool AffectedByResizedInitialContainingBlock(const NGLayoutResult&);
+  bool AffectedByResizedInitialContainingBlock(const LayoutResult&);
 
   // Update generated markers and counters after style and layout tree update.
   // container - The container for container queries, otherwise nullptr.
diff --git a/third_party/blink/renderer/core/layout/list/README.md b/third_party/blink/renderer/core/layout/list/README.md
index a53ce9b..ae4f4be 100644
--- a/third_party/blink/renderer/core/layout/list/README.md
+++ b/third_party/blink/renderer/core/layout/list/README.md
@@ -92,7 +92,7 @@
 if it appears within a block formatting context,
 but its positioning is determined when [LayoutListItem] is laid out.
 
-To do this, algorithms can set an unpositioned list marker to [NGLayoutResult],
+To do this, algorithms can set an unpositioned list marker to [LayoutResult],
 which will be propagated to the nearest [LayoutListItem],
 similar to absolute positioned objects propagate to its containing blocks.
 
@@ -139,5 +139,5 @@
 [LayoutListItem]: layout_list_item.h
 [LayoutInsideListMarker]: layout_inside_list_marker.h
 [LayoutOutsideListMarker]: layout_outside_list_marker.h
-[NGLayoutResult]: ../ng/ng_layout_result.h
+[LayoutResult]: ../ng/ng_layout_result.h
 [PaintLayer]: ../../paint/PaintLayer.h
diff --git a/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.cc b/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.cc
index 7087d92..c1d41733 100644
--- a/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.cc
+++ b/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.cc
@@ -36,7 +36,7 @@
   return margins.first;
 }
 
-const NGLayoutResult* UnpositionedListMarker::Layout(
+const LayoutResult* UnpositionedListMarker::Layout(
     const ConstraintSpace& parent_space,
     const ComputedStyle& parent_style,
     FontBaseline baseline_type) const {
@@ -45,7 +45,7 @@
 
   // We need the first-line baseline from the list-marker, instead of the
   // typical atomic-inline baseline.
-  const NGLayoutResult* marker_layout_result = marker_node.LayoutAtomicInline(
+  const LayoutResult* marker_layout_result = marker_node.LayoutAtomicInline(
       parent_space, parent_style, parent_space.UseFirstLineStyle(),
       BaselineAlgorithmType::kDefault);
   DCHECK(marker_layout_result);
@@ -83,12 +83,12 @@
     FontBaseline baseline_type,
     const NGPhysicalFragment& content,
     const BoxStrut& border_scrollbar_padding,
-    const NGLayoutResult& marker_layout_result,
+    const LayoutResult& marker_layout_result,
     LayoutUnit content_baseline,
     LayoutUnit* block_offset,
     BoxFragmentBuilder* container_builder) const {
-  const NGPhysicalBoxFragment& marker_physical_fragment =
-      To<NGPhysicalBoxFragment>(marker_layout_result.PhysicalFragment());
+  const auto& marker_physical_fragment =
+      To<NGPhysicalBoxFragment>(marker_layout_result.GetPhysicalFragment());
 
   // Compute the inline offset of the marker.
   LogicalBoxFragment marker_fragment(space.GetWritingDirection(),
@@ -125,11 +125,11 @@
 void UnpositionedListMarker::AddToBoxWithoutLineBoxes(
     const ConstraintSpace& space,
     FontBaseline baseline_type,
-    const NGLayoutResult& marker_layout_result,
+    const LayoutResult& marker_layout_result,
     BoxFragmentBuilder* container_builder,
     LayoutUnit* intrinsic_block_size) const {
-  const NGPhysicalBoxFragment& marker_physical_fragment =
-      To<NGPhysicalBoxFragment>(marker_layout_result.PhysicalFragment());
+  const auto& marker_physical_fragment =
+      To<NGPhysicalBoxFragment>(marker_layout_result.GetPhysicalFragment());
 
   // When there are no line boxes, marker is top-aligned to the list item.
   // https://github.com/w3c/csswg-drafts/issues/2417
diff --git a/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.h b/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.h
index be466f52..82711a5 100644
--- a/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.h
+++ b/third_party/blink/renderer/core/layout/list/unpositioned_list_marker.h
@@ -22,8 +22,8 @@
 class ComputedStyle;
 class ConstraintSpace;
 class LayoutOutsideListMarker;
+class LayoutResult;
 class LayoutUnit;
-class NGLayoutResult;
 class NGPhysicalFragment;
 
 // Represents an unpositioned list marker.
@@ -34,7 +34,7 @@
 //
 // To handle these two cases consistently, when list markers appear in these
 // algorithm, they are set as "unpositioned", and are propagated to ancestors
-// through NGLayoutResult until they meet the corresponding list items.
+// through LayoutResult until they meet the corresponding list items.
 //
 // In order to adjust with the other content of LI, marker will be handled
 // after other children.
@@ -72,7 +72,7 @@
                 FontBaseline,
                 const NGPhysicalFragment& content,
                 const BoxStrut&,
-                const NGLayoutResult& marker_layout_result,
+                const LayoutResult& marker_layout_result,
                 LayoutUnit content_baseline,
                 LayoutUnit* block_offset,
                 BoxFragmentBuilder*) const;
@@ -82,7 +82,7 @@
   // marker.
   void AddToBoxWithoutLineBoxes(const ConstraintSpace&,
                                 FontBaseline,
-                                const NGLayoutResult& marker_layout_result,
+                                const LayoutResult& marker_layout_result,
                                 BoxFragmentBuilder*,
                                 LayoutUnit* intrinsic_block_size) const;
   LayoutUnit InlineOffset(const LayoutUnit marker_inline_size) const;
@@ -91,9 +91,9 @@
     return marker_layout_object_ == other.marker_layout_object_;
   }
 
-  const NGLayoutResult* Layout(const ConstraintSpace& parent_space,
-                               const ComputedStyle& parent_style,
-                               FontBaseline) const;
+  const LayoutResult* Layout(const ConstraintSpace& parent_space,
+                             const ComputedStyle& parent_style,
+                             FontBaseline) const;
 
 #if DCHECK_IS_ON()
   void CheckMargin() const;
diff --git a/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.cc
index 100bfb8..8f6e2d2 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.cc
@@ -151,7 +151,7 @@
   DCHECK(*denominator);
 }
 
-const NGLayoutResult* MathFractionLayoutAlgorithm::Layout() {
+const LayoutResult* MathFractionLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
 
   BlockNode numerator = nullptr;
@@ -160,23 +160,25 @@
 
   const auto numerator_space = CreateConstraintSpaceForMathChild(
       Node(), ChildAvailableSize(), GetConstraintSpace(), numerator);
-  const NGLayoutResult* numerator_layout_result =
+  const LayoutResult* numerator_layout_result =
       numerator.Layout(numerator_space);
   const auto numerator_margins = ComputeMarginsFor(
       numerator_space, numerator.Style(), GetConstraintSpace());
   const auto denominator_space = CreateConstraintSpaceForMathChild(
       Node(), ChildAvailableSize(), GetConstraintSpace(), denominator);
-  const NGLayoutResult* denominator_layout_result =
+  const LayoutResult* denominator_layout_result =
       denominator.Layout(denominator_space);
   const auto denominator_margins = ComputeMarginsFor(
       denominator_space, denominator.Style(), GetConstraintSpace());
 
   const LogicalBoxFragment numerator_fragment(
       GetConstraintSpace().GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(numerator_layout_result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(
+          numerator_layout_result->GetPhysicalFragment()));
   const LogicalBoxFragment denominator_fragment(
       GetConstraintSpace().GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(denominator_layout_result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(
+          denominator_layout_result->GetPhysicalFragment()));
   const auto baseline_type = Style().GetFontBaseline();
 
   const LayoutUnit numerator_ascent =
diff --git a/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.h
index 740edac..42bc3b85 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_fraction_layout_algorithm.h
@@ -16,7 +16,7 @@
   explicit MathFractionLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
  private:
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 
diff --git a/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.cc
index 8d1a781..1c3eb646 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.cc
@@ -32,7 +32,7 @@
       Node().IsInlineFormattingContextRoot());
 }
 
-const NGLayoutResult* MathOperatorLayoutAlgorithm::Layout() {
+const LayoutResult* MathOperatorLayoutAlgorithm::Layout() {
   // This algorithm can only be used for operators with a single text node,
   // which itself must contain only one glyph. We ensure that the subtree is
   // properly laid out but the glyph will actually be used to determine a
@@ -46,7 +46,7 @@
 
   SimpleInlineChildLayoutContext context(To<InlineNode>(child),
                                          &container_builder_);
-  const NGLayoutResult* child_layout_result = To<InlineNode>(child).Layout(
+  const LayoutResult* child_layout_result = To<InlineNode>(child).Layout(
       GetConstraintSpace(), /* break_token */ nullptr,
       /* column_spanner_path */ nullptr, &context);
   container_builder_.AddResult(*child_layout_result, {});
diff --git a/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.h
index 29e3da0..fba8fb47 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_operator_layout_algorithm.h
@@ -19,7 +19,7 @@
   explicit MathOperatorLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
  private:
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
   UChar32 GetBaseCodePoint() const;
 };
diff --git a/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.cc
index 29c45bf..31d4de5 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.cc
@@ -54,20 +54,20 @@
   }
 }
 
-const NGLayoutResult* MathPaddedLayoutAlgorithm::Layout() {
+const LayoutResult* MathPaddedLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
 
   BlockNode content = nullptr;
   GetContentAsAnonymousMrow(&content);
   LayoutUnit content_ascent, content_descent;
   BoxStrut content_margins;
-  const NGLayoutResult* content_layout_result = nullptr;
+  const LayoutResult* content_layout_result = nullptr;
   if (content) {
     ConstraintSpace constraint_space = CreateConstraintSpaceForMathChild(
         Node(), ChildAvailableSize(), GetConstraintSpace(), content);
     content_layout_result = content.Layout(constraint_space);
     const auto& content_fragment =
-        To<NGPhysicalBoxFragment>(content_layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(content_layout_result->GetPhysicalFragment());
     content_margins = ComputeMarginsFor(constraint_space, content.Style(),
                                         GetConstraintSpace());
     LogicalBoxFragment fragment(GetConstraintSpace().GetWritingDirection(),
diff --git a/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.h
index df1a714..65e8444 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_padded_layout_algorithm.h
@@ -16,7 +16,7 @@
  public:
   explicit MathPaddedLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 
diff --git a/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.cc
index 3f515f7..5e5f953c 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.cc
@@ -61,7 +61,7 @@
   }
 }
 
-const NGLayoutResult* MathRadicalLayoutAlgorithm::Layout() {
+const LayoutResult* MathRadicalLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
   DCHECK(IsValidMathMLRadical(Node()));
 
@@ -77,8 +77,8 @@
   BlockNode index = nullptr;
   GatherChildren(&base, &index, &container_builder_);
 
-  const NGLayoutResult* base_layout_result = nullptr;
-  const NGLayoutResult* index_layout_result = nullptr;
+  const LayoutResult* base_layout_result = nullptr;
+  const LayoutResult* index_layout_result = nullptr;
   if (base) {
     // Handle layout of base child. For <msqrt> the base is anonymous and uses
     // the row layout algorithm.
@@ -86,7 +86,7 @@
         Node(), ChildAvailableSize(), GetConstraintSpace(), base);
     base_layout_result = base.Layout(constraint_space);
     const auto& base_fragment =
-        To<NGPhysicalBoxFragment>(base_layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(base_layout_result->GetPhysicalFragment());
     base_margins =
         ComputeMarginsFor(constraint_space, base.Style(), GetConstraintSpace());
     LogicalBoxFragment fragment(GetConstraintSpace().GetWritingDirection(),
@@ -102,7 +102,7 @@
         Node(), ChildAvailableSize(), GetConstraintSpace(), index);
     index_layout_result = index.Layout(constraint_space);
     const auto& index_fragment =
-        To<NGPhysicalBoxFragment>(index_layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(index_layout_result->GetPhysicalFragment());
     index_margins = ComputeMarginsFor(constraint_space, index.Style(),
                                       GetConstraintSpace());
     LogicalBoxFragment fragment(GetConstraintSpace().GetWritingDirection(),
diff --git a/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.h
index 85a0ac03..e62d484 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_radical_layout_algorithm.h
@@ -16,7 +16,7 @@
  public:
   explicit MathRadicalLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 
diff --git a/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.cc
index 787a052..63364c6 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.cc
@@ -66,10 +66,10 @@
   if (!inherits_block_stretch_size_constraint &&
       !inherits_inline_stretch_size_constraint) {
     auto UpdateBlockStretchSizes =
-        [&](const NGLayoutResult* result) {
+        [&](const LayoutResult* result) {
           LogicalBoxFragment fragment(
               constraint_space.GetWritingDirection(),
-              To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+              To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
           LayoutUnit ascent = fragment.FirstBaselineOrSynthesize(baseline_type);
           stretch_sizes.ascent = std::max(stretch_sizes.ascent, ascent),
           stretch_sizes.descent =
@@ -154,7 +154,7 @@
     if (should_add_space)
       DetermineOperatorSpacing(To<BlockNode>(child), &lspace, &rspace);
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(child_layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(child_layout_result->GetPhysicalFragment());
     LogicalBoxFragment fragment(constraint_space.GetWritingDirection(),
                                 physical_fragment);
 
@@ -189,7 +189,7 @@
   row_total_size->block_size = max_row_ascent + max_row_descent;
 }
 
-const NGLayoutResult* MathRowLayoutAlgorithm::Layout() {
+const LayoutResult* MathRowLayoutAlgorithm::Layout() {
   DCHECK(!IsBreakInside(GetBreakToken()));
 
   bool is_display_block_math =
diff --git a/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.h
index fe1184dc..95c2364 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_row_layout_algorithm.h
@@ -25,7 +25,7 @@
     ChildWithOffsetAndMargins(const BlockNode& child,
                               const BoxStrut& margins,
                               LogicalOffset offset,
-                              const NGLayoutResult* result)
+                              const LayoutResult* result)
         : child(child),
           margins(margins),
           offset(offset),
@@ -39,12 +39,12 @@
     BlockNode child;
     BoxStrut margins;
     LogicalOffset offset;
-    Member<const NGLayoutResult> result;
+    Member<const LayoutResult> result;
   };
   typedef HeapVector<ChildWithOffsetAndMargins, 4> ChildrenVector;
 
  private:
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 
diff --git a/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.cc
index efc25ba6..e4aa6f8e 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.cc
@@ -275,7 +275,8 @@
       child.Layout(constraint_space, nullptr /*break_token*/);
   LogicalBoxFragment fragment(
       GetConstraintSpace().GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(child_and_metrics.result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(
+          child_and_metrics.result->GetPhysicalFragment()));
   child_and_metrics.inline_size = fragment.InlineSize();
   child_and_metrics.margins =
       ComputeMarginsFor(constraint_space, child.Style(), GetConstraintSpace());
@@ -288,7 +289,7 @@
   return child_and_metrics;
 }
 
-const NGLayoutResult* MathScriptsLayoutAlgorithm::Layout() {
+const LayoutResult* MathScriptsLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
 
   BlockNode base = nullptr;
diff --git a/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.h
index e1dcfc5..6b4372b 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_scripts_layout_algorithm.h
@@ -24,7 +24,7 @@
     DISALLOW_NEW();
 
    public:
-    Member<const NGLayoutResult> result;
+    Member<const LayoutResult> result;
     LayoutUnit ascent;
     LayoutUnit descent;
     LayoutUnit inline_size;
@@ -79,7 +79,7 @@
       const ChildrenAndMetrics& sub_metrics,
       const ChildrenAndMetrics& sup_metrics) const;
 
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.cc
index 0e047f4..6d67882 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.cc
@@ -15,7 +15,7 @@
   DCHECK(params.space.IsNewFormattingContext());
 }
 
-const NGLayoutResult* MathSpaceLayoutAlgorithm::Layout() {
+const LayoutResult* MathSpaceLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
 
   LayoutUnit intrinsic_block_size = BorderScrollbarPadding().BlockSum();
diff --git a/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.h
index 2f089f69..28a7e83 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_space_layout_algorithm.h
@@ -17,7 +17,7 @@
   explicit MathSpaceLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
  private:
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 };
diff --git a/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.cc
index d681a12..c356d2c 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.cc
@@ -20,7 +20,7 @@
       Node().IsInlineFormattingContextRoot());
 }
 
-const NGLayoutResult* MathTokenLayoutAlgorithm::Layout() {
+const LayoutResult* MathTokenLayoutAlgorithm::Layout() {
   DCHECK(!IsBreakInside(GetBreakToken()));
 
   LayoutInputNode child = Node().FirstChild();
@@ -40,12 +40,12 @@
 
   SimpleInlineChildLayoutContext context(To<InlineNode>(child),
                                          &container_builder_);
-  const NGLayoutResult* child_layout_result = To<InlineNode>(child).Layout(
+  const LayoutResult* child_layout_result = To<InlineNode>(child).Layout(
       GetConstraintSpace(), /* break_token */ nullptr,
       /* column_spanner_path */ nullptr, &context);
 
   const auto& line_box =
-      To<PhysicalLineBoxFragment>(child_layout_result->PhysicalFragment());
+      To<PhysicalLineBoxFragment>(child_layout_result->GetPhysicalFragment());
   const FontHeight line_metrics = line_box.Metrics();
   container_builder_.AddResult(
       *child_layout_result,
diff --git a/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.h
index 6e5d2176..45d322e 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_token_layout_algorithm.h
@@ -20,7 +20,7 @@
   explicit MathTokenLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
  private:
-  const NGLayoutResult* Layout() final;
+  const LayoutResult* Layout() final;
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) final;
 };
 
diff --git a/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.cc b/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.cc
index b0786564..44b71c1 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.cc
@@ -182,7 +182,7 @@
   }
 }
 
-const NGLayoutResult* MathUnderOverLayoutAlgorithm::Layout() {
+const LayoutResult* MathUnderOverLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
   DCHECK(IsValidMathMLScript(Node()));
 
@@ -216,10 +216,10 @@
 
   // https://w3c.github.io/mathml-core/#dfn-algorithm-for-stretching-operators-along-the-inline-axis
   LayoutUnit inline_stretch_size;
-  auto UpdateInlineStretchSize = [&](const NGLayoutResult* result) {
+  auto UpdateInlineStretchSize = [&](const LayoutResult* result) {
     LogicalFragment fragment(
         constraint_space.GetWritingDirection(),
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
     inline_stretch_size = std::max(inline_stretch_size, fragment.InlineSize());
   };
 
@@ -299,7 +299,7 @@
 
   LogicalBoxFragment base_fragment(
       constraint_space.GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(base_layout_result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(base_layout_result->GetPhysicalFragment()));
   LayoutUnit base_ascent =
       base_fragment.FirstBaselineOrSynthesize(baseline_type);
 
@@ -307,12 +307,12 @@
   // therefore centered relative to themselves).
   if (over) {
     const auto over_space = CreateConstraintSpaceForUnderOverChild(over);
-    const NGLayoutResult* over_layout_result = over.Layout(over_space);
+    const LayoutResult* over_layout_result = over.Layout(over_space);
     BoxStrut over_margins =
         ComputeMarginsFor(over_space, over.Style(), constraint_space);
     LogicalBoxFragment over_fragment(
         constraint_space.GetWritingDirection(),
-        To<NGPhysicalBoxFragment>(over_layout_result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(over_layout_result->GetPhysicalFragment()));
     ascent += parameters.over_extra_ascender + over_margins.block_start;
     LogicalOffset over_offset = {
         content_start_offset.inline_offset + over_margins.inline_start +
@@ -354,12 +354,12 @@
 
   if (under) {
     const auto under_space = CreateConstraintSpaceForUnderOverChild(under);
-    const NGLayoutResult* under_layout_result = under.Layout(under_space);
+    const LayoutResult* under_layout_result = under.Layout(under_space);
     BoxStrut under_margins =
         ComputeMarginsFor(under_space, under.Style(), constraint_space);
     LogicalBoxFragment under_fragment(
         constraint_space.GetWritingDirection(),
-        To<NGPhysicalBoxFragment>(under_layout_result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(under_layout_result->GetPhysicalFragment()));
     descent += under_margins.block_start;
     if (parameters.use_under_over_bar_fallback) {
       if (!HasAccent(Node(), true))
diff --git a/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.h b/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.h
index 3976a16..abbf82d5 100644
--- a/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/mathml/math_under_over_layout_algorithm.h
@@ -16,7 +16,7 @@
  public:
   explicit MathUnderOverLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
diff --git a/third_party/blink/renderer/core/layout/ng/BlockLayout.md b/third_party/blink/renderer/core/layout/ng/BlockLayout.md
index e58312e..b874335 100644
--- a/third_party/blink/renderer/core/layout/ng/BlockLayout.md
+++ b/third_party/blink/renderer/core/layout/ng/BlockLayout.md
@@ -13,7 +13,7 @@
 
 Our block layout implementation is based on the principle that children place
 *themselves* within the block formatting context. This information is
-communicated with the optional [NGLayoutResult::BfcOffset](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/ng/ng_layout_result.h).
+communicated with the optional [LayoutResult::BfcOffset](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/ng/ng_layout_result.h).
 
 A child's BFCOffset is optional as empty blocks cannot place themselves within
 the BFC. They may be affected by siblings.
diff --git a/third_party/blink/renderer/core/layout/ng/block-fragmentation-tutorial.md b/third_party/blink/renderer/core/layout/ng/block-fragmentation-tutorial.md
index 64c2a35..453bacb 100644
--- a/third_party/blink/renderer/core/layout/ng/block-fragmentation-tutorial.md
+++ b/third_party/blink/renderer/core/layout/ng/block-fragmentation-tutorial.md
@@ -14,7 +14,7 @@
 Any layout algorithm for block nodes takes ConstraintSpace, BlockNode and
 BlockBreakToken as input, and writes output to BoxFragmentBuilder, which
 will eventually generate an NGPhysicalBoxFragment wrapped inside an
-NGLayoutResult. This will serve as input to the parent algorithm, which will
+LayoutResult. This will serve as input to the parent algorithm, which will
 eventually add the child fragment to their output, i.e. BoxFragmentBuilder (or
 abort / finish without doing so). Rather than having each layout algorithm
 implement block fragmentation on its own, we have a shared fragmentation
@@ -23,7 +23,7 @@
 algorithm can easily hook up with the various stages or aspects of block
 fragmentation of a node. The utility functions will perform the relevant
 operations on these core NG structures (ConstraintSpace, BlockNode,
-BlockBreakToken, NGLayoutResult, and so on).
+BlockBreakToken, LayoutResult, and so on).
 
 The purpose of the fragmentation machinery is to find the ideal (most appealing)
 places to break in one
@@ -263,7 +263,7 @@
 token](ng_block_break_token.h) to the resulting fragment. The break tokens form
 a tree structure for each parent we need to break and resume inside of, which
 we'll traverse when resuming layout in the next fragmentainer. See for instance
-[NGBlockChildIterator](ng_block_child_iterator.h), and how it makes use of the
+[BlockChildIterator](ng_block_child_iterator.h), and how it makes use of the
 break token tree structure during child layout in
 [BlockLayoutAlgorithm::Layout()](ng_block_layout_algorithm.cc).
 
@@ -389,7 +389,7 @@
 means that we have actually found a better earlier breakpoint (further up in the
 fragmentainer). When this happens, we need to abort and rerun layout, but this
 time with a parameter that says exactly where to stop and break. Early breaks
-are stored in NGLayoutResult when found. See NGLayoutResult::GetEarlyBreak() and
+are stored in LayoutResult when found. See LayoutResult::GetEarlyBreak() and
 the [EarlyBreak](ng_early_break.h) structure.
 
 An algorithm can be rerun to break at the appealing early breakpoint by passing
@@ -564,7 +564,7 @@
 * If we're out of space, and the appeal of breaking before and inside are both
   lower than the appeal of an earlier breakpoint, we need to use said earlier
   breakpoint, which is stored in the fragment builder (and propagated from
-  descendants via their [NGLayoutResult](ng_layout_result.h)). Return
+  descendants via their [LayoutResult](ng_layout_result.h)). Return
   kNeedsEarlierBreak. We'll need to re-run layout in a special mode, where the
   algorithm is told to break at a specified node (automatic breaking will be
   disabled). There may be nested situations to consider here. For example:
@@ -608,11 +608,11 @@
    unappealing it is). Add #a to the #wrapper2 fragment builder.
 1. Lay out #b. There's a perfect breakpoint before it. Overwrite the previously
    found early (last-resort) break. Add #b to the builder. We still have room.
-1. Finish #wrapper2. Its NGLayoutResult will contain the early break pointing
+1. Finish #wrapper2. Its LayoutResult will contain the early break pointing
    before #b. There's a last-resort breakpoint before #wrapper2 (as the first
    child of #wrapper1), but we already have something better - the perfect one
    before #b.
-1. Finish #wrapper1. Its NGLayoutResult will contain the early break pointing
+1. Finish #wrapper1. Its LayoutResult will contain the early break pointing
    inside #wrapper2, which has an early break pointing before #b. There's a
    perfect breakpoint before #wrapper1, but the possible break inside (before
    #b) is further down, so keep that one.
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
index 0956111..a9d2674 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
@@ -67,7 +67,7 @@
     OutlineRectCollector& collector,
     LayoutObject::OutlineInfo* info,
     const PhysicalOffset& additional_offset,
-    NGOutlineType include_block_overflows) const {
+    OutlineType include_block_overflows) const {
   NOT_DESTROYED();
 
   // TODO(crbug.com/1145048): Currently |NGBoxPhysicalFragment| does not support
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
index 3f8fb11..1dce01b 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
@@ -44,7 +44,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        LayoutObject::OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const final;
+                       OutlineType) const final;
 
   void DirtyLinesFromChangedChild(LayoutObject* child) final;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
index e80ab99..12011ad 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -496,7 +496,7 @@
   return depends_on_min_max_sizes;
 }
 
-const NGLayoutResult* ComputeOofBlockDimensions(
+const LayoutResult* ComputeOofBlockDimensions(
     const BlockNode& node,
     const ComputedStyle& style,
     const ConstraintSpace& space,
@@ -511,7 +511,7 @@
 
   const bool is_table = node.IsTable();
 
-  const NGLayoutResult* result = nullptr;
+  const LayoutResult* result = nullptr;
 
   MinMaxSizes min_max_block_sizes = ComputeMinMaxBlockSizes(
       space, style, border_padding, imcb.Size().block_size, anchor_evaluator);
@@ -545,7 +545,7 @@
     }
 
     return LogicalFragment(style.GetWritingDirection(),
-                           result->PhysicalFragment())
+                           result->GetPhysicalFragment())
         .BlockSize();
   };
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
index 2032922..c5d4fa3c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
@@ -18,7 +18,7 @@
 class BlockNode;
 class BoxFragmentBuilder;
 class ConstraintSpace;
-class NGLayoutResult;
+class LayoutResult;
 struct LogicalStaticPosition;
 
 struct CORE_EXPORT LogicalOofDimensions {
@@ -133,7 +133,7 @@
 
 // If layout was performed to determine the position, this will be returned
 // otherwise it will return nullptr.
-CORE_EXPORT const NGLayoutResult* ComputeOofBlockDimensions(
+CORE_EXPORT const LayoutResult* ComputeOofBlockDimensions(
     const BlockNode&,
     const ComputedStyle& style,
     const ConstraintSpace&,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
index 5ddb6670..23ad4d6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
@@ -39,12 +39,12 @@
   FragmentGeometry fragment_geometry =
       CalculateInitialFragmentGeometry(space, node, /* break_token */ nullptr);
 
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       BlockLayoutAlgorithm(
           {node, fragment_geometry, space, To<BlockBreakToken>(break_token)})
           .Layout();
 
-  return To<NGPhysicalBoxFragment>(&result->PhysicalFragment());
+  return To<NGPhysicalBoxFragment>(&result->GetPhysicalFragment());
 }
 
 const NGPhysicalBoxFragment*
@@ -57,12 +57,12 @@
   FragmentGeometry fragment_geometry =
       CalculateInitialFragmentGeometry(space, node, /* break_token */ nullptr);
 
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       FieldsetLayoutAlgorithm(
           {node, fragment_geometry, space, To<BlockBreakToken>(break_token)})
           .Layout();
 
-  return To<NGPhysicalBoxFragment>(&result->PhysicalFragment());
+  return To<NGPhysicalBoxFragment>(&result->GetPhysicalFragment());
 }
 
 const NGPhysicalBoxFragment* BaseLayoutAlgorithmTest::GetBoxFragmentByElementId(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
index e7d656b..73cad6d 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
@@ -11,9 +11,9 @@
 
 namespace blink {
 
-NGBlockChildIterator::NGBlockChildIterator(LayoutInputNode first_child,
-                                           const BlockBreakToken* break_token,
-                                           bool calculate_child_idx)
+BlockChildIterator::BlockChildIterator(LayoutInputNode first_child,
+                                       const BlockBreakToken* break_token,
+                                       bool calculate_child_idx)
     : next_unstarted_child_(first_child),
       break_token_(break_token),
       child_token_idx_(0) {
@@ -37,7 +37,7 @@
   }
 }
 
-NGBlockChildIterator::Entry NGBlockChildIterator::NextChild(
+BlockChildIterator::Entry BlockChildIterator::NextChild(
     const InlineBreakToken* previous_inline_break_token) {
   if (previous_inline_break_token) {
     DCHECK(!child_idx_);
@@ -101,7 +101,7 @@
   return Entry(current_child, current_child_break_token, current_child_idx);
 }
 
-void NGBlockChildIterator::AdvanceToNextChild(const LayoutInputNode& child) {
+void BlockChildIterator::AdvanceToNextChild(const LayoutInputNode& child) {
   next_unstarted_child_ = child.NextSibling();
   if (child_idx_)
     (*child_idx_)++;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
index 209498b..af3c4db 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
@@ -28,13 +28,13 @@
 //
 // This class does not handle modifications to its arguments after it has been
 // constructed.
-class CORE_EXPORT NGBlockChildIterator {
+class CORE_EXPORT BlockChildIterator {
   STACK_ALLOCATED();
 
  public:
-  NGBlockChildIterator(LayoutInputNode first_child,
-                       const BlockBreakToken* break_token,
-                       bool calculate_child_idx = false);
+  BlockChildIterator(LayoutInputNode first_child,
+                     const BlockBreakToken* break_token,
+                     bool calculate_child_idx = false);
 
   // Returns the next input node which should be laid out, along with its
   // respective break token.
@@ -61,7 +61,7 @@
   bool did_handle_first_child_ = false;
 };
 
-struct NGBlockChildIterator::Entry {
+struct BlockChildIterator::Entry {
   STACK_ALLOCATED();
 
  public:
@@ -75,7 +75,7 @@
   const BreakToken* token;
   absl::optional<wtf_size_t> index;
 
-  bool operator==(const NGBlockChildIterator::Entry& other) const {
+  bool operator==(const BlockChildIterator::Entry& other) const {
     return node == other.node && token == other.token;
   }
 };
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
index 3bbcccd..caa270c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator_test.cc
@@ -34,15 +34,14 @@
   return BlockBreakToken::Create(&builder);
 }
 
-using NGBlockChildIteratorTest = RenderingTest;
+using BlockChildIteratorTest = RenderingTest;
 
-TEST_F(NGBlockChildIteratorTest, NullFirstChild) {
-  NGBlockChildIterator iterator(nullptr, nullptr);
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+TEST_F(BlockChildIteratorTest, NullFirstChild) {
+  BlockChildIterator iterator(nullptr, nullptr);
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 }
 
-TEST_F(NGBlockChildIteratorTest, NoBreakToken) {
+TEST_F(BlockChildIteratorTest, NoBreakToken) {
   SetBodyInnerHTML(R"HTML(
       <div id='child1'></div>
       <div id='child2'></div>
@@ -53,15 +52,14 @@
   LayoutInputNode node3 = node2.NextSibling();
 
   // The iterator should loop through three children.
-  NGBlockChildIterator iterator(node1, nullptr);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  BlockChildIterator iterator(node1, nullptr);
+  ASSERT_EQ(BlockChildIterator::Entry(node1, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 }
 
-TEST_F(NGBlockChildIteratorTest, BreakTokens) {
+TEST_F(BlockChildIteratorTest, BreakTokens) {
   SetBodyInnerHTML(R"HTML(
       <div id='container'>
         <div id='child1'></div>
@@ -86,60 +84,56 @@
   const BlockBreakToken* parent_token =
       CreateBreakToken(container, &child_break_tokens);
 
-  NGBlockChildIterator iterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1),
+  BlockChildIterator iterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(node1, child_token1),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node2, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 
   child_break_tokens.clear();
   child_break_tokens.push_back(child_token1);
   child_break_tokens.push_back(child_token2);
   parent_token = CreateBreakToken(container, &child_break_tokens);
 
-  iterator = NGBlockChildIterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1),
+  iterator = BlockChildIterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(node1, child_token1),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node2, child_token2),
+  ASSERT_EQ(BlockChildIterator::Entry(node2, child_token2),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node3, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 
   child_break_tokens.clear();
   child_break_tokens.push_back(child_token2);
   child_break_tokens.push_back(child_token3);
   parent_token = CreateBreakToken(container, &child_break_tokens);
 
-  iterator = NGBlockChildIterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node2, child_token2),
+  iterator = BlockChildIterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(node2, child_token2),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node3, child_token3),
+  ASSERT_EQ(BlockChildIterator::Entry(node3, child_token3),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 
   child_break_tokens.clear();
   child_break_tokens.push_back(child_token1);
   child_break_tokens.push_back(child_token3);
   parent_token = CreateBreakToken(container, &child_break_tokens);
 
-  iterator = NGBlockChildIterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1),
+  iterator = BlockChildIterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(node1, child_token1),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node3, child_token3),
+  ASSERT_EQ(BlockChildIterator::Entry(node3, child_token3),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(node4, nullptr), iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 }
 
-TEST_F(NGBlockChildIteratorTest, SeenAllChildren) {
+TEST_F(BlockChildIteratorTest, SeenAllChildren) {
   SetBodyInnerHTML(R"HTML(
       <div id='container'>
         <div id='child1'></div>
@@ -160,11 +154,10 @@
   // e.g. when #child1 has overflow into a new fragmentainer, while #child2 was
   // finished in an earlier fragmentainer.
 
-  NGBlockChildIterator iterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(node1, child_token1),
+  BlockChildIterator iterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(node1, child_token1),
             iterator.NextChild());
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 
   parent_token = CreateBreakToken(container, /* child_break_tokens */ nullptr,
                                   /* has_seen_all_children*/ true);
@@ -173,12 +166,11 @@
   // we have a large container with fixed block-size, with empty space at the
   // end, not occupied by any children.
 
-  iterator = NGBlockChildIterator(node1, parent_token);
-  ASSERT_EQ(NGBlockChildIterator::Entry(nullptr, nullptr),
-            iterator.NextChild());
+  iterator = BlockChildIterator(node1, parent_token);
+  ASSERT_EQ(BlockChildIterator::Entry(nullptr, nullptr), iterator.NextChild());
 }
 
-TEST_F(NGBlockChildIteratorTest, DeleteNodeWhileIteration) {
+TEST_F(BlockChildIteratorTest, DeleteNodeWhileIteration) {
   SetBodyInnerHTML(R"HTML(
       <div id='child1'></div>
       <div id='child2'></div>
@@ -188,8 +180,8 @@
   LayoutInputNode node2 = node1.NextSibling();
   LayoutInputNode node3 = node2.NextSibling();
 
-  using Entry = NGBlockChildIterator::Entry;
-  NGBlockChildIterator iterator(node1, nullptr);
+  using Entry = BlockChildIterator::Entry;
+  BlockChildIterator iterator(node1, nullptr);
   EXPECT_EQ(Entry(node1, nullptr), iterator.NextChild());
   {
     // Set the container query flag to pass LayoutObject::
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index aa461a3..32f1106 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -88,7 +88,7 @@
   return false;
 }
 
-inline const NGLayoutResult* LayoutBlockChild(
+inline const LayoutResult* LayoutBlockChild(
     const ConstraintSpace& space,
     const BreakToken* break_token,
     const EarlyBreak* early_break,
@@ -102,7 +102,7 @@
                       early_break_in_child, column_spanner_path);
 }
 
-inline const NGLayoutResult* LayoutInflow(
+inline const LayoutResult* LayoutInflow(
     const ConstraintSpace& space,
     const BreakToken* break_token,
     const EarlyBreak* early_break,
@@ -470,8 +470,8 @@
   return {inline_offset, LayoutUnit()};
 }
 
-const NGLayoutResult* BlockLayoutAlgorithm::Layout() {
-  const NGLayoutResult* result = nullptr;
+const LayoutResult* BlockLayoutAlgorithm::Layout() {
+  const LayoutResult* result = nullptr;
   // Inline children require an inline child layout context to be
   // passed between siblings. We want to stack-allocate that one, but
   // only on demand, as it's quite big.
@@ -482,7 +482,7 @@
     result = Layout(nullptr);
   }
 
-  if (result->Status() == NGLayoutResult::kSuccess) {
+  if (result->Status() == LayoutResult::kSuccess) {
     return result;
   }
 
@@ -491,12 +491,12 @@
   return HandleNonsuccessfulLayoutResult(result);
 }
 
-NOINLINE const NGLayoutResult*
+NOINLINE const LayoutResult*
 BlockLayoutAlgorithm::HandleNonsuccessfulLayoutResult(
-    const NGLayoutResult* result) {
-  DCHECK(result->Status() != NGLayoutResult::kSuccess);
+    const LayoutResult* result) {
+  DCHECK(result->Status() != LayoutResult::kSuccess);
   switch (result->Status()) {
-    case NGLayoutResult::kNeedsEarlierBreak: {
+    case LayoutResult::kNeedsEarlierBreak: {
       // If we found a good break somewhere inside this block, re-layout and
       // break at that location.
       DCHECK(result->GetEarlyBreak());
@@ -508,10 +508,10 @@
       BlockLayoutAlgorithm algorithm_with_break(params);
       return RelayoutAndBreakEarlier(&algorithm_with_break);
     }
-    case NGLayoutResult::kNeedsRelayoutWithNoForcedTruncateAtLineClamp:
+    case LayoutResult::kNeedsRelayoutWithNoForcedTruncateAtLineClamp:
       DCHECK(!ignore_line_clamp_);
       return RelayoutIgnoringLineClamp();
-    case NGLayoutResult::kDisableFragmentation:
+    case LayoutResult::kDisableFragmentation:
       DCHECK(GetConstraintSpace().HasBlockFragmentation());
       return RelayoutWithoutFragmentation<BlockLayoutAlgorithm>();
     default:
@@ -519,7 +519,7 @@
   }
 }
 
-const NGLayoutResult* BlockLayoutAlgorithm::LayoutInlineChild(
+const LayoutResult* BlockLayoutAlgorithm::LayoutInlineChild(
     const InlineNode& node) {
   const TextWrap wrap = node.Style().GetTextWrap();
   if (UNLIKELY(wrap == TextWrap::kPretty)) {
@@ -540,25 +540,24 @@
   return LayoutWithSimpleInlineChildLayoutContext(node);
 }
 
-NOINLINE const NGLayoutResult*
+NOINLINE const LayoutResult*
 BlockLayoutAlgorithm::LayoutWithSimpleInlineChildLayoutContext(
     const InlineNode& child) {
   SimpleInlineChildLayoutContext context(child, &container_builder_);
-  const NGLayoutResult* result = Layout(&context);
+  const LayoutResult* result = Layout(&context);
   return result;
 }
 
 template <wtf_size_t capacity>
-NOINLINE const NGLayoutResult*
+NOINLINE const LayoutResult*
 BlockLayoutAlgorithm::LayoutWithOptimalInlineChildLayoutContext(
     const InlineNode& child) {
   OptimalInlineChildLayoutContext<capacity> context(child, &container_builder_);
-  const NGLayoutResult* result = Layout(&context);
+  const LayoutResult* result = Layout(&context);
   return result;
 }
 
-NOINLINE const NGLayoutResult*
-BlockLayoutAlgorithm::RelayoutIgnoringLineClamp() {
+NOINLINE const LayoutResult* BlockLayoutAlgorithm::RelayoutIgnoringLineClamp() {
   LayoutAlgorithmParams params(Node(),
                                container_builder_.InitialFragmentGeometry(),
                                GetConstraintSpace(), GetBreakToken(), nullptr);
@@ -570,7 +569,7 @@
   return algorithm_ignoring_line_clamp.Layout();
 }
 
-inline const NGLayoutResult* BlockLayoutAlgorithm::Layout(
+inline const LayoutResult* BlockLayoutAlgorithm::Layout(
     InlineChildLayoutContext* inline_child_layout_context) {
   DCHECK_EQ(!!inline_child_layout_context,
             Node().IsInlineFormattingContextRoot());
@@ -653,7 +652,7 @@
       // from a break token.
       DCHECK(!constraint_space.IsNewFormattingContext());
       DCHECK(!is_resuming_);
-      return container_builder_.Abort(NGLayoutResult::kBfcBlockOffsetResolved);
+      return container_builder_.Abort(LayoutResult::kBfcBlockOffsetResolved);
     }
     // Move to the content edge. This is where the first child should be placed.
     previous_inflow_position.logical_block_offset = content_edge;
@@ -706,17 +705,17 @@
   // |previous_inflow_position| and |BreakToken()|.
   const InlineBreakToken* previous_inline_break_token = nullptr;
 
-  NGBlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken());
+  BlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken());
 
   // If this layout is blocked by a display-lock, then we pretend this node has
   // no children and that there are no break tokens. Due to this, we skip layout
   // on these children.
   if (Node().ChildLayoutBlockedByDisplayLock())
-    child_iterator = NGBlockChildIterator(BlockNode(nullptr), nullptr);
+    child_iterator = BlockChildIterator(BlockNode(nullptr), nullptr);
 
   BlockNode ruby_text_child(nullptr);
   BlockNode placeholder_child(nullptr);
-  NGBlockChildIterator::Entry entry;
+  BlockChildIterator::Entry entry;
   for (entry = child_iterator.NextChild(); LayoutInputNode child = entry.node;
        entry = child_iterator.NextChild(previous_inline_break_token)) {
     const BreakToken* child_break_token = entry.token;
@@ -811,7 +810,7 @@
           // do that first and re-layout at the right BFC block-offset, and THEN
           // break.
           return container_builder_.Abort(
-              NGLayoutResult::kBfcBlockOffsetResolved);
+              LayoutResult::kBfcBlockOffsetResolved);
         }
         container_builder_.AddBreakBeforeChild(child, kBreakAppealPerfect,
                                                /* is_forced_break */ false);
@@ -819,7 +818,7 @@
         break;
       }
 
-      NGLayoutResult::EStatus status;
+      LayoutResult::EStatus status;
       if (child.CreatesNewFormattingContext()) {
         status = HandleNewFormattingContext(
             child, To<BlockBreakToken>(child_break_token),
@@ -831,7 +830,7 @@
             inline_child_layout_context, &previous_inline_break_token);
       }
 
-      if (status != NGLayoutResult::kSuccess) {
+      if (status != LayoutResult::kSuccess) {
         // We need to abort the layout. No fragment will be generated.
         return container_builder_.Abort(status);
       }
@@ -882,7 +881,7 @@
     // the node may have subsequent lines. If there aren't, the containing
     // element will relayout.
     return container_builder_.Abort(
-        NGLayoutResult::kNeedsRelayoutWithNoForcedTruncateAtLineClamp);
+        LayoutResult::kNeedsRelayoutWithNoForcedTruncateAtLineClamp);
   }
 
   if (!child_iterator.NextChild(previous_inline_break_token).node) {
@@ -908,7 +907,7 @@
   return FinishLayout(&previous_inflow_position, inline_child_layout_context);
 }
 
-const NGLayoutResult* BlockLayoutAlgorithm::FinishLayout(
+const LayoutResult* BlockLayoutAlgorithm::FinishLayout(
     PreviousInflowPosition* previous_inflow_position,
     InlineChildLayoutContext* inline_child_layout_context) {
   const auto& constraint_space = GetConstraintSpace();
@@ -985,8 +984,7 @@
       // determined.
       DCHECK(!constraint_space.IsNewFormattingContext());
       if (!ResolveBfcBlockOffset(previous_inflow_position)) {
-        return container_builder_.Abort(
-            NGLayoutResult::kBfcBlockOffsetResolved);
+        return container_builder_.Abort(LayoutResult::kBfcBlockOffsetResolved);
       }
       DCHECK(container_builder_.BfcBlockOffset());
     } else {
@@ -1078,7 +1076,7 @@
       (border_box_size.block_size || GetBreakToken() ||
        container_builder_.FoundColumnSpanner())) {
     if (!ResolveBfcBlockOffset(previous_inflow_position))
-      return container_builder_.Abort(NGLayoutResult::kBfcBlockOffsetResolved);
+      return container_builder_.Abort(LayoutResult::kBfcBlockOffsetResolved);
     DCHECK(container_builder_.BfcBlockOffset());
   }
 
@@ -1102,7 +1100,7 @@
       // following fragments have a line box.
       !container_builder_.HasInflowChildBreakInside()) {
     if (!PositionListMarkerWithoutLineBoxes(previous_inflow_position))
-      return container_builder_.Abort(NGLayoutResult::kBfcBlockOffsetResolved);
+      return container_builder_.Abort(LayoutResult::kBfcBlockOffsetResolved);
   }
 
   container_builder_.SetEndMarginStrut(end_margin_strut);
@@ -1136,10 +1134,10 @@
     BreakStatus status = FinalizeForFragmentation(block_end_border_padding);
     if (status != BreakStatus::kContinue) {
       if (status == BreakStatus::kNeedsEarlierBreak) {
-        return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+        return container_builder_.Abort(LayoutResult::kNeedsEarlierBreak);
       }
       DCHECK_EQ(status, BreakStatus::kDisableFragmentation);
-      return container_builder_.Abort(NGLayoutResult::kDisableFragmentation);
+      return container_builder_.Abort(LayoutResult::kDisableFragmentation);
     }
 
     // Read the intrinsic block-size back, since it may have been reduced due to
@@ -1233,7 +1231,7 @@
   }
 
   const auto& previous_fragment =
-      To<NGPhysicalBoxFragment>(previous_result_->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(previous_result_->GetPhysicalFragment());
   const FragmentItems* previous_items = previous_fragment.Items();
   DCHECK(previous_items);
 
@@ -1427,13 +1425,13 @@
     return;
   }
 
-  DCHECK_EQ(positioned_float.layout_result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(positioned_float.layout_result->Status(), LayoutResult::kSuccess);
 
   // TODO(mstensho): There should be a class A breakpoint between a float and
   // another float, and also between a float and an in-flow block.
 
   const NGPhysicalFragment& physical_fragment =
-      positioned_float.layout_result->PhysicalFragment();
+      positioned_float.layout_result->GetPhysicalFragment();
   LayoutUnit float_inline_size =
       LogicalFragment(constraint_space.GetWritingDirection(), physical_fragment)
           .InlineSize();
@@ -1449,7 +1447,7 @@
   container_builder_.AddResult(*positioned_float.layout_result, logical_offset);
 }
 
-NGLayoutResult::EStatus BlockLayoutAlgorithm::HandleNewFormattingContext(
+LayoutResult::EStatus BlockLayoutAlgorithm::HandleNewFormattingContext(
     LayoutInputNode child,
     const BlockBreakToken* child_break_token,
     PreviousInflowPosition* previous_inflow_position) {
@@ -1546,7 +1544,7 @@
       // If we need to abort here, it means that we had preceding unpositioned
       // floats. This is only expected if we're here for the first time.
       DCHECK(!bfc_offset_already_resolved);
-      return NGLayoutResult::kBfcBlockOffsetResolved;
+      return LayoutResult::kBfcBlockOffsetResolved;
     }
 
     // We reset the block offset here as it may have been affected by clearance.
@@ -1569,7 +1567,7 @@
                           child_determined_bfc_offset;
   BfcOffset child_bfc_offset;
   BoxStrut resolved_margins;
-  const NGLayoutResult* layout_result = LayoutNewFormattingContext(
+  const LayoutResult* layout_result = LayoutNewFormattingContext(
       child, child_break_token, child_data,
       {child_origin_line_offset, child_bfc_offset_estimate}, abort_if_cleared,
       &child_bfc_offset, &resolved_margins);
@@ -1605,7 +1603,7 @@
         // incorrect estimate is with the child's margin adjoining. Any other
         // incorrect estimate will result in failed layout.
         DCHECK_EQ(old_offset, adjoining_bfc_offset_estimate);
-        return NGLayoutResult::kBfcBlockOffsetResolved;
+        return LayoutResult::kBfcBlockOffsetResolved;
       }
     }
 
@@ -1629,17 +1627,17 @@
         child, *layout_result, previous_inflow_position,
         child_bfc_offset.block_offset, has_container_separation);
     if (break_status == BreakStatus::kBrokeBefore) {
-      return NGLayoutResult::kSuccess;
+      return LayoutResult::kSuccess;
     }
     if (break_status == BreakStatus::kNeedsEarlierBreak) {
-      return NGLayoutResult::kNeedsEarlierBreak;
+      return LayoutResult::kNeedsEarlierBreak;
     }
 
     // If the child aborted layout, we cannot continue.
-    DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+    DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
   }
 
-  const auto& physical_fragment = layout_result->PhysicalFragment();
+  const auto& physical_fragment = layout_result->GetPhysicalFragment();
   LogicalFragment fragment(constraint_space.GetWritingDirection(),
                            physical_fragment);
 
@@ -1649,7 +1647,7 @@
 
   if (!PositionOrPropagateListMarker(*layout_result, &logical_offset,
                                      previous_inflow_position))
-    return NGLayoutResult::kBfcBlockOffsetResolved;
+    return LayoutResult::kBfcBlockOffsetResolved;
 
   PropagateBaselineFromBlockChild(physical_fragment, resolved_margins,
                                   logical_offset.block_offset);
@@ -1671,10 +1669,10 @@
                                            child_break_token);
   }
 
-  return NGLayoutResult::kSuccess;
+  return LayoutResult::kSuccess;
 }
 
-const NGLayoutResult* BlockLayoutAlgorithm::LayoutNewFormattingContext(
+const LayoutResult* BlockLayoutAlgorithm::LayoutNewFormattingContext(
     LayoutInputNode child,
     const BlockBreakToken* child_break_token,
     const InflowChildData& child_data,
@@ -1777,7 +1775,7 @@
     // exclusion space.
     DCHECK(child_space.GetExclusionSpace().IsEmpty());
 
-    const NGLayoutResult* layout_result = LayoutBlockChild(
+    const LayoutResult* layout_result = LayoutBlockChild(
         child_space, child_break_token, early_break_,
         /* column_spanner_path */ nullptr, &To<BlockNode>(child));
 
@@ -1785,11 +1783,11 @@
     // should be returned.
     DCHECK(layout_result->GetExclusionSpace().IsEmpty());
 
-    DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+    DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
 
     // Check if we can fit in the opportunity block direction.
     LogicalFragment fragment(writing_direction,
-                             layout_result->PhysicalFragment());
+                             layout_result->GetPhysicalFragment());
     if (fragment.BlockSize() > opportunity.rect.BlockSize())
       continue;
 
@@ -1804,7 +1802,7 @@
       // Because the marker is laid out as a normal block child, its inline
       // size is extended to fill up the space. Compute the regular marker size
       // from the first child.
-      const auto& marker_fragment = layout_result->PhysicalFragment();
+      const auto& marker_fragment = layout_result->GetPhysicalFragment();
       LayoutUnit marker_inline_size;
       if (!marker_fragment.Children().empty()) {
         marker_inline_size =
@@ -1896,7 +1894,7 @@
   return nullptr;
 }
 
-NGLayoutResult::EStatus BlockLayoutAlgorithm::HandleInflow(
+LayoutResult::EStatus BlockLayoutAlgorithm::HandleInflow(
     LayoutInputNode child,
     const BreakToken* child_break_token,
     PreviousInflowPosition* previous_inflow_position,
@@ -1916,7 +1914,7 @@
       if (TryReuseFragmentsFromCache(*child_inline_node,
                                      previous_inflow_position,
                                      previous_inline_break_token))
-        return NGLayoutResult::kSuccess;
+        return LayoutResult::kSuccess;
     }
   }
 
@@ -1938,7 +1936,7 @@
   // keep in sync.
   if (has_clearance_past_adjoining_floats) {
     if (!ResolveBfcBlockOffset(previous_inflow_position))
-      return NGLayoutResult::kBfcBlockOffsetResolved;
+      return LayoutResult::kBfcBlockOffsetResolved;
 
     // If we had clearance past any adjoining floats, we already know where the
     // child is going to be (the child's margins won't have any effect).
@@ -1962,7 +1960,7 @@
       /* is_new_fc */ false, forced_bfc_block_offset,
       has_clearance_past_adjoining_floats,
       previous_inflow_position->block_end_annotation_space);
-  const NGLayoutResult* layout_result =
+  const LayoutResult* layout_result =
       LayoutInflow(child_space, child_break_token, early_break_,
                    column_spanner_path_, &child, inline_child_layout_context);
 
@@ -1976,12 +1974,12 @@
                       previous_inline_break_token);
 }
 
-NGLayoutResult::EStatus BlockLayoutAlgorithm::FinishInflow(
+LayoutResult::EStatus BlockLayoutAlgorithm::FinishInflow(
     LayoutInputNode child,
     const BreakToken* child_break_token,
     const ConstraintSpace& child_space,
     bool has_clearance_past_adjoining_floats,
-    const NGLayoutResult* layout_result,
+    const LayoutResult* layout_result,
     InflowChildData* child_data,
     PreviousInflowPosition* previous_inflow_position,
     InlineChildLayoutContext* inline_child_layout_context,
@@ -1999,7 +1997,7 @@
   // A child may have aborted its layout if it resolved its BFC block-offset.
   // If we don't have a BFC block-offset yet, we need to propagate the abort
   // signal up to our parent.
-  if (layout_result->Status() == NGLayoutResult::kBfcBlockOffsetResolved &&
+  if (layout_result->Status() == LayoutResult::kBfcBlockOffsetResolved &&
       !container_builder_.BfcBlockOffset()) {
     // There's no need to do anything apart from resolving the BFC block-offset
     // here, so make sure that it aborts before trying to position floats or
@@ -2032,7 +2030,7 @@
 
     if (!ResolveBfcBlockOffset(previous_inflow_position, bfc_block_offset,
                                /* forced_bfc_block_offset */ absl::nullopt))
-      return NGLayoutResult::kBfcBlockOffsetResolved;
+      return LayoutResult::kBfcBlockOffsetResolved;
   }
 
   // We have special behavior for a self-collapsing child which gets pushed
@@ -2065,7 +2063,7 @@
     // is therefore resolvable, and if it hasn't already been resolved, we'll
     // do it now to separate the child's collapsed margin from this container.
     if (!ResolveBfcBlockOffset(previous_inflow_position))
-      return NGLayoutResult::kBfcBlockOffsetResolved;
+      return LayoutResult::kBfcBlockOffsetResolved;
   } else if (layout_result->SubtreeModifiedMarginStrut()) {
     // The child doesn't have clearance, and modified its incoming
     // margin-strut. Propagate this information up to our parent if needed.
@@ -2079,7 +2077,7 @@
     DCHECK(is_self_collapsing);
 
     if (container_builder_.BfcBlockOffset() &&
-        layout_result->Status() == NGLayoutResult::kSuccess) {
+        layout_result->Status() == LayoutResult::kSuccess) {
       // Since we know our own BFC block-offset, though, we can calculate that
       // of the child as well.
       child_bfc_block_offset = PositionSelfCollapsingChildWithParentBfc(
@@ -2087,9 +2085,11 @@
 
       // We may need to relayout this child if it had any (adjoining) objects
       // which were positioned in the incorrect place.
-      if (layout_result->PhysicalFragment().HasAdjoiningObjectDescendants() &&
-          *child_bfc_block_offset != child_space.ExpectedBfcBlockOffset())
+      if (layout_result->GetPhysicalFragment()
+              .HasAdjoiningObjectDescendants() &&
+          *child_bfc_block_offset != child_space.ExpectedBfcBlockOffset()) {
         self_collapsing_child_needs_relayout = true;
+      }
     }
   } else if (!child_had_clearance && !is_self_collapsing) {
     // Only non self-collapsing children are allowed resolve their parent's BFC
@@ -2101,7 +2101,7 @@
     // resolved.
     if (!ResolveBfcBlockOffset(previous_inflow_position,
                                *child_bfc_block_offset))
-      return NGLayoutResult::kBfcBlockOffsetResolved;
+      return LayoutResult::kBfcBlockOffsetResolved;
   }
 
   // We need to re-layout a self-collapsing child if it was affected by
@@ -2137,7 +2137,7 @@
   //  - It aborted its layout as it resolved its BFC block offset.
   //  - It has some unpositioned floats.
   //  - It was affected by clearance.
-  if ((layout_result->Status() == NGLayoutResult::kBfcBlockOffsetResolved ||
+  if ((layout_result->Status() == LayoutResult::kBfcBlockOffsetResolved ||
        self_collapsing_child_needs_relayout) &&
       child_bfc_block_offset) {
     // Assert that any clearance previously detected isn't lost.
@@ -2156,7 +2156,7 @@
         LayoutInflow(new_child_space, child_break_token, early_break_,
                      column_spanner_path_, &child, inline_child_layout_context);
 
-    if (layout_result->Status() == NGLayoutResult::kBfcBlockOffsetResolved) {
+    if (layout_result->Status() == LayoutResult::kBfcBlockOffsetResolved) {
       // Even a second layout pass may abort, if the BFC block offset initially
       // calculated turned out to be wrong. This happens when we discover that
       // an in-flow block-level descendant that establishes a new formatting
@@ -2178,7 +2178,7 @@
                                    inline_child_layout_context);
     }
 
-    DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+    DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
 
     // We stored this in a local variable, so it better not have changed.
     DCHECK_EQ(layout_result->IsSelfCollapsing(), is_self_collapsing);
@@ -2205,7 +2205,7 @@
       // block-in-inline instead of that for the line. That's where we find the
       // relevant info for block fragmentation considerations, including the
       // block break token, if any.
-      const NGLayoutResult& layout_result_to_use =
+      const LayoutResult& layout_result_to_use =
           container_builder_.LayoutResultForPropagation(*layout_result);
 
       BreakStatus break_status = BreakBeforeChildIfNeeded(
@@ -2213,10 +2213,10 @@
           line_box_bfc_block_offset.value_or(*child_bfc_block_offset),
           has_container_separation);
       if (break_status == BreakStatus::kBrokeBefore) {
-        return NGLayoutResult::kSuccess;
+        return LayoutResult::kSuccess;
       }
       if (break_status == BreakStatus::kNeedsEarlierBreak) {
-        return NGLayoutResult::kNeedsEarlierBreak;
+        return LayoutResult::kNeedsEarlierBreak;
       }
     }
 
@@ -2261,7 +2261,7 @@
       container_builder_.SetIsPushedByFloats();
   }
 
-  const auto& physical_fragment = layout_result->PhysicalFragment();
+  const auto& physical_fragment = layout_result->GetPhysicalFragment();
   LogicalFragment fragment(GetConstraintSpace().GetWritingDirection(),
                            physical_fragment);
 
@@ -2275,7 +2275,7 @@
 
   if (!PositionOrPropagateListMarker(*layout_result, &logical_offset,
                                      previous_inflow_position))
-    return NGLayoutResult::kBfcBlockOffsetResolved;
+    return LayoutResult::kBfcBlockOffsetResolved;
 
   if (physical_fragment.IsLineBox()) {
     PropagateBaselineFromLineBox(physical_fragment,
@@ -2326,7 +2326,7 @@
                                            child_break_token);
   }
 
-  return NGLayoutResult::kSuccess;
+  return LayoutResult::kSuccess;
 }
 
 InflowChildData BlockLayoutAlgorithm::ComputeChildData(
@@ -2393,7 +2393,7 @@
     const InflowChildData& child_data,
     const absl::optional<LayoutUnit>& child_bfc_block_offset,
     const LogicalOffset& logical_offset,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     const LogicalFragment& fragment,
     bool self_collapsing_child_had_clearance) {
   // Determine the child's end logical offset, for the next child to use.
@@ -2491,7 +2491,7 @@
     // doesn't really make much of a difference, this isn't the case in the
     // initial column balancing pass.
     if (const auto* physical_fragment = DynamicTo<NGPhysicalBoxFragment>(
-            &layout_result.PhysicalFragment())) {
+            &layout_result.GetPhysicalFragment())) {
       if (const BlockBreakToken* token = physical_fragment->GetBreakToken()) {
         // TODO(mstensho): Don't apply the margin to all overflowing fragments
         // (if any). It should only be applied after the fragment where we
@@ -2536,7 +2536,7 @@
     const LayoutInputNode& child,
     const ConstraintSpace& child_space,
     const InflowChildData& child_data,
-    const NGLayoutResult& layout_result) const {
+    const LayoutResult& layout_result) const {
   DCHECK(layout_result.IsSelfCollapsing());
 
   // The child must be an in-flow zero-block-size fragment, use its end margin
@@ -2613,7 +2613,7 @@
 
 BreakStatus BlockLayoutAlgorithm::BreakBeforeChildIfNeeded(
     LayoutInputNode child,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     PreviousInflowPosition* previous_inflow_position,
     LayoutUnit bfc_block_offset,
     bool has_container_separation) {
@@ -2672,7 +2672,7 @@
   // columns, and without this exception for BR clear=all, we'd end up
   // stretching to fit the entire float(s) (that could otherwise be broken
   // nicely into fragments) in a single column.
-  if (child.IsInline() && layout_result.Status() == NGLayoutResult::kSuccess) {
+  if (child.IsInline() && layout_result.Status() == LayoutResult::kSuccess) {
     if (!first_overflowing_line_) {
       // We're at the first overflowing line. This is the space shortage that
       // we are going to report. We do this in spite of not yet knowing
@@ -2911,7 +2911,7 @@
     // have this flag, or gets this estimate wrong, it'll relayout with the
     // appropriate "forced" BFC block-offset.
     if (child.IsBlock()) {
-      if (const NGLayoutResult* cached_result =
+      if (const LayoutResult* cached_result =
               child.GetLayoutBox()->GetCachedLayoutResult(
                   To<BlockBreakToken>(child_break_token))) {
         const auto& prev_space = cached_result->GetConstraintSpaceForCaching();
@@ -3030,9 +3030,9 @@
     DCHECK(container_builder_.ItemsBuilder());
     const auto& items =
         container_builder_.ItemsBuilder()->GetLogicalLineItems(line_box);
-    const NGLayoutResult* result = items.BlockInInlineLayoutResult();
+    const LayoutResult* result = items.BlockInInlineLayoutResult();
     DCHECK(result);
-    PropagateBaselineFromBlockChild(result->PhysicalFragment(),
+    PropagateBaselineFromBlockChild(result->GetPhysicalFragment(),
                                     /* margins */ BoxStrut(), block_offset);
     return;
   }
@@ -3193,7 +3193,7 @@
 }
 
 bool BlockLayoutAlgorithm::PositionOrPropagateListMarker(
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     LogicalOffset* content_offset,
     PreviousInflowPosition* previous_inflow_position) {
   // If this is not a list-item, propagate unpositioned list markers to
@@ -3209,7 +3209,7 @@
   container_builder_.ClearUnpositionedListMarker();
 
   const ConstraintSpace& space = GetConstraintSpace();
-  const NGPhysicalFragment& content = layout_result.PhysicalFragment();
+  const auto& content = layout_result.GetPhysicalFragment();
   FontBaseline baseline_type = Style().GetFontBaseline();
   if (auto content_baseline =
           list_marker.ContentAlignmentBaseline(space, baseline_type, content)) {
@@ -3217,7 +3217,7 @@
     // now because authors cannot style list-markers currently. If we want to
     // support `::marker` pseudo, we need to create ConstraintSpace for marker
     // separately.
-    const NGLayoutResult* marker_layout_result =
+    const LayoutResult* marker_layout_result =
         list_marker.Layout(space, container_builder_.Style(), baseline_type);
     DCHECK(marker_layout_result);
     // If the BFC block-offset of li is still not resolved, resolved it now.
@@ -3255,7 +3255,7 @@
   const ConstraintSpace& space = GetConstraintSpace();
   FontBaseline baseline_type = Style().GetFontBaseline();
   // Layout the list marker.
-  const NGLayoutResult* marker_layout_result =
+  const LayoutResult* marker_layout_result =
       list_marker.Layout(space, container_builder_.Style(), baseline_type);
   DCHECK(marker_layout_result);
   // If the BFC block-offset of li is still not resolved, resolve it now.
@@ -3305,11 +3305,11 @@
     builder.SetInlineAutoBehavior(AutoSizeBehavior::kStretchImplicit);
   }
 
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       ruby_text_child.Layout(builder.ToConstraintSpace(), break_token);
 
-  const NGPhysicalBoxFragment& ruby_text_fragment =
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+  const auto& ruby_text_fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   const LogicalRect ruby_text_box = ruby_text_fragment.ConvertChildToLogical(
       ruby_text_fragment.ComputeRubyEmHeightBox());
 
@@ -3406,7 +3406,7 @@
       placeholder, /* child_break_token */ nullptr, child_data, available_size,
       is_new_fc);
 
-  const NGLayoutResult* result = placeholder.Layout(space);
+  const LayoutResult* result = placeholder.Layout(space);
   LogicalOffset offset = BorderScrollbarPadding().StartOffset();
   if (Node().IsTextArea()) {
     return FinishTextControlPlaceholder(result, offset, apply_fixed_size,
@@ -3420,7 +3420,7 @@
   }
   LogicalBoxFragment fragment(
       GetConstraintSpace().GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
   // We should apply FirstBaseline() of the placeholder fragment because the
   // placeholder might have the 'overflow' property, and its LastBaseline()
   // might be the block-end margin.
@@ -3451,7 +3451,7 @@
 }
 
 LayoutUnit BlockLayoutAlgorithm::FinishTextControlPlaceholder(
-    const NGLayoutResult* result,
+    const LayoutResult* result,
     const LogicalOffset& offset,
     bool apply_fixed_size,
     const PreviousInflowPosition& previous_inflow_position) {
@@ -3462,7 +3462,7 @@
   }
   LogicalBoxFragment fragment(
       GetConstraintSpace().GetWritingDirection(),
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment()));
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment()));
   return std::max(block_offset, offset.block_offset + fragment.BlockSize());
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index 0581407..d7477d5 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -70,26 +70,26 @@
   void SetBoxType(NGPhysicalFragment::NGBoxType type);
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
  private:
-  NOINLINE const NGLayoutResult* HandleNonsuccessfulLayoutResult(
-      const NGLayoutResult*);
+  NOINLINE const LayoutResult* HandleNonsuccessfulLayoutResult(
+      const LayoutResult*);
 
-  const NGLayoutResult* LayoutInlineChild(const InlineNode& child);
-  NOINLINE const NGLayoutResult* LayoutWithSimpleInlineChildLayoutContext(
+  const LayoutResult* LayoutInlineChild(const InlineNode& child);
+  NOINLINE const LayoutResult* LayoutWithSimpleInlineChildLayoutContext(
       const InlineNode& child);
   template <wtf_size_t capacity>
-  NOINLINE const NGLayoutResult* LayoutWithOptimalInlineChildLayoutContext(
+  NOINLINE const LayoutResult* LayoutWithOptimalInlineChildLayoutContext(
       const InlineNode& child);
 
-  NOINLINE const NGLayoutResult* RelayoutIgnoringLineClamp();
+  NOINLINE const LayoutResult* RelayoutIgnoringLineClamp();
 
-  inline const NGLayoutResult* Layout(
+  inline const LayoutResult* Layout(
       InlineChildLayoutContext* inline_child_layout_context);
 
-  const NGLayoutResult* FinishLayout(PreviousInflowPosition*,
-                                     InlineChildLayoutContext*);
+  const LayoutResult* FinishLayout(PreviousInflowPosition*,
+                                   InlineChildLayoutContext*);
 
   // Return the BFC block offset of this block.
   LayoutUnit BfcBlockOffset() const {
@@ -136,7 +136,7 @@
       const InflowChildData&,
       const absl::optional<LayoutUnit>& child_bfc_block_offset,
       const LogicalOffset&,
-      const NGLayoutResult&,
+      const LayoutResult&,
       const LogicalFragment&,
       bool self_collapsing_child_had_clearance);
 
@@ -151,7 +151,7 @@
       const LayoutInputNode& child,
       const ConstraintSpace& child_space,
       const InflowChildData& child_data,
-      const NGLayoutResult&) const;
+      const LayoutResult&) const;
 
   void AlignContent(LayoutUnit content_block_size);
 
@@ -186,14 +186,14 @@
   //
   // Returns false if we need to abort layout, because a previously unknown BFC
   // block offset has now been resolved.
-  NGLayoutResult::EStatus HandleNewFormattingContext(
+  LayoutResult::EStatus HandleNewFormattingContext(
       LayoutInputNode child,
       const BlockBreakToken* child_break_token,
       PreviousInflowPosition*);
 
   // Performs the actual layout of a new formatting context. This may be called
   // multiple times from HandleNewFormattingContext.
-  const NGLayoutResult* LayoutNewFormattingContext(
+  const LayoutResult* LayoutNewFormattingContext(
       LayoutInputNode child,
       const BlockBreakToken* child_break_token,
       const InflowChildData&,
@@ -205,19 +205,19 @@
   // Handle an in-flow child.
   // Returns false if we need to abort layout, because a previously unknown BFC
   // block offset has now been resolved. (Same as HandleNewFormattingContext).
-  NGLayoutResult::EStatus HandleInflow(
+  LayoutResult::EStatus HandleInflow(
       LayoutInputNode child,
       const BreakToken* child_break_token,
       PreviousInflowPosition*,
       InlineChildLayoutContext*,
       const InlineBreakToken** previous_inline_break_token);
 
-  NGLayoutResult::EStatus FinishInflow(
+  LayoutResult::EStatus FinishInflow(
       LayoutInputNode child,
       const BreakToken* child_break_token,
       const ConstraintSpace&,
       bool has_clearance_past_adjoining_floats,
-      const NGLayoutResult*,
+      const LayoutResult*,
       InflowChildData*,
       PreviousInflowPosition*,
       InlineChildLayoutContext*,
@@ -243,7 +243,7 @@
   // Insert a fragmentainer break before the child if necessary.
   // See |::blink::BreakBeforeChildIfNeeded()| for more documentation.
   BreakStatus BreakBeforeChildIfNeeded(LayoutInputNode child,
-                                       const NGLayoutResult&,
+                                       const LayoutResult&,
                                        PreviousInflowPosition*,
                                        LayoutUnit bfc_block_offset,
                                        bool has_container_separation);
@@ -316,7 +316,7 @@
 
   // Positions a list marker for the specified block content.
   // Return false if it aborts when resolving BFC block offset for LI.
-  bool PositionOrPropagateListMarker(const NGLayoutResult&,
+  bool PositionOrPropagateListMarker(const LayoutResult&,
                                      LogicalOffset*,
                                      PreviousInflowPosition*);
 
@@ -379,7 +379,7 @@
   // This function returns a new value for `PreviousInflowPosition::
   // logical_block_offset`.
   LayoutUnit FinishTextControlPlaceholder(
-      const NGLayoutResult* result,
+      const LayoutResult* result,
       const LogicalOffset& offset,
       bool apply_fixed_size,
       const PreviousInflowPosition& previous_inflow_position);
@@ -393,7 +393,7 @@
   LogicalSize child_percentage_size_;
   LogicalSize replaced_child_percentage_size_;
 
-  const NGLayoutResult* previous_result_ = nullptr;
+  const LayoutResult* previous_result_ = nullptr;
 
   const ColumnSpannerPath* column_spanner_path_ = nullptr;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
index 48e70f1..2253039a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -39,7 +39,7 @@
                           ->item(0)
                           ->GetLayoutObject());
     return To<NGPhysicalBoxFragment>(
-        &layout_box->GetSingleCachedLayoutResult()->PhysicalFragment());
+        &layout_box->GetSingleCachedLayoutResult()->GetPhysicalFragment());
   }
 
   MinMaxSizes RunComputeMinMaxSizes(BlockNode node) {
@@ -55,9 +55,9 @@
     return algorithm.ComputeMinMaxSizes(MinMaxSizesFloatInput()).sizes;
   }
 
-  const NGLayoutResult* RunCachedLayoutResult(const ConstraintSpace& space,
-                                              const BlockNode& node) {
-    NGLayoutCacheStatus cache_status;
+  const LayoutResult* RunCachedLayoutResult(const ConstraintSpace& space,
+                                            const BlockNode& node) {
+    LayoutCacheStatus cache_status;
     absl::optional<FragmentGeometry> initial_fragment_geometry;
     return To<LayoutBlockFlow>(node.GetLayoutBox())
         ->CachedLayoutResult(space, nullptr, nullptr, nullptr,
@@ -117,8 +117,8 @@
   auto* block_flow = To<LayoutBlockFlow>(GetLayoutObjectByElementId("box"));
   BlockNode node(block_flow);
 
-  const NGLayoutResult* result = node.Layout(space, nullptr);
-  EXPECT_EQ(PhysicalSize(30, 40), result->PhysicalFragment().Size());
+  const LayoutResult* result = node.Layout(space, nullptr);
+  EXPECT_EQ(PhysicalSize(30, 40), result->GetPhysicalFragment().Size());
 
   // Test pointer-equal constraint space.
   result = RunCachedLayoutResult(space, node);
@@ -164,8 +164,8 @@
   auto* block_flow = To<LayoutBlockFlow>(GetLayoutObjectByElementId("box"));
   BlockNode node(block_flow);
 
-  const NGLayoutResult* result = node.Layout(space, nullptr);
-  EXPECT_EQ(PhysicalSize(30, 40), result->PhysicalFragment().Size());
+  const LayoutResult* result = node.Layout(space, nullptr);
+  EXPECT_EQ(PhysicalSize(30, 40), result->GetPhysicalFragment().Size());
 
   // Test pointer-equal constraint space.
   result = RunCachedLayoutResult(space, node);
@@ -245,13 +245,13 @@
   ConstraintSpace space200 =
       create_space(LogicalSize(LayoutUnit(100), LayoutUnit(200)));
 
-  auto run_test = [&](auto id) -> const NGLayoutResult* {
+  auto run_test = [&](auto id) -> const LayoutResult* {
     // Grab the box under test.
     auto* box = To<LayoutBlockFlow>(GetLayoutObjectByElementId(id));
     BlockNode node(box);
 
     // Check that we have a cache hit with space100.
-    const NGLayoutResult* result = RunCachedLayoutResult(space100, node);
+    const LayoutResult* result = RunCachedLayoutResult(space100, node);
     EXPECT_NE(result, nullptr);
 
     // Return the result of the cache with space200.
@@ -310,7 +310,7 @@
       create_space(LogicalSize(LayoutUnit(300), LayoutUnit(100)),
                    BfcOffset(LayoutUnit(50), LayoutUnit()));
 
-  const NGLayoutResult* result = nullptr;
+  const LayoutResult* result = nullptr;
   auto* box1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("box1"));
 
   // Ensure we get a cached layout result, even if our BFC line-offset changed.
@@ -1033,7 +1033,7 @@
   const auto* fragment =
       &To<NGPhysicalBoxFragment>(GetLayoutBoxByElementId("container")
                                      ->GetSingleCachedLayoutResult()
-                                     ->PhysicalFragment());
+                                     ->GetPhysicalFragment());
 
   String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
   offset:unplaced size:200x60
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index e24e831..0658d7c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -201,9 +201,9 @@
   }
 }
 
-inline const NGLayoutResult* LayoutWithAlgorithm(
+inline const LayoutResult* LayoutWithAlgorithm(
     const LayoutAlgorithmParams& params) {
-  const NGLayoutResult* result = nullptr;
+  const LayoutResult* result = nullptr;
   DetermineAlgorithmAndRun(params,
                            [&result](LayoutAlgorithmOperations* algorithm) {
                              result = algorithm->Layout();
@@ -315,7 +315,7 @@
 
 }  // namespace
 
-const NGLayoutResult* BlockNode::Layout(
+const LayoutResult* BlockNode::Layout(
     const ConstraintSpace& constraint_space,
     const BlockBreakToken* break_token,
     const EarlyBreak* early_break,
@@ -325,13 +325,13 @@
   // internal shared vector.
   // In order for the caching logic to work correctly we need to set the
   // pointer to the value previous shared vector.
-  if (const NGLayoutResult* previous_result =
+  if (const LayoutResult* previous_result =
           box_->GetCachedLayoutResult(break_token)) {
     constraint_space.GetExclusionSpace().PreInitialize(
         previous_result->GetConstraintSpaceForCaching().GetExclusionSpace());
   }
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   // We may be able to hit the cache without calculating fragment geometry
   // (calculating that isn't necessarily very cheap). So, start off without it.
@@ -343,12 +343,12 @@
   if (needed_layout)
     box_->GetFrameView()->IncBlockLayoutCount();
 
-  const NGLayoutResult* layout_result = box_->CachedLayoutResult(
+  const LayoutResult* layout_result = box_->CachedLayoutResult(
       constraint_space, break_token, early_break, column_spanner_path,
       &fragment_geometry, &cache_status);
 
-  if ((cache_status == NGLayoutCacheStatus::kHit ||
-       cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout) &&
+  if ((cache_status == LayoutCacheStatus::kHit ||
+       cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout) &&
       needed_layout &&
       constraint_space.CacheSlot() == LayoutResultCacheSlot::kLayout &&
       box_->HasBrokenSpine() && !ChildLayoutBlockedByDisplayLock()) {
@@ -357,10 +357,9 @@
     // clone the result to pick the most recent fragments from the LayoutBox
     // children, because we stopped rebuilding the fragment spine right here
     // after performing subtree layout.
-    layout_result =
-        NGLayoutResult::CloneWithPostLayoutFragments(*layout_result);
+    layout_result = LayoutResult::CloneWithPostLayoutFragments(*layout_result);
     const auto& new_fragment =
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
     // If we have fragment items, and we're not done (more fragments to follow),
     // be sure to miss the cache for any subsequent fragments, lest finalization
     // be missed (which could cause trouble for InlineCursor when walking the
@@ -371,13 +370,13 @@
     box_->ClearHasBrokenSpine();
   }
 
-  if (cache_status == NGLayoutCacheStatus::kHit) {
+  if (cache_status == LayoutCacheStatus::kHit) {
     DCHECK(layout_result);
 
     // We may have to update the margins on box_; we reuse the layout result
     // even if a percentage margin may have changed.
     UpdateMarginPaddingInfoIfNeeded(constraint_space,
-                                    layout_result->PhysicalFragment());
+                                    layout_result->GetPhysicalFragment());
 
     UpdateShapeOutsideInfoIfNeeded(*layout_result, constraint_space);
 
@@ -427,11 +426,11 @@
 
   // Try to perform "simplified" layout, unless it's a fragmentation context
   // root (the simplified layout algorithm doesn't support fragmentainers).
-  if (cache_status == NGLayoutCacheStatus::kNeedsSimplifiedLayout &&
+  if (cache_status == LayoutCacheStatus::kNeedsSimplifiedLayout &&
       (!block_flow || !block_flow->IsFragmentationContextRoot())) {
     DCHECK(layout_result);
 #if DCHECK_IS_ON()
-    const NGLayoutResult* previous_result = layout_result;
+    const LayoutResult* previous_result = layout_result;
 #endif
 
     // A child may have changed size while performing "simplified" layout (it
@@ -446,7 +445,7 @@
           *previous_result, /* check_same_block_size */ !block_flow);
     }
 #endif
-  } else if (cache_status == NGLayoutCacheStatus::kCanReuseLines) {
+  } else if (cache_status == LayoutCacheStatus::kCanReuseLines) {
     params.previous_result = layout_result;
     layout_result = nullptr;
   } else {
@@ -471,8 +470,8 @@
   PaintLayerScrollableArea::DelayScrollOffsetClampScope delay_clamp_scope;
 
   absl::optional<PhysicalSize> optional_old_box_size;
-  if (layout_result->Status() == NGLayoutResult::kSuccess &&
-      !layout_result->PhysicalFragment().GetBreakToken()) {
+  if (layout_result->Status() == LayoutResult::kSuccess &&
+      !layout_result->GetPhysicalFragment().GetBreakToken()) {
     optional_old_box_size = box_->Size();
   }
 
@@ -498,7 +497,8 @@
   BoxStrut scrollbars_after = ComputeScrollbars(constraint_space, *this);
   if ((scrollbars_before != scrollbars_after ||
        inline_size_before != fragment_geometry->border_box_size.inline_size) &&
-      !NGDisableSideEffectsScope::IsDisabled() && !IsBreakInside(break_token)) {
+      !DisableLayoutSideEffectsScope::IsDisabled() &&
+      !IsBreakInside(break_token)) {
     bool freeze_horizontal = false, freeze_vertical = false;
     // If we're in a measure pass, freeze both scrollbars right away, to avoid
     // quadratic time complexity for deeply nested flexboxes.
@@ -565,21 +565,22 @@
   // shape-outside area.
   //
   // TODO(ikilpatrick): This should be fixed by moving the shape-outside data
-  // to the NGLayoutResult, removing this "side" data-structure.
+  // to the LayoutResult, removing this "side" data-structure.
   UpdateShapeOutsideInfoIfNeeded(*layout_result, constraint_space);
 
   return layout_result;
 }
 
-const NGLayoutResult* BlockNode::SimplifiedLayout(
+const LayoutResult* BlockNode::SimplifiedLayout(
     const NGPhysicalFragment& previous_fragment) const {
-  const NGLayoutResult* previous_result = box_->GetSingleCachedLayoutResult();
+  const LayoutResult* previous_result = box_->GetSingleCachedLayoutResult();
   DCHECK(previous_result);
 
   // We might be be trying to perform simplfied layout on a fragment in the
   // "measure" cache slot, abort if this is the case.
-  if (&previous_result->PhysicalFragment() != &previous_fragment)
+  if (&previous_result->GetPhysicalFragment() != &previous_fragment) {
     return nullptr;
+  }
 
   if (!box_->NeedsLayout())
     return previous_result;
@@ -589,18 +590,18 @@
 
   // Perform layout on ourselves using the previous constraint space.
   const ConstraintSpace space(previous_result->GetConstraintSpaceForCaching());
-  const NGLayoutResult* result = Layout(space, /* break_token */ nullptr);
+  const LayoutResult* result = Layout(space, /* break_token */ nullptr);
 
-  if (result->Status() != NGLayoutResult::kSuccess) {
+  if (result->Status() != LayoutResult::kSuccess) {
     // TODO(crbug.com/1297864): The optimistic BFC block-offsets aren't being
     // set correctly for block-in-inline causing these layouts to fail.
     return nullptr;
   }
 
   const auto& old_fragment =
-      To<NGPhysicalBoxFragment>(previous_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(previous_result->GetPhysicalFragment());
   const auto& new_fragment =
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
 
   // Simplified layout has the ability to add/remove scrollbars, this can cause
   // a couple (rare) edge-cases which will make the fragment different enough
@@ -623,13 +624,13 @@
   return result;
 }
 
-const NGLayoutResult* BlockNode::LayoutRepeatableRoot(
+const LayoutResult* BlockNode::LayoutRepeatableRoot(
     const ConstraintSpace& constraint_space,
     const BlockBreakToken* break_token) const {
   // We read and write the physical fragments vector in LayoutBox here, which
   // isn't allowed if side-effects are disabled. Call-sites must make sure that
   // we don't attempt to repeat content if side-effects are disabled.
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
 
   // When laying out repeatable content, we cannot at the same time allow it to
   // break inside.
@@ -639,20 +640,21 @@
   DCHECK(!IsBreakInside(break_token));
 
   bool is_first = !break_token || !break_token->IsRepeated();
-  const NGLayoutResult* result;
+  const LayoutResult* result;
   if (is_first) {
     // We're generating the first fragment for repeated content. Perform regular
     // layout.
     result = Layout(constraint_space, break_token);
-    DCHECK(!result->PhysicalFragment().GetBreakToken());
+    DCHECK(!result->GetPhysicalFragment().GetBreakToken());
   } else {
     // We're repeating. Create a shallow clone of the first result. Once we're
     // at the last fragment, we'll actually create a deep clone.
-    result = NGLayoutResult::Clone(*box_->GetLayoutResult(0));
+    result = LayoutResult::Clone(*box_->GetLayoutResult(0));
   }
 
   wtf_size_t index = FragmentIndex(break_token);
-  const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+  const auto& fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   // We need to create a special "repeat" break token, which will be the
   // incoming break token when generating the next fragment. This is needed in
   // order to get the sequence numbers right, which is important when adding the
@@ -679,7 +681,7 @@
 }
 
 void BlockNode::FinishRepeatableRoot() const {
-  DCHECK(!NGDisableSideEffectsScope::IsDisabled());
+  DCHECK(!DisableLayoutSideEffectsScope::IsDisabled());
 
   // This is the last fragment. It won't be repeated again. We have already
   // created fragments for the repeated nodes, but the cloning was shallow.
@@ -703,12 +705,12 @@
         *box_->GetPhysicalFragment(i);
     bool is_first = i == 1;
     bool is_last = i + 1 == fragment_count;
-    NGFragmentRepeater repeater(is_first, is_last);
+    FragmentRepeater repeater(is_first, is_last);
     repeater.CloneChildFragments(physical_fragment);
   }
 }
 
-const NGLayoutResult* BlockNode::CachedLayoutResultForOutOfFlowPositioned(
+const LayoutResult* BlockNode::CachedLayoutResultForOutOfFlowPositioned(
     LogicalSize container_content_size) const {
   DCHECK(IsOutOfFlowPositioned());
 
@@ -720,7 +722,7 @@
   if (box_->PhysicalFragmentCount() > 1)
     return nullptr;
 
-  const NGLayoutResult* cached_layout_result =
+  const LayoutResult* cached_layout_result =
       box_->GetSingleCachedLayoutResult();
   if (!cached_layout_result)
     return nullptr;
@@ -744,7 +746,7 @@
   // we know it doesn't depend on the static-position.
   //
   // TODO(layout-dev): We might be able to determine what the previous
-  // static-position was based on |NGLayoutResult::OutOfFlowPositionedOffset|.
+  // static-position was based on |LayoutResult::OutOfFlowPositionedOffset|.
   bool depends_on_static_position =
       (Style().UsedLeft().IsAuto() && Style().UsedRight().IsAuto()) ||
       (Style().UsedTop().IsAuto() && Style().UsedBottom().IsAuto());
@@ -773,14 +775,15 @@
     LayoutBlockFlow* block_flow,
     const ConstraintSpace& constraint_space,
     const BlockBreakToken* break_token,
-    const NGLayoutResult* layout_result,
+    const LayoutResult* layout_result,
     const absl::optional<PhysicalSize>& old_box_size) const {
   // Computing MinMax after layout. Do not modify the |LayoutObject| tree, paint
   // properties, and other global states.
-  if (NGDisableSideEffectsScope::IsDisabled())
+  if (DisableLayoutSideEffectsScope::IsDisabled()) {
     return;
+  }
 
-  if (layout_result->Status() != NGLayoutResult::kSuccess) {
+  if (layout_result->Status() != LayoutResult::kSuccess) {
     // Layout aborted, but there may be results from a previous layout lying
     // around. They are fine to keep, but since we aborted, it means that we
     // want to attempt layout again. Be sure to miss the cache.
@@ -789,7 +792,7 @@
   }
 
   const auto& physical_fragment =
-      To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
 
   if (auto* replaced = DynamicTo<LayoutReplaced>(*box_)) {
     // NG replaced elements are painted with legacy painters. We need to force
@@ -852,7 +855,7 @@
     DCHECK(!physical_fragment.HasItems());
   }
 
-  if (!layout_result->PhysicalFragment().GetBreakToken()) {
+  if (!layout_result->GetPhysicalFragment().GetBreakToken()) {
     DCHECK(old_box_size);
     if (box_->Size() != *old_box_size) {
       box_->SizeChanged();
@@ -861,10 +864,11 @@
   CopyFragmentDataToLayoutBox(constraint_space, *layout_result, break_token);
 }
 
-void BlockNode::StoreResultInLayoutBox(const NGLayoutResult* result,
+void BlockNode::StoreResultInLayoutBox(const LayoutResult* result,
                                        const BlockBreakToken* break_token,
                                        bool clear_trailing_results) const {
-  const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+  const auto& fragment =
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   wtf_size_t fragment_idx = 0;
 
   if (fragment.IsOnlyForNode()) {
@@ -928,14 +932,14 @@
     // If we're computing MinMax after layout, we need to disable side effects
     // so that |Layout| does not update the |LayoutObject| tree and other global
     // states.
-    absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+    absl::optional<DisableLayoutSideEffectsScope> disable_side_effects;
     if (!GetLayoutBox()->NeedsLayout())
       disable_side_effects.emplace();
 
-    const NGLayoutResult* layout_result = Layout(constraint_space);
-    DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+    const LayoutResult* layout_result = Layout(constraint_space);
+    DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
     sizes = LogicalFragment({container_writing_mode, TextDirection::kLtr},
-                            layout_result->PhysicalFragment())
+                            layout_result->GetPhysicalFragment())
                 .InlineSize();
     const bool depends_on_block_constraints =
         Style().LogicalWidth().IsAuto() ||
@@ -1142,10 +1146,10 @@
 
 void BlockNode::CopyFragmentDataToLayoutBox(
     const ConstraintSpace& constraint_space,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     const BlockBreakToken* previous_break_token) const {
   const auto& physical_fragment =
-      To<NGPhysicalBoxFragment>(layout_result.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(layout_result.GetPhysicalFragment());
   bool is_last_fragment = !physical_fragment.GetBreakToken();
 
   // TODO(mstensho): This should always be done by the parent algorithm, since
@@ -1538,7 +1542,7 @@
   return To<MathMLRadicalElement>(GetDOMNode())->HasIndex();
 }
 
-const NGLayoutResult* BlockNode::LayoutAtomicInline(
+const LayoutResult* BlockNode::LayoutAtomicInline(
     const ConstraintSpace& parent_constraint_space,
     const ComputedStyle& parent_style,
     bool use_first_line_style,
@@ -1559,8 +1563,8 @@
   builder.SetReplacedPercentageResolutionSize(
       parent_constraint_space.ReplacedPercentageResolutionSize());
   ConstraintSpace constraint_space = builder.ToConstraintSpace();
-  const NGLayoutResult* result = Layout(constraint_space);
-  if (!NGDisableSideEffectsScope::IsDisabled()) {
+  const LayoutResult* result = Layout(constraint_space);
+  if (!DisableLayoutSideEffectsScope::IsDisabled()) {
     // TODO(kojii): Investigate why ClearNeedsLayout() isn't called
     // automatically when it's being laid out.
     GetLayoutBox()->ClearNeedsLayout();
@@ -1568,12 +1572,12 @@
   return result;
 }
 
-const NGLayoutResult* BlockNode::RunSimplifiedLayout(
+const LayoutResult* BlockNode::RunSimplifiedLayout(
     const LayoutAlgorithmParams& params,
-    const NGLayoutResult& previous_result) const {
+    const LayoutResult& previous_result) const {
   SimplifiedLayoutAlgorithm algorithm(params, previous_result);
   if (const auto* previous_box_fragment = DynamicTo<NGPhysicalBoxFragment>(
-          &previous_result.PhysicalFragment())) {
+          &previous_result.GetPhysicalFragment())) {
     if (previous_box_fragment->HasItems())
       return algorithm.LayoutWithItemsBuilder();
   }
@@ -1614,19 +1618,20 @@
 // current shape machinery requires setting the size of the float after layout
 // in the parents writing mode.
 void BlockNode::UpdateShapeOutsideInfoIfNeeded(
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     const ConstraintSpace& constraint_space) const {
   if (!box_->IsFloating() || !box_->GetShapeOutsideInfo())
     return;
 
-  if (layout_result.Status() != NGLayoutResult::kSuccess)
+  if (layout_result.Status() != LayoutResult::kSuccess) {
     return;
+  }
 
   // The box_ may not have a valid size yet (due to an intermediate layout),
   // use the fragment's size instead.
-  PhysicalSize box_size = layout_result.PhysicalFragment().Size();
+  PhysicalSize box_size = layout_result.GetPhysicalFragment().Size();
 
-  // TODO(ikilpatrick): Ideally this should be moved to a NGLayoutResult
+  // TODO(ikilpatrick): Ideally this should be moved to a LayoutResult
   // computing the shape area. There may be an issue with the new fragmentation
   // model and computing the correct sizes of shapes.
   ShapeOutsideInfo* shape_outside = box_->GetShapeOutsideInfo();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
index 880a091..f128e68 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -21,7 +21,7 @@
 class FragmentItems;
 class InlineNode;
 class LayoutBox;
-class NGLayoutResult;
+class LayoutResult;
 class NGPhysicalBoxFragment;
 class NGPhysicalFragment;
 enum class BaselineAlgorithmType;
@@ -37,17 +37,17 @@
 
   BlockNode(std::nullptr_t) : LayoutInputNode(nullptr) {}
 
-  const NGLayoutResult* Layout(const ConstraintSpace& constraint_space,
-                               const BlockBreakToken* break_token = nullptr,
-                               const EarlyBreak* = nullptr,
-                               const ColumnSpannerPath* = nullptr) const;
+  const LayoutResult* Layout(const ConstraintSpace& constraint_space,
+                             const BlockBreakToken* break_token = nullptr,
+                             const EarlyBreak* = nullptr,
+                             const ColumnSpannerPath* = nullptr) const;
 
   // This method is just for use within the |SimplifiedLayoutAlgorithm|.
   //
   // If layout is dirty, it will perform layout using the previous constraint
-  // space used to generate the |NGLayoutResult|.
+  // space used to generate the |LayoutResult|.
   // Otherwise it will simply return the previous layout result generated.
-  const NGLayoutResult* SimplifiedLayout(
+  const LayoutResult* SimplifiedLayout(
       const NGPhysicalFragment& previous_fragment) const;
 
   // Lay out a repeatable node during block fragmentation (fixed positioned
@@ -75,8 +75,8 @@
   // (mainly), we need to clone the fragment as many times as it repeats, and we
   // also need to make sure that the break tokens are reasonably intact -
   // including the sequence numbers. This is why we need this.
-  const NGLayoutResult* LayoutRepeatableRoot(const ConstraintSpace&,
-                                             const BlockBreakToken*) const;
+  const LayoutResult* LayoutRepeatableRoot(const ConstraintSpace&,
+                                           const BlockBreakToken*) const;
 
   // Finalize the cloned layout results of a repeatable root. This will
   // deep-clone and set the correct break token sequence numbers, and make sure
@@ -97,7 +97,7 @@
   //
   // If the containing-block size hasn't changed, and we are layout-clean we
   // can reuse the previous layout result.
-  const NGLayoutResult* CachedLayoutResultForOutOfFlowPositioned(
+  const LayoutResult* CachedLayoutResultForOutOfFlowPositioned(
       LogicalSize container_content_size) const;
 
   LayoutInputNode NextSibling() const;
@@ -199,7 +199,7 @@
   bool HasIndex() const;
 
   // Layout an atomic inline; e.g., inline block.
-  const NGLayoutResult* LayoutAtomicInline(
+  const LayoutResult* LayoutAtomicInline(
       const ConstraintSpace& parent_constraint_space,
       const ComputedStyle& parent_style,
       bool use_first_line_style,
@@ -249,19 +249,19 @@
  private:
   void PrepareForLayout() const;
 
-  const NGLayoutResult* RunSimplifiedLayout(const LayoutAlgorithmParams&,
-                                            const NGLayoutResult&) const;
+  const LayoutResult* RunSimplifiedLayout(const LayoutAlgorithmParams&,
+                                          const LayoutResult&) const;
 
   // If this node is a LayoutNGMixin, the caller must pass the layout object for
   // this node cast to a LayoutBlockFlow as the first argument.
   void FinishLayout(LayoutBlockFlow*,
                     const ConstraintSpace&,
                     const BlockBreakToken*,
-                    const NGLayoutResult*,
+                    const LayoutResult*,
                     const absl::optional<PhysicalSize>& old_box_size) const;
 
   // Update the layout results vector in LayoutBox with the new result.
-  void StoreResultInLayoutBox(const NGLayoutResult*,
+  void StoreResultInLayoutBox(const LayoutResult*,
                               const BlockBreakToken*,
                               bool clear_trailing_results = false) const;
 
@@ -269,7 +269,7 @@
   // data to the layout box.
   void CopyFragmentDataToLayoutBox(
       const ConstraintSpace&,
-      const NGLayoutResult&,
+      const LayoutResult&,
       const BlockBreakToken* previous_break_token) const;
   void CopyFragmentItemsToLayoutBox(
       const NGPhysicalBoxFragment& container,
@@ -289,7 +289,7 @@
       const NGPhysicalFragment& fragment) const;
 
   void UpdateShapeOutsideInfoIfNeeded(
-      const NGLayoutResult&,
+      const LayoutResult&,
       const ConstraintSpace& constraint_space) const;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
index 3de0c54..3551310c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.cc
@@ -22,12 +22,12 @@
   absl::optional<LayoutUnit> baseline;
   switch (physical_fragment_.Style().BaselineSource()) {
     case EBaselineSource::kAuto:
-      baseline = PhysicalBoxFragment().UseLastBaselineForInlineBaseline()
+      baseline = GetPhysicalBoxFragment().UseLastBaselineForInlineBaseline()
                      ? LastBaseline()
                      : FirstBaseline();
 
       // Some blocks force the baseline to be the block-end margin edge.
-      if (PhysicalBoxFragment().UseBlockEndMarginEdgeForInlineBaseline()) {
+      if (GetPhysicalBoxFragment().UseBlockEndMarginEdgeForInlineBaseline()) {
         baseline = BlockSize() + (writing_direction_.IsFlippedLines()
                                       ? margins.line_over
                                       : margins.line_under);
@@ -68,7 +68,7 @@
 LayoutUnit LogicalBoxFragment::BlockEndScrollableOverflow() const {
   WritingModeConverter converter(writing_direction_, physical_fragment_.Size());
   LogicalRect overflow =
-      converter.ToLogical(PhysicalBoxFragment().ScrollableOverflow());
+      converter.ToLogical(GetPhysicalBoxFragment().ScrollableOverflow());
   return overflow.BlockEndOffset();
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
index 48a0952d..345fb99 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -20,7 +20,7 @@
                      const NGPhysicalBoxFragment& physical_fragment)
       : LogicalFragment(writing_direction, physical_fragment) {}
 
-  const NGPhysicalBoxFragment& PhysicalBoxFragment() const {
+  const NGPhysicalBoxFragment& GetPhysicalBoxFragment() const {
     return To<NGPhysicalBoxFragment>(physical_fragment_);
   }
 
@@ -42,7 +42,7 @@
     if (!IsWritingModeEqual())
       return absl::nullopt;
 
-    auto baseline = PhysicalBoxFragment().FirstBaseline();
+    auto baseline = GetPhysicalBoxFragment().FirstBaseline();
     if (baseline && physical_fragment_.IsScrollContainer())
       baseline = std::max(LayoutUnit(), std::min(*baseline, BlockSize()));
 
@@ -61,7 +61,7 @@
     if (!IsWritingModeEqual())
       return absl::nullopt;
 
-    auto baseline = PhysicalBoxFragment().LastBaseline();
+    auto baseline = GetPhysicalBoxFragment().LastBaseline();
     if (baseline && physical_fragment_.IsScrollContainer())
       baseline = std::max(LayoutUnit(), std::min(*baseline, BlockSize()));
 
@@ -83,14 +83,16 @@
   FontHeight BaselineMetrics(const LineBoxStrut& margins, FontBaseline) const;
 
   BoxStrut Borders() const {
-    return PhysicalBoxFragment().Borders().ConvertToLogical(writing_direction_);
+    return GetPhysicalBoxFragment().Borders().ConvertToLogical(
+        writing_direction_);
   }
   BoxStrut Padding() const {
-    return PhysicalBoxFragment().Padding().ConvertToLogical(writing_direction_);
+    return GetPhysicalBoxFragment().Padding().ConvertToLogical(
+        writing_direction_);
   }
 
   bool HasDescendantsForTablePart() const {
-    return PhysicalBoxFragment().HasDescendantsForTablePart();
+    return GetPhysicalBoxFragment().HasDescendantsForTablePart();
   }
 
   LayoutUnit BlockEndScrollableOverflow() const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
index 3c0d0df..d55884f8 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -23,12 +23,12 @@
 
 namespace blink {
 
-const NGLayoutResult& BoxFragmentBuilder::LayoutResultForPropagation(
-    const NGLayoutResult& layout_result) const {
-  if (layout_result.Status() != NGLayoutResult::kSuccess) {
+const LayoutResult& BoxFragmentBuilder::LayoutResultForPropagation(
+    const LayoutResult& layout_result) const {
+  if (layout_result.Status() != LayoutResult::kSuccess) {
     return layout_result;
   }
-  const auto& fragment = layout_result.PhysicalFragment();
+  const auto& fragment = layout_result.GetPhysicalFragment();
   if (fragment.IsBox()) {
     return layout_result;
   }
@@ -101,19 +101,19 @@
 }
 
 void BoxFragmentBuilder::AddResult(
-    const NGLayoutResult& child_layout_result,
+    const LayoutResult& child_layout_result,
     const LogicalOffset offset,
     absl::optional<const BoxStrut> margins,
     absl::optional<LogicalOffset> relative_offset,
     const OofInlineContainer<LogicalOffset>* inline_container) {
-  const auto& fragment = child_layout_result.PhysicalFragment();
+  const auto& fragment = child_layout_result.GetPhysicalFragment();
 
   // We'll normally propagate info from child_layout_result here, but if that's
   // a line box with a block inside, we'll use the result for that block
   // instead. The fact that we create a line box at all in such cases is just an
   // implementation detail -- anything of interest is stored on the child block
   // fragment.
-  const NGLayoutResult* result_for_propagation = &child_layout_result;
+  const LayoutResult* result_for_propagation = &child_layout_result;
 
   if (!fragment.IsBox() && items_builder_) {
     if (const auto* line = DynamicTo<PhysicalLineBoxFragment>(&fragment)) {
@@ -155,7 +155,7 @@
   PropagateFromLayoutResult(*result_for_propagation);
 }
 
-void BoxFragmentBuilder::AddResult(const NGLayoutResult& child_layout_result,
+void BoxFragmentBuilder::AddResult(const LayoutResult& child_layout_result,
                                    const LogicalOffset offset) {
   AddResult(child_layout_result, offset, absl::nullopt, absl::nullopt, nullptr);
 }
@@ -349,7 +349,7 @@
 }
 
 void BoxFragmentBuilder::PropagateBreakInfo(
-    const NGLayoutResult& child_layout_result,
+    const LayoutResult& child_layout_result,
     LogicalOffset offset) {
   DCHECK(has_block_fragmentation_);
 
@@ -367,8 +367,7 @@
       is_block_size_for_fragmentation_clamped_ = true;
   }
 
-  const NGPhysicalFragment& child_fragment =
-      child_layout_result.PhysicalFragment();
+  const auto& child_fragment = child_layout_result.GetPhysicalFragment();
   const auto* child_box_fragment =
       DynamicTo<NGPhysicalBoxFragment>(child_fragment);
   const BlockBreakToken* token =
@@ -449,7 +448,7 @@
     if (const auto* child_spanner_path =
             child_layout_result.GetColumnSpannerPath()) {
       DCHECK(HasInflowChildBreakInside() ||
-             !child_layout_result.PhysicalFragment().IsBox());
+             !child_layout_result.GetPhysicalFragment().IsBox());
       const auto* spanner_path =
           MakeGarbageCollected<ColumnSpannerPath>(Node(), child_spanner_path);
       SetColumnSpannerPath(spanner_path);
@@ -467,11 +466,12 @@
 }
 
 void BoxFragmentBuilder::PropagateChildBreakValues(
-    const NGLayoutResult& child_layout_result) {
-  if (child_layout_result.Status() != NGLayoutResult::kSuccess)
+    const LayoutResult& child_layout_result) {
+  if (child_layout_result.Status() != LayoutResult::kSuccess) {
     return;
+  }
 
-  const auto& fragment = child_layout_result.PhysicalFragment();
+  const auto& fragment = child_layout_result.GetPhysicalFragment();
   if (fragment.IsInline() || !fragment.IsCSSBox() ||
       fragment.IsFloatingOrOutOfFlowPositioned())
     return;
@@ -503,7 +503,7 @@
   }
 }
 
-const NGLayoutResult* BoxFragmentBuilder::ToBoxFragment(
+const LayoutResult* BoxFragmentBuilder::ToBoxFragment(
     WritingMode block_or_line_writing_mode) {
 #if DCHECK_IS_ON()
   if (ItemsBuilder()) {
@@ -572,8 +572,8 @@
       NGPhysicalBoxFragment::Create(this, block_or_line_writing_mode);
   fragment->CheckType();
 
-  return MakeGarbageCollected<NGLayoutResult>(
-      NGLayoutResult::BoxFragmentBuilderPassKey(), std::move(fragment), this);
+  return MakeGarbageCollected<LayoutResult>(
+      LayoutResult::BoxFragmentBuilderPassKey(), std::move(fragment), this);
 }
 
 LogicalOffset BoxFragmentBuilder::GetChildOffset(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index 960e6b2..e777b9c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -189,7 +189,7 @@
   // that's passed to the function, but if this is a line box with a block
   // inside (aka. block-in-inline), it will return the layout result for the
   // block instead.
-  const NGLayoutResult& LayoutResultForPropagation(const NGLayoutResult&) const;
+  const LayoutResult& LayoutResultForPropagation(const LayoutResult&) const;
 
   // Add a break token for a child that doesn't yet have any fragments, because
   // its first fragment is to be produced in the next fragmentainer. This will
@@ -210,13 +210,13 @@
   // |inline_container| is passed when adding an OOF that is contained by a
   // non-atomic inline.
   void AddResult(
-      const NGLayoutResult&,
+      const LayoutResult&,
       const LogicalOffset,
       absl::optional<const BoxStrut> margins,
       absl::optional<LogicalOffset> relative_offset = absl::nullopt,
       const OofInlineContainer<LogicalOffset>* inline_container = nullptr);
   // AddResult() with the default margin computation.
-  void AddResult(const NGLayoutResult& child_layout_result,
+  void AddResult(const LayoutResult& child_layout_result,
                  const LogicalOffset offset);
 
   // Add a child fragment and propagate info from it. Called by AddResult().
@@ -432,11 +432,11 @@
   }
 
   // Creates the fragment. Can only be called once.
-  const NGLayoutResult* ToBoxFragment() {
+  const LayoutResult* ToBoxFragment() {
     DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
     return ToBoxFragment(GetWritingMode());
   }
-  const NGLayoutResult* ToInlineBoxFragment() {
+  const LayoutResult* ToInlineBoxFragment() {
     // The logical coordinate for inline box uses line-relative writing-mode,
     // not
     // flow-relative.
@@ -624,15 +624,15 @@
   }
 
   // Propagate the break-before/break-after of the child (if applicable).
-  void PropagateChildBreakValues(const NGLayoutResult& child_layout_result);
+  void PropagateChildBreakValues(const LayoutResult& child_layout_result);
 
  private:
   // Propagate fragmentation details. This includes checking whether we have
   // fragmented in this flow, break appeal, column spanner detection, and column
   // balancing hints.
-  void PropagateBreakInfo(const NGLayoutResult&, LogicalOffset);
+  void PropagateBreakInfo(const LayoutResult&, LogicalOffset);
 
-  const NGLayoutResult* ToBoxFragment(WritingMode);
+  const LayoutResult* ToBoxFragment(WritingMode);
 
   const FragmentGeometry* initial_fragment_geometry_ = nullptr;
   BoxStrut border_padding_;
@@ -721,7 +721,7 @@
 
   friend class BlockBreakToken;
   friend class NGPhysicalBoxFragment;
-  friend class NGLayoutResult;
+  friend class LayoutResult;
   friend class PhysicalFragmentRareData;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index 16050c9c..7d81135 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -232,7 +232,7 @@
   }
 }
 
-const NGLayoutResult* ColumnLayoutAlgorithm::Layout() {
+const LayoutResult* ColumnLayoutAlgorithm::Layout() {
   const LogicalSize border_box_size = container_builder_.InitialBorderBoxSize();
   // TODO(mstensho): This isn't the content-box size, as
   // |BorderScrollbarPadding()| has been adjusted for fragmentation. Verify
@@ -454,7 +454,7 @@
     // break token, we wouldn't be able to resume layout after the any initial
     // spanners.
     if (!entry.spanner) {
-      const NGLayoutResult* result =
+      const LayoutResult* result =
           LayoutRow(child_break_token, LayoutUnit(), &margin_strut);
 
       if (!result) {
@@ -466,7 +466,7 @@
       walker.Next();
 
       const auto* next_column_token =
-          To<BlockBreakToken>(result->PhysicalFragment().GetBreakToken());
+          To<BlockBreakToken>(result->GetPhysicalFragment().GetBreakToken());
 
       if (const auto* path = result->GetColumnSpannerPath()) {
         // We found a spanner, and if there's column content to resume at after
@@ -562,20 +562,20 @@
   DISALLOW_NEW();
 
  public:
-  Member<const NGLayoutResult> result;
+  Member<const LayoutResult> result;
   LogicalOffset offset;
 
-  ResultWithOffset(const NGLayoutResult* result, LogicalOffset offset)
+  ResultWithOffset(const LayoutResult* result, LogicalOffset offset)
       : result(result), offset(offset) {}
 
   const NGPhysicalBoxFragment& Fragment() const {
-    return To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+    return To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   }
 
   void Trace(Visitor* visitor) const { visitor->Trace(result); }
 };
 
-const NGLayoutResult* ColumnLayoutAlgorithm::LayoutRow(
+const LayoutResult* ColumnLayoutAlgorithm::LayoutRow(
     const BlockBreakToken* next_column_token,
     LayoutUnit minimum_column_block_size,
     MarginStrut* margin_strut) {
@@ -711,7 +711,7 @@
     }
   }
 
-  const NGLayoutResult* result = nullptr;
+  const LayoutResult* result = nullptr;
   absl::optional<BreakAppeal> min_break_appeal;
   LayoutUnit intrinsic_block_size_contribution;
 
@@ -751,7 +751,7 @@
       child_algorithm.SetBoxType(NGPhysicalFragment::kColumnBox);
       result = child_algorithm.Layout();
       const auto& column =
-          To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+          To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
       intrinsic_block_size_contribution = column_size.block_size;
       if (shrink_to_fit_column_block_size) {
         // Shrink-to-fit the row block-size contribution from the first column
@@ -1097,7 +1097,7 @@
   }
 
   const auto& spanner_fragment =
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   LogicalFragment logical_fragment(GetConstraintSpace().GetWritingDirection(),
                                    spanner_fragment);
 
@@ -1140,7 +1140,7 @@
   if (!baseline)
     return;
 
-  const NGLayoutResult* layout_result = marker.Layout(
+  const LayoutResult* layout_result = marker.Layout(
       GetConstraintSpace(), container_builder_.Style(), baseline_type);
   DCHECK(layout_result);
 
@@ -1163,7 +1163,7 @@
 
   // Lay out the list marker.
   FontBaseline baseline_type = Style().GetFontBaseline();
-  const NGLayoutResult* layout_result =
+  const LayoutResult* layout_result =
       marker.Layout(GetConstraintSpace(), Style(), baseline_type);
   DCHECK(layout_result);
   // Position the list marker without aligning with line boxes.
@@ -1310,13 +1310,13 @@
     params.column_spanner_path = spanner_path_;
     BlockLayoutAlgorithm balancing_algorithm(params);
     balancing_algorithm.SetBoxType(NGPhysicalFragment::kColumnBox);
-    const NGLayoutResult* result = balancing_algorithm.Layout();
+    const LayoutResult* result = balancing_algorithm.Layout();
 
     // This algorithm should never abort.
-    DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+    DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
 
-    const NGPhysicalBoxFragment& fragment =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+    const auto& fragment =
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
 
     // Add a content run, as long as we have soft break opportunities. Ignore
     // content that's doomed to end up in overflowing columns (because of too
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
index 764c8cd1..9c786f8 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.h
@@ -24,7 +24,7 @@
  public:
   explicit ColumnLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
@@ -43,9 +43,9 @@
   // column that was laid out. The rows themselves don't create fragments. If
   // we're in a nested fragmentation context, and a break is inserted before the
   // row, nullptr is returned.
-  const NGLayoutResult* LayoutRow(const BlockBreakToken* next_column_token,
-                                  LayoutUnit miminum_column_block_size,
-                                  MarginStrut*);
+  const LayoutResult* LayoutRow(const BlockBreakToken* next_column_token,
+                                LayoutUnit miminum_column_block_size,
+                                MarginStrut*);
 
   // Lay out a column spanner. The return value will tell whether to break
   // before the spanner or not. If |BreakStatus::kContinue| is returned, and
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index 57858df..7abacae 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -632,7 +632,7 @@
 
   // The amount of available space for block-start side annotation.
   // For the first box, this is the padding-block-start value of the container.
-  // Otherwise, this comes from NGLayoutResult::BlockEndAnnotationSpace().
+  // Otherwise, this comes from LayoutResult::BlockEndAnnotationSpace().
   // If the value is negative, it's block-end annotation overflow of the
   // previous box.
   LayoutUnit BlockStartAnnotationSpace() const {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc b/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc
index dab34d2..f00fe4a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.cc
@@ -6,6 +6,6 @@
 
 namespace blink {
 
-unsigned NGDisableSideEffectsScope::count_ = 0;
+unsigned DisableLayoutSideEffectsScope::count_ = 0;
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h b/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h
index 326de34..9ac0568 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_disable_side_effects_scope.h
@@ -14,12 +14,12 @@
 // just return fragments without updating the |LayoutObject| tree, paint
 // properties, and other global objects. This is used e.g., when computing
 // MinMax after layout.
-class CORE_EXPORT NGDisableSideEffectsScope {
+class CORE_EXPORT DisableLayoutSideEffectsScope {
   STACK_ALLOCATED();
 
  public:
-  NGDisableSideEffectsScope() { ++count_; }
-  ~NGDisableSideEffectsScope() {
+  DisableLayoutSideEffectsScope() { ++count_; }
+  ~DisableLayoutSideEffectsScope() {
     DCHECK(count_);
     --count_;
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index efe8554..a591bd5 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -68,7 +68,7 @@
   border_box_size_ = container_builder_.InitialBorderBoxSize();
 }
 
-const NGLayoutResult* FieldsetLayoutAlgorithm::Layout() {
+const LayoutResult* FieldsetLayoutAlgorithm::Layout() {
   // Layout of a fieldset container consists of two parts: Create a child
   // fragment for the rendered legend (if any), and create a child fragment for
   // the fieldset contents anonymous box (if any).
@@ -92,7 +92,7 @@
   BreakStatus break_status = LayoutChildren();
   if (break_status == BreakStatus::kNeedsEarlierBreak) {
     // We need to abort the layout. No fragment will be generated.
-    return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+    return container_builder_.Abort(LayoutResult::kNeedsEarlierBreak);
   }
 
   intrinsic_block_size_ = ClampIntrinsicBlockSize(
@@ -250,12 +250,12 @@
 
   auto legend_space = CreateConstraintSpaceForLegend(
       legend, ChildAvailableSize(), percentage_size);
-  const NGLayoutResult* result = legend.Layout(legend_space, GetBreakToken());
+  const LayoutResult* result = legend.Layout(legend_space, GetBreakToken());
 
   // Legends are monolithic, so abortions are not expected.
-  DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
 
-  const auto& physical_fragment = result->PhysicalFragment();
+  const auto& physical_fragment = result->GetPhysicalFragment();
 
   LayoutUnit legend_border_box_block_size =
       LogicalFragment(writing_direction_, physical_fragment).BlockSize();
@@ -288,7 +288,7 @@
 
   LayoutUnit legend_inline_start = ComputeLegendInlineOffset(
       legend.Style(),
-      LogicalFragment(writing_direction_, result->PhysicalFragment())
+      LogicalFragment(writing_direction_, result->GetPhysicalFragment())
           .InlineSize(),
       legend_margins, Style(), BorderScrollbarPadding().inline_start,
       ChildAvailableSize().inline_size);
@@ -340,7 +340,7 @@
     }
   }
 
-  const NGLayoutResult* result = nullptr;
+  const LayoutResult* result = nullptr;
   bool is_past_end = GetBreakToken() && GetBreakToken()->IsAtBlockEnd();
 
   LayoutUnit max_content_block_size = LayoutUnit::Max();
@@ -367,7 +367,7 @@
   // - The intrinsic block-size of the content is larger than the
   //   max-block-size.
   if (max_content_block_size != LayoutUnit::Max() &&
-      (!result || result->Status() == NGLayoutResult::kSuccess)) {
+      (!result || result->Status() == LayoutResult::kSuccess)) {
     DCHECK_EQ(adjusted_padding_box_size.block_size, kIndefiniteSize);
     if (max_content_block_size > Padding().BlockSum()) {
       // intrinsic_block_size_ is
@@ -379,7 +379,7 @@
     }
 
     if (result) {
-      const auto& fragment = result->PhysicalFragment();
+      const auto& fragment = result->GetPhysicalFragment();
       LayoutUnit total_block_size =
           LogicalFragment(writing_direction_, fragment).BlockSize();
       if (content_break_token)
@@ -409,12 +409,12 @@
   }
 
   if (break_status == BreakStatus::kContinue) {
-    DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+    DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
     LogicalOffset offset(Borders().inline_start, intrinsic_block_size_);
     container_builder_.AddResult(*result, offset);
 
     const auto& fragment =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
     if (auto first_baseline = fragment.FirstBaseline()) {
       container_builder_.SetFirstBaseline(offset.block_offset +
                                           *first_baseline);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
index eb9c06be..3413e11 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
@@ -21,7 +21,7 @@
  public:
   explicit FieldsetLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
index 6ccc93b..142f35c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
@@ -194,7 +194,8 @@
   LayoutFloatWithoutFragmentation(unpositioned_float);
   DCHECK(unpositioned_float->layout_result);
 
-  const auto& fragment = unpositioned_float->layout_result->PhysicalFragment();
+  const auto& fragment =
+      unpositioned_float->layout_result->GetPhysicalFragment();
   DCHECK(!fragment.GetBreakToken());
 
   const ConstraintSpace& parent_space = unpositioned_float->parent_space;
@@ -216,7 +217,7 @@
   bool is_fragmentable =
       is_same_writing_mode && parent_space.HasBlockFragmentation();
 
-  const NGLayoutResult* layout_result = nullptr;
+  const LayoutResult* layout_result = nullptr;
   BoxStrut fragment_margins;
   LayoutOpportunity opportunity;
   bool need_break_before = false;
@@ -229,7 +230,7 @@
     fragment_margins = unpositioned_float->margins;
 
     LogicalFragment float_fragment(parent_space.GetWritingDirection(),
-                                   layout_result->PhysicalFragment());
+                                   layout_result->GetPhysicalFragment());
 
     // Find a layout opportunity that will fit our float.
     opportunity = FindLayoutOpportunityForFloat(
@@ -251,7 +252,7 @@
       // We have already laid out the float to find its inline-size.
       LogicalFragment float_fragment(
           parent_space.GetWritingDirection(),
-          unpositioned_float->layout_result->PhysicalFragment());
+          unpositioned_float->layout_result->GetPhysicalFragment());
       // We can find a layout opportunity and set the fragmentainer offset right
       // away.
       opportunity = FindLayoutOpportunityForFloat(
@@ -279,14 +280,14 @@
       is_at_fragmentainer_start = space.IsAtFragmentainerStart();
 
       layout_result = node.Layout(space, unpositioned_float->token);
-      DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+      DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
 
       // If we knew the right block-offset up front, we're done.
       if (!optimistically_placed)
         break;
 
       LogicalFragment float_fragment(parent_space.GetWritingDirection(),
-                                     layout_result->PhysicalFragment());
+                                     layout_result->GetPhysicalFragment());
 
       // Find a layout opportunity that will fit our float, and see if our
       // initial estimate was correct.
@@ -335,7 +336,7 @@
           opportunity.rect.start_offset.block_offset +
           fragment_margins.block_start;
       const auto* break_token = To<BlockBreakToken>(
-          layout_result->PhysicalFragment().GetBreakToken());
+          layout_result->GetPhysicalFragment().GetBreakToken());
       bool is_at_block_end = !break_token || break_token->IsAtBlockEnd();
       if (!is_at_block_end) {
         // We need to resume in the next fragmentainer (or even push the whole
@@ -350,7 +351,7 @@
       } else if (is_at_block_end &&
                  parent_space.HasKnownFragmentainerBlockSize()) {
         LogicalFragment float_fragment(parent_space.GetWritingDirection(),
-                                       layout_result->PhysicalFragment());
+                                       layout_result->GetPhysicalFragment());
         LayoutUnit outer_block_end = fragmentainer_block_offset +
                                      float_fragment.BlockSize() +
                                      fragment_margins.block_end;
@@ -366,7 +367,7 @@
   }
 
   const auto& physical_fragment =
-      To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment());
   LogicalFragment float_fragment(parent_space.GetWritingDirection(),
                                  physical_fragment);
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
index 5babac8..a23921a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
@@ -188,17 +188,17 @@
 }
 
 void FragmentBuilder::PropagateFromLayoutResultAndFragment(
-    const NGLayoutResult& child_result,
+    const LayoutResult& child_result,
     LogicalOffset child_offset,
     LogicalOffset relative_offset,
     const OofInlineContainer<LogicalOffset>* inline_container) {
   PropagateFromLayoutResult(child_result);
-  PropagateFromFragment(child_result.PhysicalFragment(), child_offset,
+  PropagateFromFragment(child_result.GetPhysicalFragment(), child_offset,
                         relative_offset, inline_container);
 }
 
 void FragmentBuilder::PropagateFromLayoutResult(
-    const NGLayoutResult& child_result) {
+    const LayoutResult& child_result) {
   has_orthogonal_fallback_size_descendant_ |=
       child_result.HasOrthogonalFallbackInlineSize() ||
       child_result.HasOrthogonalFallbackSizeDescendant();
@@ -922,9 +922,9 @@
   UpdateMinimalSpaceShortage(space_shortage, &minimal_space_shortage_);
 }
 
-const NGLayoutResult* FragmentBuilder::Abort(NGLayoutResult::EStatus status) {
-  return MakeGarbageCollected<NGLayoutResult>(
-      NGLayoutResult::FragmentBuilderPassKey(), status, this);
+const LayoutResult* FragmentBuilder::Abort(LayoutResult::EStatus status) {
+  return MakeGarbageCollected<LayoutResult>(
+      LayoutResult::FragmentBuilderPassKey(), status, this);
 }
 
 #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
index b9ca2072..04d8a09 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
@@ -453,7 +453,7 @@
     has_descendant_that_depends_on_percentage_block_size_ = b;
   }
 
-  // See NGLayoutResult::AnnotationOverflow().
+  // See LayoutResult::AnnotationOverflow().
   void SetAnnotationOverflow(LayoutUnit overflow) {
     annotation_overflow_ = overflow;
   }
@@ -489,7 +489,7 @@
   void SetIsInitialColumnBalancingPass() {
     // Note that we have no dedicated flag for being in the initial column
     // balancing pass here. We'll just bump tallest_unbreakable_block_size_ to
-    // 0, so that NGLayoutResult knows that we need to store unbreakable
+    // 0, so that LayoutResult knows that we need to store unbreakable
     // block-size.
     DCHECK_EQ(tallest_unbreakable_block_size_, LayoutUnit::Min());
     tallest_unbreakable_block_size_ = LayoutUnit();
@@ -498,7 +498,7 @@
     return tallest_unbreakable_block_size_ >= LayoutUnit();
   }
 
-  const NGLayoutResult* Abort(NGLayoutResult::EStatus);
+  const LayoutResult* Abort(LayoutResult::EStatus);
 
 #if DCHECK_IS_ON()
   String ToString() const;
@@ -524,12 +524,12 @@
   ScrollStartTargetCandidates& EnsureScrollStartTargets();
 
   void PropagateFromLayoutResultAndFragment(
-      const NGLayoutResult&,
+      const LayoutResult&,
       LogicalOffset child_offset,
       LogicalOffset relative_offset,
       const OofInlineContainer<LogicalOffset>* = nullptr);
 
-  void PropagateFromLayoutResult(const NGLayoutResult&);
+  void PropagateFromLayoutResult(const LayoutResult&);
   void PropagateScrollStartTarget(const NGPhysicalFragment& child);
 
   void PropagateFromFragment(
@@ -601,9 +601,9 @@
   // The appeal of breaking inside this container.
   BreakAppeal break_appeal_ = kBreakAppealPerfect;
 
-  // See NGLayoutResult::AnnotationOverflow().
+  // See LayoutResult::AnnotationOverflow().
   LayoutUnit annotation_overflow_;
-  // See NGLayoutResult::BlockEndAnnotationSpace().
+  // See LayoutResult::BlockEndAnnotationSpace().
   LayoutUnit block_end_annotation_space_;
 
   LayoutUnit minimal_space_shortage_ = kIndefiniteSize;
@@ -644,7 +644,7 @@
 #endif
 
   friend class InlineLayoutStateStack;
-  friend class NGLayoutResult;
+  friend class LayoutResult;
   friend class NGPhysicalFragment;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc
index bdfdf0f..0d217fe56 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.cc
@@ -114,7 +114,7 @@
 
 }  // anonymous namespace
 
-void NGFragmentRepeater::CloneChildFragments(
+void FragmentRepeater::CloneChildFragments(
     const NGPhysicalBoxFragment& cloned_fragment) {
   if (cloned_fragment.HasItems()) {
     // Fragment items have already been cloned, but any atomic inlines were
@@ -131,11 +131,11 @@
         DCHECK(child_box_fragment->GetLayoutObject()->IsLayoutInline());
         continue;
       }
-      const NGLayoutResult* child_result =
+      const LayoutResult* child_result =
           GetClonableLayoutResult(*child_layout_box, *child_box_fragment);
       child_result = Repeat(*child_result);
       child_box_fragment =
-          &To<NGPhysicalBoxFragment>(child_result->PhysicalFragment());
+          &To<NGPhysicalBoxFragment>(child_result->GetPhysicalFragment());
       cloned_item.GetMutableForCloning().ReplaceBoxFragment(
           *child_box_fragment);
     }
@@ -148,10 +148,10 @@
       if (child_box->IsCSSBox()) {
         const auto* child_layout_box =
             To<LayoutBox>(child_box->GetLayoutObject());
-        const NGLayoutResult* child_result =
+        const LayoutResult* child_result =
             GetClonableLayoutResult(*child_layout_box, *child_box);
         child_result = Repeat(*child_result);
-        child.fragment = &child_result->PhysicalFragment();
+        child.fragment = &child_result->GetPhysicalFragment();
       } else if (child_box->IsFragmentainerBox()) {
         child_box = NGPhysicalBoxFragment::Clone(*child_box);
         CloneChildFragments(*child_box);
@@ -164,10 +164,10 @@
   }
 }
 
-const NGLayoutResult* NGFragmentRepeater::Repeat(const NGLayoutResult& other) {
-  const NGLayoutResult* cloned_result = NGLayoutResult::Clone(other);
+const LayoutResult* FragmentRepeater::Repeat(const LayoutResult& other) {
+  const LayoutResult* cloned_result = LayoutResult::Clone(other);
   const auto& cloned_fragment =
-      To<NGPhysicalBoxFragment>(cloned_result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(cloned_result->GetPhysicalFragment());
   auto& layout_box = *To<LayoutBox>(cloned_fragment.GetMutableLayoutObject());
 
   if (is_first_clone_ && cloned_fragment.IsFirstForNode()) {
@@ -194,7 +194,7 @@
   return cloned_result;
 }
 
-const NGLayoutResult* NGFragmentRepeater::GetClonableLayoutResult(
+const LayoutResult* FragmentRepeater::GetClonableLayoutResult(
     const LayoutBox& layout_box,
     const NGPhysicalBoxFragment& fragment) const {
   if (const BlockBreakToken* break_token = fragment.GetBreakToken()) {
@@ -208,9 +208,10 @@
   // fragmentation context), in case we've already been through this. This will
   // actually be the very first result, unless there's a fragmentation context
   // established inside the repeated root.
-  for (const NGLayoutResult* result : layout_box.GetLayoutResults()) {
+  for (const LayoutResult* result : layout_box.GetLayoutResults()) {
     const BlockBreakToken* break_token =
-        To<NGPhysicalBoxFragment>(result->PhysicalFragment()).GetBreakToken();
+        To<NGPhysicalBoxFragment>(result->GetPhysicalFragment())
+            .GetBreakToken();
     if (!break_token || break_token->IsRepeated())
       return result;
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.h b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.h
index 5d31796..8c34743 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_repeater.h
@@ -10,7 +10,7 @@
 namespace blink {
 
 class LayoutBox;
-class NGLayoutResult;
+class LayoutResult;
 class NGPhysicalBoxFragment;
 
 // Fragment tree mutator / cloner / repeater.
@@ -22,11 +22,11 @@
 // On the layout side, we only lay out the element once, but pre-paint and paint
 // require one unique fragment for each time it repeats, since we need one
 // FragmentData object for each, each with its own global-ish paint offset.
-class NGFragmentRepeater {
+class FragmentRepeater {
   STACK_ALLOCATED();
 
  public:
-  NGFragmentRepeater(bool is_first_clone, bool is_last_fragment)
+  FragmentRepeater(bool is_first_clone, bool is_last_fragment)
       : is_first_clone_(is_first_clone), is_last_fragment_(is_last_fragment) {}
 
   // Deep-clone the subtree of an already shallowly cloned fragment. This will
@@ -36,9 +36,9 @@
   void CloneChildFragments(const NGPhysicalBoxFragment& cloned_fragment);
 
  private:
-  const NGLayoutResult* Repeat(const NGLayoutResult& other);
+  const LayoutResult* Repeat(const LayoutResult& other);
 
-  const NGLayoutResult* GetClonableLayoutResult(
+  const LayoutResult* GetClonableLayoutResult(
       const LayoutBox& layout_box,
       const NGPhysicalBoxFragment& fragment) const;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index ae6b320f..94b9a4c3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -109,7 +109,7 @@
                                                      EBreakInside);
 
 EBreakBetween CalculateBreakBetweenValue(LayoutInputNode child,
-                                         const NGLayoutResult& layout_result,
+                                         const LayoutResult& layout_result,
                                          const BoxFragmentBuilder& builder) {
   if (child.IsInline())
     return EBreakBetween::kAuto;
@@ -117,8 +117,9 @@
   // Since it's not an inline node, if we have a fragment at all, it has to be a
   // box fragment.
   const NGPhysicalBoxFragment* box_fragment = nullptr;
-  if (layout_result.Status() == NGLayoutResult::kSuccess) {
-    box_fragment = &To<NGPhysicalBoxFragment>(layout_result.PhysicalFragment());
+  if (layout_result.Status() == LayoutResult::kSuccess) {
+    box_fragment =
+        &To<NGPhysicalBoxFragment>(layout_result.GetPhysicalFragment());
     if (!box_fragment->IsFirstForNode()) {
       // If the node is resumed after a break, we are not *before* it anymore,
       // so ignore values. We normally don't even consider breaking before a
@@ -152,14 +153,16 @@
 
 bool IsBreakableAtStartOfResumedContainer(
     const ConstraintSpace& space,
-    const NGLayoutResult& child_layout_result,
+    const LayoutResult& child_layout_result,
     const BoxFragmentBuilder& builder) {
-  if (child_layout_result.Status() != NGLayoutResult::kSuccess)
+  if (child_layout_result.Status() != LayoutResult::kSuccess) {
     return false;
+  }
   bool is_first_for_node = true;
   if (const auto* box_fragment = DynamicTo<NGPhysicalBoxFragment>(
-          child_layout_result.PhysicalFragment()))
+          child_layout_result.GetPhysicalFragment())) {
     is_first_for_node = box_fragment->IsFirstForNode();
+  }
   return IsBreakableAtStartOfResumedContainer(space, builder,
                                               is_first_for_node);
 }
@@ -173,7 +176,7 @@
 
 BreakAppeal CalculateBreakAppealBefore(const ConstraintSpace& space,
                                        LayoutInputNode child,
-                                       const NGLayoutResult& layout_result,
+                                       const LayoutResult& layout_result,
                                        const BoxFragmentBuilder& builder,
                                        bool has_container_separation) {
   bool breakable_at_start_of_container =
@@ -187,15 +190,15 @@
 
 BreakAppeal CalculateBreakAppealBefore(
     const ConstraintSpace& space,
-    NGLayoutResult::EStatus layout_result_status,
+    LayoutResult::EStatus layout_result_status,
     EBreakBetween break_between,
     bool has_container_separation,
     bool breakable_at_start_of_container) {
-  DCHECK(layout_result_status == NGLayoutResult::kSuccess ||
-         layout_result_status == NGLayoutResult::kOutOfFragmentainerSpace);
+  DCHECK(layout_result_status == LayoutResult::kSuccess ||
+         layout_result_status == LayoutResult::kOutOfFragmentainerSpace);
   BreakAppeal break_appeal = kBreakAppealPerfect;
   if (!has_container_separation &&
-      layout_result_status == NGLayoutResult::kSuccess) {
+      layout_result_status == LayoutResult::kSuccess) {
     if (!breakable_at_start_of_container) {
       // This is not a valid break point. If there's no container separation, it
       // means that we're breaking before the first piece of in-flow content
@@ -226,11 +229,11 @@
 
 BreakAppeal CalculateBreakAppealInside(
     const ConstraintSpace& space,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     absl::optional<BreakAppeal> hypothetical_appeal) {
   if (layout_result.HasForcedBreak())
     return kBreakAppealPerfect;
-  const auto& physical_fragment = layout_result.PhysicalFragment();
+  const auto& physical_fragment = layout_result.GetPhysicalFragment();
   const auto* break_token =
       DynamicTo<BlockBreakToken>(physical_fragment.GetBreakToken());
   BreakAppeal appeal;
@@ -815,7 +818,7 @@
 BreakStatus BreakBeforeChildIfNeeded(
     const ConstraintSpace& space,
     LayoutInputNode child,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     LayoutUnit fragmentainer_block_offset,
     bool has_container_separation,
     BoxFragmentBuilder* builder,
@@ -859,7 +862,7 @@
 
 void BreakBeforeChild(const ConstraintSpace& space,
                       LayoutInputNode child,
-                      const NGLayoutResult* layout_result,
+                      const LayoutResult* layout_result,
                       LayoutUnit fragmentainer_block_offset,
                       absl::optional<BreakAppeal> appeal,
                       bool is_forced_break,
@@ -867,10 +870,10 @@
                       absl::optional<LayoutUnit> block_size_override) {
 #if DCHECK_IS_ON()
   DCHECK(layout_result || block_size_override);
-  if (layout_result && layout_result->Status() == NGLayoutResult::kSuccess) {
+  if (layout_result && layout_result->Status() == LayoutResult::kSuccess) {
     // In order to successfully break before a node, this has to be its first
     // fragment.
-    const auto& physical_fragment = layout_result->PhysicalFragment();
+    const auto& physical_fragment = layout_result->GetPhysicalFragment();
     DCHECK(!physical_fragment.IsBox() ||
            To<NGPhysicalBoxFragment>(physical_fragment).IsFirstForNode());
   }
@@ -891,7 +894,7 @@
 }
 
 void PropagateSpaceShortage(const ConstraintSpace& space,
-                            const NGLayoutResult* layout_result,
+                            const LayoutResult* layout_result,
                             LayoutUnit fragmentainer_block_offset,
                             FragmentBuilder* builder,
                             absl::optional<LayoutUnit> block_size_override) {
@@ -911,7 +914,7 @@
 
 LayoutUnit CalculateSpaceShortage(
     const ConstraintSpace& space,
-    const NGLayoutResult* layout_result,
+    const LayoutResult* layout_result,
     LayoutUnit fragmentainer_block_offset,
     absl::optional<LayoutUnit> block_size_override) {
   // Space shortage is only reported for soft breaks, and they can only exist if
@@ -930,10 +933,11 @@
     // Calculate space shortage: Figure out how much more space would have been
     // sufficient to make the child fragment fit right here in the current
     // fragmentainer. If layout aborted, though, we can't calculate anything.
-    if (layout_result->Status() != NGLayoutResult::kSuccess)
+    if (layout_result->Status() != LayoutResult::kSuccess) {
       return kIndefiniteSize;
+    }
     LogicalFragment fragment(space.GetWritingDirection(),
-                             layout_result->PhysicalFragment());
+                             layout_result->GetPhysicalFragment());
     space_shortage = fragmentainer_block_offset + fragment.BlockSize() -
                      space.FragmentainerBlockSize();
   } else {
@@ -960,16 +964,16 @@
 
 bool MovePastBreakpoint(const ConstraintSpace& space,
                         LayoutInputNode child,
-                        const NGLayoutResult& layout_result,
+                        const LayoutResult& layout_result,
                         LayoutUnit fragmentainer_block_offset,
                         BreakAppeal appeal_before,
                         BoxFragmentBuilder* builder,
                         bool is_row_item,
                         FlexColumnBreakInfo* flex_column_break_info) {
-  if (layout_result.Status() != NGLayoutResult::kSuccess) {
+  if (layout_result.Status() != LayoutResult::kSuccess) {
     // Layout aborted - no fragment was produced. There's nothing to move
     // past. We need to break before.
-    DCHECK_EQ(layout_result.Status(), NGLayoutResult::kOutOfFragmentainerSpace);
+    DCHECK_EQ(layout_result.Status(), LayoutResult::kOutOfFragmentainerSpace);
     // The only case where this should happen is with BR clear=all.
     DCHECK(child.IsInline());
     return false;
@@ -977,7 +981,7 @@
 
   if (child.IsBlock()) {
     const auto& box_fragment =
-        To<NGPhysicalBoxFragment>(layout_result.PhysicalFragment());
+        To<NGPhysicalBoxFragment>(layout_result.GetPhysicalFragment());
 
     // If we're at a resumed fragment, don't break before it. Once we've found
     // room for the first fragment, we cannot skip fragmentainers afterwards. We
@@ -1001,7 +1005,7 @@
 
   if (!space.HasKnownFragmentainerBlockSize() &&
       space.IsInitialColumnBalancingPass() && builder) {
-    if (layout_result.PhysicalFragment().IsMonolithic() ||
+    if (layout_result.GetPhysicalFragment().IsMonolithic() ||
         (child.IsBlock() &&
          IsAvoidBreakValue(space, child.Style().BreakInside()))) {
       // If this is the initial column balancing pass, attempt to make the
@@ -1035,13 +1039,13 @@
 }
 
 bool MovePastBreakpoint(const ConstraintSpace& space,
-                        const NGLayoutResult& layout_result,
+                        const LayoutResult& layout_result,
                         LayoutUnit fragmentainer_block_offset,
                         BreakAppeal appeal_before,
                         BoxFragmentBuilder* builder,
                         bool is_row_item,
                         FlexColumnBreakInfo* flex_column_break_info) {
-  DCHECK_EQ(layout_result.Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(layout_result.Status(), LayoutResult::kSuccess);
 
   if (!space.HasKnownFragmentainerBlockSize()) {
     // We only care about soft breaks if we have a fragmentainer block-size.
@@ -1049,7 +1053,7 @@
     return true;
   }
 
-  const auto& physical_fragment = layout_result.PhysicalFragment();
+  const auto& physical_fragment = layout_result.GetPhysicalFragment();
   LogicalFragment fragment(space.GetWritingDirection(), physical_fragment);
   const auto* break_token =
       DynamicTo<BlockBreakToken>(physical_fragment.GetBreakToken());
@@ -1140,7 +1144,7 @@
 
 void UpdateEarlyBreakAtBlockChild(const ConstraintSpace& space,
                                   BlockNode child,
-                                  const NGLayoutResult& layout_result,
+                                  const LayoutResult& layout_result,
                                   BreakAppeal appeal_before,
                                   BoxFragmentBuilder* builder,
                                   FlexColumnBreakInfo* flex_column_break_info) {
@@ -1149,7 +1153,7 @@
   // help honor any break avoidance requests that come after this child. But
   // breaking *before* the child might help.
   const auto* break_token =
-      To<BlockBreakToken>(layout_result.PhysicalFragment().GetBreakToken());
+      To<BlockBreakToken>(layout_result.GetPhysicalFragment().GetBreakToken());
   // See if there's a good breakpoint inside the child.
   BreakAppeal appeal_inside = kBreakAppealLastResort;
   if (const auto* breakpoint = layout_result.GetEarlyBreak()) {
@@ -1207,7 +1211,7 @@
 
 bool AttemptSoftBreak(const ConstraintSpace& space,
                       LayoutInputNode child,
-                      const NGLayoutResult* layout_result,
+                      const LayoutResult* layout_result,
                       LayoutUnit fragmentainer_block_offset,
                       BreakAppeal appeal_before,
                       BoxFragmentBuilder* builder,
@@ -1471,7 +1475,7 @@
 }
 
 LayoutUnit BlockSizeForFragmentation(
-    const NGLayoutResult& result,
+    const LayoutResult& result,
     WritingDirectionMode container_writing_direction) {
   LayoutUnit block_size = result.BlockSizeForFragmentation();
   if (block_size == kIndefiniteSize) {
@@ -1480,7 +1484,7 @@
     // other kind of monolithic content.
     WritingMode writing_mode = container_writing_direction.GetWritingMode();
     LogicalSize logical_size =
-        result.PhysicalFragment().Size().ConvertToLogical(writing_mode);
+        result.GetPhysicalFragment().Size().ConvertToLogical(writing_mode);
     block_size = logical_size.block_size;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
index 7e9033f..19af3dfec 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -21,7 +21,7 @@
 namespace blink {
 
 class EarlyBreak;
-class NGLayoutResult;
+class LayoutResult;
 
 // Each column in a flex container is fragmented independently, so we need to
 // track early break and break-after info for each column separately.
@@ -88,7 +88,7 @@
 // is the combination of all break-before and break-after values that met at the
 // breakpoint.
 EBreakBetween CalculateBreakBetweenValue(LayoutInputNode child,
-                                         const NGLayoutResult&,
+                                         const LayoutResult&,
                                          const BoxFragmentBuilder&);
 
 // Return true if the container is being resumed after a fragmentainer break,
@@ -103,7 +103,7 @@
 // That row may be taller, which might help us avoid breaking violations.
 bool IsBreakableAtStartOfResumedContainer(
     const ConstraintSpace& space,
-    const NGLayoutResult& child_layout_result,
+    const LayoutResult& child_layout_result,
     const BoxFragmentBuilder& builder);
 
 bool IsBreakableAtStartOfResumedContainer(const ConstraintSpace& space,
@@ -113,12 +113,12 @@
 // Calculate the appeal of breaking before this child.
 BreakAppeal CalculateBreakAppealBefore(const ConstraintSpace&,
                                        LayoutInputNode child,
-                                       const NGLayoutResult&,
+                                       const LayoutResult&,
                                        const BoxFragmentBuilder&,
                                        bool has_container_separation);
 BreakAppeal CalculateBreakAppealBefore(
     const ConstraintSpace&,
-    NGLayoutResult::EStatus layout_result_status,
+    LayoutResult::EStatus layout_result_status,
     EBreakBetween break_between,
     bool has_container_separation,
     bool breakable_at_start_of_container);
@@ -129,7 +129,7 @@
 // didn't break, but still need to consider (see EarlyBreak).
 BreakAppeal CalculateBreakAppealInside(
     const ConstraintSpace& space,
-    const NGLayoutResult&,
+    const LayoutResult&,
     absl::optional<BreakAppeal> hypothetical_appeal = absl::nullopt);
 
 // To ensure content progression, we need fragmentainers to hold something
@@ -332,7 +332,7 @@
 BreakStatus BreakBeforeChildIfNeeded(
     const ConstraintSpace&,
     LayoutInputNode child,
-    const NGLayoutResult&,
+    const LayoutResult&,
     LayoutUnit fragmentainer_block_offset,
     bool has_container_separation,
     BoxFragmentBuilder*,
@@ -345,7 +345,7 @@
 void BreakBeforeChild(
     const ConstraintSpace&,
     LayoutInputNode child,
-    const NGLayoutResult*,
+    const LayoutResult*,
     LayoutUnit fragmentainer_block_offset,
     absl::optional<BreakAppeal> appeal,
     bool is_forced_break,
@@ -376,7 +376,7 @@
 // layout result.
 void PropagateSpaceShortage(
     const ConstraintSpace&,
-    const NGLayoutResult*,
+    const LayoutResult*,
     LayoutUnit fragmentainer_block_offset,
     FragmentBuilder*,
     absl::optional<LayoutUnit> block_size_override = absl::nullopt);
@@ -386,7 +386,7 @@
 // layout result.
 LayoutUnit CalculateSpaceShortage(
     const ConstraintSpace&,
-    const NGLayoutResult*,
+    const LayoutResult*,
     LayoutUnit fragmentainer_block_offset,
     absl::optional<LayoutUnit> block_size_override = absl::nullopt);
 // Update |minimal_space_shortage| based on the current |space_shortage|.
@@ -400,7 +400,7 @@
 // details on |flex_column_break_info|.
 bool MovePastBreakpoint(const ConstraintSpace& space,
                         LayoutInputNode child,
-                        const NGLayoutResult& layout_result,
+                        const LayoutResult& layout_result,
                         LayoutUnit fragmentainer_block_offset,
                         BreakAppeal appeal_before,
                         BoxFragmentBuilder* builder,
@@ -409,7 +409,7 @@
 
 // Same as above, but without the parts that require an LayoutInputNode.
 bool MovePastBreakpoint(const ConstraintSpace& space,
-                        const NGLayoutResult& layout_result,
+                        const LayoutResult& layout_result,
                         LayoutUnit fragmentainer_block_offset,
                         BreakAppeal appeal_before,
                         BoxFragmentBuilder* builder,
@@ -423,7 +423,7 @@
 void UpdateEarlyBreakAtBlockChild(
     const ConstraintSpace&,
     BlockNode child,
-    const NGLayoutResult&,
+    const LayoutResult&,
     BreakAppeal appeal_before,
     BoxFragmentBuilder*,
     FlexColumnBreakInfo* flex_column_break_info = nullptr);
@@ -437,7 +437,7 @@
 bool AttemptSoftBreak(
     const ConstraintSpace&,
     LayoutInputNode child,
-    const NGLayoutResult*,
+    const LayoutResult*,
     LayoutUnit fragmentainer_block_offset,
     BreakAppeal appeal_before,
     BoxFragmentBuilder*,
@@ -534,7 +534,7 @@
 // supposed to affect block fragmentation), and also out-of-flow positioned
 // descendants (in the initial balancing pass), but not relative offsets.
 LayoutUnit BlockSizeForFragmentation(
-    const NGLayoutResult&,
+    const LayoutResult&,
     WritingDirectionMode container_writing_direction);
 
 // Return true if we support painting of multiple fragments for the given
diff --git a/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.cc
index 76812c0eb..d7b1a39 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.cc
@@ -41,7 +41,7 @@
     const LayoutAlgorithmParams& params)
     : LayoutAlgorithm<BlockNode, BoxFragmentBuilder, BlockBreakToken>(params) {}
 
-const NGLayoutResult* FrameSetLayoutAlgorithm::Layout() {
+const LayoutResult* FrameSetLayoutAlgorithm::Layout() {
   auto& frame_set = *To<HTMLFrameSetElement>(Node().GetDOMNode());
   auto layout_data = std::make_unique<FrameSetLayoutData>();
   layout_data->border_thickness = frame_set.Border(Style());
@@ -318,7 +318,7 @@
   space_builder.SetAvailableSize(available_size);
   space_builder.SetIsFixedInlineSize(true);
   space_builder.SetIsFixedBlockSize(true);
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       To<BlockNode>(child).Layout(space_builder.ToConstraintSpace());
   container_builder_.AddResult(
       *result, position.ConvertToLogical(container_direction, frameset_size,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.h
index ed77ad8e..d9421635 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_frame_set_layout_algorithm.h
@@ -18,7 +18,7 @@
  public:
   explicit FrameSetLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
  private:
diff --git a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
index a5b291e..3bd5b68 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_ink_overflow.cc
@@ -630,7 +630,7 @@
       ink_overflow.size.inline_size, style, inline_context,
       /* selection_text_decoration */ absl::nullopt, decoration_override,
       &scaled_font, kMinimumThicknessIsOne);
-  NGTextDecorationOffset decoration_offset(style);
+  TextDecorationOffset decoration_offset(style);
   gfx::RectF accumulated_bound;
   for (wtf_size_t i = 0; i < decoration_info.AppliedDecorationCount(); i++) {
     decoration_info.SetDecorationIndex(i);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc b/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc
index bb68f1f..1368acf 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_inline_layout_test.cc
@@ -47,7 +47,7 @@
 
   FragmentGeometry fragment_geometry = CalculateInitialFragmentGeometry(
       constraint_space, node, /* break_token */ nullptr);
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       BlockLayoutAlgorithm({node, fragment_geometry, constraint_space})
           .Layout();
   EXPECT_TRUE(result);
@@ -74,7 +74,7 @@
   FragmentGeometry fragment_geometry =
       CalculateInitialFragmentGeometry(constraint_space, node,
                                        /* break_token */ nullptr);
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       BlockLayoutAlgorithm({node, fragment_geometry, constraint_space})
           .Layout();
   EXPECT_TRUE(result);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
index 2fee09d..a75aab2c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h
@@ -18,7 +18,7 @@
 class ColumnSpannerPath;
 class ComputedStyle;
 class EarlyBreak;
-class NGLayoutResult;
+class LayoutResult;
 
 // Operations provided by a layout algorithm.
 class LayoutAlgorithmOperations {
@@ -27,7 +27,7 @@
   // constraints given by the ConstraintSpace. Returns a layout result with
   // the resulting layout information.
   // TODO(layout-dev): attempt to make this function const.
-  virtual const NGLayoutResult* Layout() = 0;
+  virtual const LayoutResult* Layout() = 0;
 
   // Computes the min-content and max-content intrinsic sizes for the given box.
   // The result will not take any min-width, max-width or width properties into
@@ -61,7 +61,7 @@
   const BlockBreakToken* break_token;
   const EarlyBreak* early_break;
   const ColumnSpannerPath* column_spanner_path = nullptr;
-  const NGLayoutResult* previous_result = nullptr;
+  const LayoutResult* previous_result = nullptr;
   const HeapVector<Member<EarlyBreak>>* additional_early_breaks;
 };
 
@@ -149,7 +149,7 @@
   // fragmentainer at an less-than-ideal location, due to breaking restrictions,
   // such as orphans, widows, break-before:avoid or break-after:avoid.
   template <typename Algorithm>
-  const NGLayoutResult* RelayoutAndBreakEarlier(
+  const LayoutResult* RelayoutAndBreakEarlier(
       const EarlyBreak& breakpoint,
       const HeapVector<Member<EarlyBreak>>* additional_early_breaks = nullptr) {
     // Not allowed to recurse!
@@ -165,7 +165,7 @@
   }
 
   template <typename Algorithm>
-  const NGLayoutResult* RelayoutAndBreakEarlier(Algorithm* new_algorithm) {
+  const LayoutResult* RelayoutAndBreakEarlier(Algorithm* new_algorithm) {
     DCHECK(new_algorithm);
     auto& new_builder = new_algorithm->container_builder_;
     new_builder.SetBoxType(container_builder_.BoxType());
@@ -182,7 +182,7 @@
   // wants to break. We don't want any zero-sized clipped fragments that
   // contribute to superfluous fragmentainers.
   template <typename Algorithm>
-  const NGLayoutResult* RelayoutWithoutFragmentation() {
+  const LayoutResult* RelayoutWithoutFragmentation() {
     DCHECK(GetConstraintSpace().HasBlockFragmentation());
     // We'll relayout with a special cloned constraint space that disables
     // further fragmentation (but rather lets clipped child content "overflow"
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
index 419bffe..b1a398b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
@@ -20,8 +20,8 @@
 
 namespace {
 
-struct SameSizeAsNGLayoutResult
-    : public GarbageCollected<SameSizeAsNGLayoutResult> {
+struct SameSizeAsLayoutResult
+    : public GarbageCollected<SameSizeAsLayoutResult> {
   const ConstraintSpace space;
   Member<void*> physical_fragment;
   Member<void*> rare_data_;
@@ -33,30 +33,30 @@
   unsigned bitfields[1];
 };
 
-ASSERT_SIZE(NGLayoutResult, SameSizeAsNGLayoutResult);
+ASSERT_SIZE(LayoutResult, SameSizeAsLayoutResult);
 
 }  // namespace
 
 // static
-const NGLayoutResult* NGLayoutResult::Clone(const NGLayoutResult& other) {
-  return MakeGarbageCollected<NGLayoutResult>(
+const LayoutResult* LayoutResult::Clone(const LayoutResult& other) {
+  return MakeGarbageCollected<LayoutResult>(
       other, NGPhysicalBoxFragment::Clone(
-                 To<NGPhysicalBoxFragment>(other.PhysicalFragment())));
+                 To<NGPhysicalBoxFragment>(other.GetPhysicalFragment())));
 }
 
 // static
-const NGLayoutResult* NGLayoutResult::CloneWithPostLayoutFragments(
-    const NGLayoutResult& other) {
-  return MakeGarbageCollected<NGLayoutResult>(
+const LayoutResult* LayoutResult::CloneWithPostLayoutFragments(
+    const LayoutResult& other) {
+  return MakeGarbageCollected<LayoutResult>(
       other, NGPhysicalBoxFragment::CloneWithPostLayoutFragments(
-                 To<NGPhysicalBoxFragment>(other.PhysicalFragment())));
+                 To<NGPhysicalBoxFragment>(other.GetPhysicalFragment())));
 }
 
-NGLayoutResult::NGLayoutResult(BoxFragmentBuilderPassKey passkey,
-                               const NGPhysicalFragment* physical_fragment,
-                               BoxFragmentBuilder* builder)
-    : NGLayoutResult(std::move(physical_fragment),
-                     static_cast<FragmentBuilder*>(builder)) {
+LayoutResult::LayoutResult(BoxFragmentBuilderPassKey passkey,
+                           const NGPhysicalFragment* physical_fragment,
+                           BoxFragmentBuilder* builder)
+    : LayoutResult(std::move(physical_fragment),
+                   static_cast<FragmentBuilder*>(builder)) {
   bitfields_.is_initial_block_size_indefinite =
       builder->is_initial_block_size_indefinite_;
   intrinsic_block_size_ = builder->intrinsic_block_size_;
@@ -111,11 +111,11 @@
   }
 }
 
-NGLayoutResult::NGLayoutResult(LineBoxFragmentBuilderPassKey passkey,
-                               const NGPhysicalFragment* physical_fragment,
-                               LineBoxFragmentBuilder* builder)
-    : NGLayoutResult(std::move(physical_fragment),
-                     static_cast<FragmentBuilder*>(builder)) {
+LayoutResult::LayoutResult(LineBoxFragmentBuilderPassKey passkey,
+                           const NGPhysicalFragment* physical_fragment,
+                           LineBoxFragmentBuilder* builder)
+    : LayoutResult(std::move(physical_fragment),
+                   static_cast<FragmentBuilder*>(builder)) {
   DCHECK_EQ(builder->bfc_block_offset_.has_value(),
             builder->line_box_bfc_block_offset_.has_value());
   if (builder->bfc_block_offset_ != builder->line_box_bfc_block_offset_) {
@@ -132,21 +132,21 @@
   }
 }
 
-NGLayoutResult::NGLayoutResult(FragmentBuilderPassKey key,
-                               EStatus status,
-                               FragmentBuilder* builder)
-    : NGLayoutResult(/* physical_fragment */ nullptr, builder) {
+LayoutResult::LayoutResult(FragmentBuilderPassKey key,
+                           EStatus status,
+                           FragmentBuilder* builder)
+    : LayoutResult(/* physical_fragment */ nullptr, builder) {
   bitfields_.status = status;
   DCHECK_NE(status, kSuccess)
       << "Use the other constructor for successful layout";
 }
 
-NGLayoutResult::NGLayoutResult(const NGLayoutResult& other,
-                               const ConstraintSpace& new_space,
-                               const MarginStrut& new_end_margin_strut,
-                               LayoutUnit bfc_line_offset,
-                               absl::optional<LayoutUnit> bfc_block_offset,
-                               LayoutUnit block_offset_delta)
+LayoutResult::LayoutResult(const LayoutResult& other,
+                           const ConstraintSpace& new_space,
+                           const MarginStrut& new_end_margin_strut,
+                           LayoutUnit bfc_line_offset,
+                           absl::optional<LayoutUnit> bfc_block_offset,
+                           LayoutUnit block_offset_delta)
     : space_(new_space),
       physical_fragment_(other.physical_fragment_),
       rare_data_(other.rare_data_
@@ -180,8 +180,8 @@
   }
 }
 
-NGLayoutResult::NGLayoutResult(const NGLayoutResult& other,
-                               const NGPhysicalFragment* physical_fragment)
+LayoutResult::LayoutResult(const LayoutResult& other,
+                           const NGPhysicalFragment* physical_fragment)
     : space_(other.space_),
       physical_fragment_(std::move(physical_fragment)),
       rare_data_(other.rare_data_
@@ -200,8 +200,8 @@
   DCHECK_EQ(physical_fragment_->Size(), other.physical_fragment_->Size());
 }
 
-NGLayoutResult::NGLayoutResult(const NGPhysicalFragment* physical_fragment,
-                               FragmentBuilder* builder)
+LayoutResult::LayoutResult(const NGPhysicalFragment* physical_fragment,
+                           FragmentBuilder* builder)
     : space_(builder->space_),
       physical_fragment_(std::move(physical_fragment)),
       rare_data_(nullptr),
@@ -281,8 +281,8 @@
       !builder->bfc_block_offset_.has_value();
 }
 
-ExclusionSpace NGLayoutResult::MergeExclusionSpaces(
-    const NGLayoutResult& other,
+ExclusionSpace LayoutResult::MergeExclusionSpaces(
+    const LayoutResult& other,
     const ExclusionSpace& new_input_exclusion_space,
     LayoutUnit bfc_line_offset,
     LayoutUnit block_offset_delta) {
@@ -295,15 +295,14 @@
       /* new_input */ new_input_exclusion_space, offset_delta);
 }
 
-NGLayoutResult::RareData* NGLayoutResult::EnsureRareData() {
+LayoutResult::RareData* LayoutResult::EnsureRareData() {
   if (!rare_data_) {
     rare_data_ = MakeGarbageCollected<RareData>();
   }
   return rare_data_.Get();
 }
 
-void NGLayoutResult::CopyMutableOutOfFlowData(
-    const NGLayoutResult& other) const {
+void LayoutResult::CopyMutableOutOfFlowData(const LayoutResult& other) const {
   if (bitfields_.has_oof_insets_for_get_computed_style) {
     return;
   }
@@ -315,8 +314,8 @@
 }
 
 #if DCHECK_IS_ON()
-void NGLayoutResult::CheckSameForSimplifiedLayout(
-    const NGLayoutResult& other,
+void LayoutResult::CheckSameForSimplifiedLayout(
+    const LayoutResult& other,
     bool check_same_block_size,
     bool check_no_fragmentation) const {
   To<NGPhysicalBoxFragment>(*physical_fragment_)
@@ -361,19 +360,19 @@
 #endif
 
 #if DCHECK_IS_ON()
-void NGLayoutResult::AssertSoleBoxFragment() const {
+void LayoutResult::AssertSoleBoxFragment() const {
   DCHECK(physical_fragment_->IsBox());
-  DCHECK(To<NGPhysicalBoxFragment>(PhysicalFragment()).IsFirstForNode());
+  DCHECK(To<NGPhysicalBoxFragment>(GetPhysicalFragment()).IsFirstForNode());
   DCHECK(!physical_fragment_->GetBreakToken());
 }
 #endif
 
-void NGLayoutResult::Trace(Visitor* visitor) const {
+void LayoutResult::Trace(Visitor* visitor) const {
   visitor->Trace(physical_fragment_);
   visitor->Trace(rare_data_);
 }
 
-void NGLayoutResult::RareData::Trace(Visitor* visitor) const {
+void LayoutResult::RareData::Trace(Visitor* visitor) const {
   visitor->Trace(early_break);
   // This will not cause TOCTOU issue because data_union_type is set in the
   // constructor and never changed.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result.h b/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
index 23be4021..2d2a5022 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
@@ -37,14 +37,13 @@
 class FragmentBuilder;
 class LineBoxFragmentBuilder;
 
-// The NGLayoutResult stores the resulting data from layout. This includes
+// The LayoutResult stores the resulting data from layout. This includes
 // geometry information in form of a NGPhysicalFragment, which is kept around
 // for painting, hit testing, etc., as well as additional data which is only
 // necessary during layout and stored on this object.
 // Layout code should access the NGPhysicalFragment through the wrappers in
 // LogicalFragment et al.
-class CORE_EXPORT NGLayoutResult final
-    : public GarbageCollected<NGLayoutResult> {
+class CORE_EXPORT LayoutResult final : public GarbageCollected<LayoutResult> {
  public:
   enum EStatus {
     kSuccess = 0,
@@ -65,44 +64,44 @@
   // Make a shallow clone of the result. The fragment is cloned. Fragment
   // *items* are also cloned, but child fragments are not. Apart from that it's
   // truly shallow. Pinky promise.
-  static const NGLayoutResult* Clone(const NGLayoutResult&);
+  static const LayoutResult* Clone(const LayoutResult&);
 
   // Same as Clone(), but uses the "post-layout" fragments to ensure
   // fragment-tree consistency.
-  static const NGLayoutResult* CloneWithPostLayoutFragments(
-      const NGLayoutResult& other);
+  static const LayoutResult* CloneWithPostLayoutFragments(
+      const LayoutResult& other);
 
-  // Create a copy of NGLayoutResult with |BfcBlockOffset| replaced by the given
+  // Create a copy of LayoutResult with |BfcBlockOffset| replaced by the given
   // parameter. Note, when |bfc_block_offset| is |nullopt|, |BfcBlockOffset| is
   // still replaced with |nullopt|.
-  NGLayoutResult(const NGLayoutResult& other,
-                 const ConstraintSpace& new_space,
-                 const MarginStrut& new_end_margin_strut,
-                 LayoutUnit bfc_line_offset,
-                 absl::optional<LayoutUnit> bfc_block_offset,
-                 LayoutUnit block_offset_delta);
+  LayoutResult(const LayoutResult& other,
+               const ConstraintSpace& new_space,
+               const MarginStrut& new_end_margin_strut,
+               LayoutUnit bfc_line_offset,
+               absl::optional<LayoutUnit> bfc_block_offset,
+               LayoutUnit block_offset_delta);
 
-  // Creates a copy of NGLayoutResult with a new (but "identical") fragment.
-  NGLayoutResult(const NGLayoutResult& other,
-                 const NGPhysicalFragment* physical_fragment);
+  // Creates a copy of LayoutResult with a new (but "identical") fragment.
+  LayoutResult(const LayoutResult& other,
+               const NGPhysicalFragment* physical_fragment);
 
   // Delegate constructor that sets up what it can, based on the builder.
-  NGLayoutResult(const NGPhysicalFragment* physical_fragment,
-                 FragmentBuilder* builder);
+  LayoutResult(const NGPhysicalFragment* physical_fragment,
+               FragmentBuilder* builder);
 
   // We don't need the copy constructor, move constructor, copy
   // assigmnment-operator, or move assignment-operator today.
   // If at some point we do need these constructors particular care will need
   // to be taken with the |rare_data_| field.
-  NGLayoutResult(const NGLayoutResult&) = delete;
-  NGLayoutResult(NGLayoutResult&&) = delete;
-  NGLayoutResult& operator=(const NGLayoutResult& other) = delete;
-  NGLayoutResult& operator=(NGLayoutResult&& other) = delete;
-  NGLayoutResult() = delete;
+  LayoutResult(const LayoutResult&) = delete;
+  LayoutResult(LayoutResult&&) = delete;
+  LayoutResult& operator=(const LayoutResult& other) = delete;
+  LayoutResult& operator=(LayoutResult&& other) = delete;
+  LayoutResult() = delete;
 
-  ~NGLayoutResult() = default;
+  ~LayoutResult() = default;
 
-  const NGPhysicalFragment& PhysicalFragment() const {
+  const NGPhysicalFragment& GetPhysicalFragment() const {
     DCHECK(physical_fragment_);
     DCHECK_EQ(kSuccess, Status());
     return *physical_fragment_;
@@ -170,7 +169,7 @@
 
   // Called after subtree layout to make sure the fields for out-of-flow
   // positioned nodes are set.
-  void CopyMutableOutOfFlowData(const NGLayoutResult& previous_result) const;
+  void CopyMutableOutOfFlowData(const LayoutResult& previous_result) const;
 
   // Returns if we can use the first-tier OOF-positioned cache.
   bool CanUseOutOfFlowPositionedFirstTierCache() const {
@@ -270,8 +269,9 @@
   // In the above example the |BfcBlockOffset()| will be at 0px, where-as the
   // |LineBoxBfcBlockOffset()| will be at 20px.
   absl::optional<LayoutUnit> LineBoxBfcBlockOffset() const {
-    if (Status() != kSuccess || !PhysicalFragment().IsLineBox())
+    if (Status() != kSuccess || !GetPhysicalFragment().IsLineBox()) {
       return absl::nullopt;
+    }
 
     if (rare_data_) {
       if (absl::optional<LayoutUnit> offset =
@@ -541,11 +541,11 @@
     }
 
    private:
-    friend class NGLayoutResult;
-    MutableForOutOfFlow(const NGLayoutResult* layout_result)
-        : layout_result_(const_cast<NGLayoutResult*>(layout_result)) {}
+    friend class LayoutResult;
+    MutableForOutOfFlow(const LayoutResult* layout_result)
+        : layout_result_(const_cast<LayoutResult*>(layout_result)) {}
 
-    NGLayoutResult* layout_result_;
+    LayoutResult* layout_result_;
   };
 
   MutableForOutOfFlow GetMutableForOutOfFlow() const {
@@ -563,12 +563,11 @@
     }
 
    private:
-    friend class NGLayoutResult;
-    explicit MutableForLayoutBoxCachedResults(
-        const NGLayoutResult* layout_result)
-        : layout_result_(const_cast<NGLayoutResult*>(layout_result)) {}
+    friend class LayoutResult;
+    explicit MutableForLayoutBoxCachedResults(const LayoutResult* layout_result)
+        : layout_result_(const_cast<LayoutResult*>(layout_result)) {}
 
-    NGLayoutResult* layout_result_;
+    LayoutResult* layout_result_;
   };
 
   MutableForLayoutBoxCachedResults GetMutableForLayoutBoxCachedResults() const {
@@ -576,26 +575,26 @@
   }
 
 #if DCHECK_IS_ON()
-  void CheckSameForSimplifiedLayout(const NGLayoutResult&,
+  void CheckSameForSimplifiedLayout(const LayoutResult&,
                                     bool check_same_block_size = true,
                                     bool check_no_fragmentation = true) const;
 #endif
 
   using FragmentBuilderPassKey = base::PassKey<FragmentBuilder>;
   // This constructor is for a non-success status.
-  NGLayoutResult(FragmentBuilderPassKey, EStatus, FragmentBuilder*);
+  LayoutResult(FragmentBuilderPassKey, EStatus, FragmentBuilder*);
 
   // This constructor requires a non-null fragment and sets a success status.
   using BoxFragmentBuilderPassKey = base::PassKey<BoxFragmentBuilder>;
-  NGLayoutResult(BoxFragmentBuilderPassKey,
-                 const NGPhysicalFragment* physical_fragment,
-                 BoxFragmentBuilder*);
+  LayoutResult(BoxFragmentBuilderPassKey,
+               const NGPhysicalFragment* physical_fragment,
+               BoxFragmentBuilder*);
 
   using LineBoxFragmentBuilderPassKey = base::PassKey<LineBoxFragmentBuilder>;
   // This constructor requires a non-null fragment and sets a success status.
-  NGLayoutResult(LineBoxFragmentBuilderPassKey,
-                 const NGPhysicalFragment* physical_fragment,
-                 LineBoxFragmentBuilder*);
+  LayoutResult(LineBoxFragmentBuilderPassKey,
+               const NGPhysicalFragment* physical_fragment,
+               LineBoxFragmentBuilder*);
 
   void Trace(Visitor*) const;
 
@@ -603,7 +602,7 @@
   friend class MutableForOutOfFlow;
 
   static ExclusionSpace MergeExclusionSpaces(
-      const NGLayoutResult& other,
+      const LayoutResult& other,
       const ExclusionSpace& new_input_exclusion_space,
       LayoutUnit bfc_line_offset,
       LayoutUnit block_offset_delta);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
index 747f4a1..84be8e1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result_caching_test.cc
@@ -11,33 +11,33 @@
 namespace blink {
 namespace {
 
-// These tests exercise the caching logic of |NGLayoutResult|s. They are
+// These tests exercise the caching logic of |LayoutResult|s. They are
 // rendering tests which contain two children: "test" and "src".
 //
 // Both have layout initially performed on them, however the "src" will have a
 // different |ConstraintSpace| which is then used to test either a cache hit
 // or miss.
-class NGLayoutResultCachingTest : public RenderingTest {
+class LayoutResultCachingTest : public RenderingTest {
  protected:
-  NGLayoutResultCachingTest() {}
+  LayoutResultCachingTest() {}
 
-  const NGLayoutResult* TestCachedLayoutResultWithBreakToken(
+  const LayoutResult* TestCachedLayoutResultWithBreakToken(
       LayoutBox* box,
       const ConstraintSpace& constraint_space,
       const BlockBreakToken* break_token) {
     absl::optional<FragmentGeometry> fragment_geometry;
-    NGLayoutCacheStatus cache_status;
+    LayoutCacheStatus cache_status;
     return box->CachedLayoutResult(constraint_space, break_token, nullptr,
                                    nullptr, &fragment_geometry, &cache_status);
   }
 
-  const NGLayoutResult* TestCachedLayoutResult(
+  const LayoutResult* TestCachedLayoutResult(
       LayoutBox* box,
       const ConstraintSpace& constraint_space,
-      NGLayoutCacheStatus* out_cache_status = nullptr) {
+      LayoutCacheStatus* out_cache_status = nullptr) {
     absl::optional<FragmentGeometry> fragment_geometry;
-    NGLayoutCacheStatus cache_status;
-    const NGLayoutResult* result =
+    LayoutCacheStatus cache_status;
+    const LayoutResult* result =
         box->CachedLayoutResult(constraint_space, nullptr, nullptr, nullptr,
                                 &fragment_geometry, &cache_status);
     if (out_cache_status) {
@@ -47,7 +47,7 @@
   }
 };
 
-TEST_F(NGLayoutResultCachingTest, HitDifferentExclusionSpace) {
+TEST_F(LayoutResultCachingTest, HitDifferentExclusionSpace) {
   // Same BFC offset, different exclusion space.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -71,19 +71,19 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(result->BfcBlockOffset().value(), LayoutUnit(50));
   EXPECT_EQ(result->BfcLineOffset(), LayoutUnit());
 }
 
-TEST_F(NGLayoutResultCachingTest, HitDifferentBFCOffset) {
+TEST_F(LayoutResultCachingTest, HitDifferentBFCOffset) {
   // Different BFC offset, same exclusion space.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -111,13 +111,13 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(result->BfcBlockOffset().value(), LayoutUnit(40));
   EXPECT_EQ(result->BfcLineOffset(), LayoutUnit());
@@ -146,7 +146,7 @@
             BfcOffset(LayoutUnit(100), LayoutUnit::Max()));
 }
 
-TEST_F(NGLayoutResultCachingTest, HitDifferentBFCOffsetSameMarginStrut) {
+TEST_F(LayoutResultCachingTest, HitDifferentBFCOffsetSameMarginStrut) {
   // Different BFC offset, same margin-strut.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -165,17 +165,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissDescendantAboveBlockStart1) {
+TEST_F(LayoutResultCachingTest, MissDescendantAboveBlockStart1) {
   // Same BFC offset, different exclusion space, descendant above
   // block start.
   SetBodyInnerHTML(R"HTML(
@@ -202,17 +202,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissDescendantAboveBlockStart2) {
+TEST_F(LayoutResultCachingTest, MissDescendantAboveBlockStart2) {
   // Different BFC offset, same exclusion space, descendant above
   // block start.
   SetBodyInnerHTML(R"HTML(
@@ -239,17 +239,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitOOFDescendantAboveBlockStart) {
+TEST_F(LayoutResultCachingTest, HitOOFDescendantAboveBlockStart) {
   // Different BFC offset, same exclusion space, OOF-descendant above
   // block start.
   SetBodyInnerHTML(R"HTML(
@@ -276,17 +276,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitLineBoxDescendantAboveBlockStart) {
+TEST_F(LayoutResultCachingTest, HitLineBoxDescendantAboveBlockStart) {
   // Different BFC offset, same exclusion space, line-box descendant above
   // block start.
   SetBodyInnerHTML(R"HTML(
@@ -318,17 +318,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissFloatInitiallyIntruding1) {
+TEST_F(LayoutResultCachingTest, MissFloatInitiallyIntruding1) {
   // Same BFC offset, different exclusion space, float initially
   // intruding.
   SetBodyInnerHTML(R"HTML(
@@ -353,17 +353,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissFloatInitiallyIntruding2) {
+TEST_F(LayoutResultCachingTest, MissFloatInitiallyIntruding2) {
   // Different BFC offset, same exclusion space, float initially
   // intruding.
   SetBodyInnerHTML(R"HTML(
@@ -388,17 +388,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissFloatWillIntrude1) {
+TEST_F(LayoutResultCachingTest, MissFloatWillIntrude1) {
   // Same BFC offset, different exclusion space, float will intrude.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -422,17 +422,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissFloatWillIntrude2) {
+TEST_F(LayoutResultCachingTest, MissFloatWillIntrude2) {
   // Different BFC offset, same exclusion space, float will intrude.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -456,17 +456,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitPushedByFloats1) {
+TEST_F(LayoutResultCachingTest, HitPushedByFloats1) {
   // Same BFC offset, different exclusion space, pushed by floats.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -490,17 +490,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitPushedByFloats2) {
+TEST_F(LayoutResultCachingTest, HitPushedByFloats2) {
   // Different BFC offset, same exclusion space, pushed by floats.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -524,17 +524,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissPushedByFloats1) {
+TEST_F(LayoutResultCachingTest, MissPushedByFloats1) {
   // Same BFC offset, different exclusion space, pushed by floats.
   // Miss due to shrinking offset.
   SetBodyInnerHTML(R"HTML(
@@ -559,17 +559,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissPushedByFloats2) {
+TEST_F(LayoutResultCachingTest, MissPushedByFloats2) {
   // Different BFC offset, same exclusion space, pushed by floats.
   // Miss due to shrinking offset.
   SetBodyInnerHTML(R"HTML(
@@ -594,17 +594,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitDifferentRareData) {
+TEST_F(LayoutResultCachingTest, HitDifferentRareData) {
   // Same absolute fixed constraints.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -622,17 +622,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitPercentageMinWidth) {
+TEST_F(LayoutResultCachingTest, HitPercentageMinWidth) {
   // min-width calculates to different values, but doesn't change size.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -650,17 +650,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitFixedMinWidth) {
+TEST_F(LayoutResultCachingTest, HitFixedMinWidth) {
   // min-width is always larger than the available size.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -678,17 +678,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitShrinkToFit) {
+TEST_F(LayoutResultCachingTest, HitShrinkToFit) {
   SetBodyInnerHTML(R"HTML(
     <div style="display: flow-root; width: 300px; height: 100px;">
       <div id="test1" style="float: left;">
@@ -719,25 +719,25 @@
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
   // test1 was sized to its max-content size, passing an available size larger
   // than the fragment should hit the cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   result = TestCachedLayoutResult(test2, space, &cache_status);
   // test2 was sized to its min-content size in, passing an available size
   // smaller than the fragment should hit the cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissShrinkToFit) {
+TEST_F(LayoutResultCachingTest, MissShrinkToFit) {
   SetBodyInnerHTML(R"HTML(
     <div style="display: flow-root; width: 300px; height: 100px;">
       <div id="test1" style="float: left;">
@@ -790,39 +790,39 @@
   auto* src3 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src3"));
   auto* src4 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src4"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
   // test1 was sized to its max-content size, passing an available size smaller
   // than the fragment should miss the cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   result = TestCachedLayoutResult(test2, space, &cache_status);
   // test2 was sized to its min-content size, passing an available size
   // larger than the fragment should miss the cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 
   space = src3->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   result = TestCachedLayoutResult(test3, space, &cache_status);
   // test3 was sized to its min-content size, however it should miss the cache
   // as it has a %-min-size.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 
   space = src4->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   result = TestCachedLayoutResult(test4, space, &cache_status);
   // test4 was sized to its max-content size, however it should miss the cache
   // due to its margin.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitShrinkToFitSameIntrinsicSizes) {
+TEST_F(LayoutResultCachingTest, HitShrinkToFitSameIntrinsicSizes) {
   // We have a shrink-to-fit node, with the min, and max intrinsic sizes being
   // equal (the available size doesn't affect the final size).
   SetBodyInnerHTML(R"HTML(
@@ -846,17 +846,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitShrinkToFitDifferentParent) {
+TEST_F(LayoutResultCachingTest, HitShrinkToFitDifferentParent) {
   // The parent "bfc" node changes from shrink-to-fit, to a fixed width. But
   // these calculate as the same available space to the "test" element.
   SetBodyInnerHTML(R"HTML(
@@ -879,17 +879,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissQuirksModePercentageBasedChild) {
+TEST_F(LayoutResultCachingTest, MissQuirksModePercentageBasedChild) {
   // Quirks-mode %-block-size child.
   GetDocument().SetCompatibilityMode(Document::kQuirksMode);
   SetBodyInnerHTML(R"HTML(
@@ -912,17 +912,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitQuirksModePercentageBasedParentAndChild) {
+TEST_F(LayoutResultCachingTest, HitQuirksModePercentageBasedParentAndChild) {
   // Quirks-mode %-block-size parent *and* child. Here we mark the parent as
   // depending on %-block-size changes, however itself doesn't change in
   // height.
@@ -950,17 +950,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitStandardsModePercentageBasedChild) {
+TEST_F(LayoutResultCachingTest, HitStandardsModePercentageBasedChild) {
   // Standards-mode %-block-size child.
   SetBodyInnerHTML(R"HTML(
     <style>
@@ -982,17 +982,17 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, ChangeTableCellBlockSizeConstrainedness) {
+TEST_F(LayoutResultCachingTest, ChangeTableCellBlockSizeConstrainedness) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .table { display: table; width: 300px; }
@@ -1027,14 +1027,14 @@
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
   auto* src3 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src3"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
   // The first child has a fixed height, and shouldn't be affected by the cell
   // height.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1042,7 +1042,7 @@
   // The second child has overflow:auto and a percentage height, but its
   // intrinsic height is identical to its extrinsic height (when the cell has a
   // height). So it won't need layout, either.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src3->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1051,10 +1051,10 @@
   // intrinsic height is 0 (no children), so it matters whether the cell has a
   // height or not. We're only going to need simplified layout, though, since no
   // children will be affected by its height change.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsSimplifiedLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsSimplifiedLayout);
 }
 
-TEST_F(NGLayoutResultCachingTest, OptimisticFloatPlacementNoRelayout) {
+TEST_F(LayoutResultCachingTest, OptimisticFloatPlacementNoRelayout) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .root { display: flow-root; width: 300px; }
@@ -1078,7 +1078,7 @@
   EXPECT_EQ(space.ForcedBfcBlockOffset(), absl::nullopt);
 }
 
-TEST_F(NGLayoutResultCachingTest, SelfCollapsingShifting) {
+TEST_F(LayoutResultCachingTest, SelfCollapsingShifting) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 300px; height: 300px; }
@@ -1128,16 +1128,16 @@
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
   auto* src3 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src3"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // Case 1: We have a different set of constraints, but as the child has no
   // adjoining descendants it can be shifted anywhere.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1145,7 +1145,7 @@
 
   // Case 2: We have a different set of constraints, but the child has an
   // adjoining object and isn't "past" the floats - it can't be reused.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 
   space = src3->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1153,11 +1153,11 @@
 
   // Case 3: We have a different set of constraints, and adjoining descendants,
   // but have a position past where they might affect us.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, ClearancePastAdjoiningFloatsMovement) {
+TEST_F(LayoutResultCachingTest, ClearancePastAdjoiningFloatsMovement) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 300px; height: 300px; }
@@ -1199,26 +1199,26 @@
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // Case 1: We have forced clearance, but floats won't impact our children.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   result = TestCachedLayoutResult(test2, space, &cache_status);
 
   // Case 2: We have forced clearance, and floats will impact our children.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MarginStrutMovementSelfCollapsing) {
+TEST_F(LayoutResultCachingTest, MarginStrutMovementSelfCollapsing) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 300px; height: 300px; }
@@ -1258,16 +1258,16 @@
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // Case 1: We can safely re-use this fragment as it doesn't append anything
   // to the margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   // The "end" margin-strut should be updated.
@@ -1280,11 +1280,11 @@
 
   // Case 2: We can't re-use this fragment as it appended a non-zero value to
   // the margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MarginStrutMovementInFlow) {
+TEST_F(LayoutResultCachingTest, MarginStrutMovementInFlow) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 300px; height: 300px; }
@@ -1346,16 +1346,16 @@
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
   auto* src3 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src3"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // Case 1: We can safely re-use this fragment as it doesn't append anything
   // to the margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   space = src2->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1363,7 +1363,7 @@
 
   // Case 2: We can't re-use this fragment as it appended a non-zero value to
   // the margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 
   space = src3->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
@@ -1371,11 +1371,11 @@
 
   // Case 3: We can't re-use this fragment as a (inner) self-collapsing block
   // appended a non-zero value to the margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MarginStrutMovementPercentage) {
+TEST_F(LayoutResultCachingTest, MarginStrutMovementPercentage) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 300px; height: 300px; }
@@ -1399,20 +1399,20 @@
   auto* test1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test1"));
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // We can't re-use this fragment as it appended a non-zero value (50%) to the
   // margin-strut within the sub-tree.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitIsFixedBlockSizeIndefinite) {
+TEST_F(LayoutResultCachingTest, HitIsFixedBlockSizeIndefinite) {
   SetBodyInnerHTML(R"HTML(
     <div style="display: flex; width: 100px; height: 100px;">
       <div id="test1" style="flex-grow: 1; min-height: 100px;">
@@ -1429,21 +1429,21 @@
   auto* test1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test1"));
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // Even though the "align-items: stretch" will make the final fixed
   // block-size indefinite, we don't have any %-block-size children, so we can
   // hit the cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissIsFixedBlockSizeIndefinite) {
+TEST_F(LayoutResultCachingTest, MissIsFixedBlockSizeIndefinite) {
   SetBodyInnerHTML(R"HTML(
     <!DOCTYPE html>
     <div style="display: flex; width: 100px; height: 100px; align-items: start;">
@@ -1461,21 +1461,21 @@
   auto* test1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test1"));
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   // The "align-items: stretch" will make the final fixed block-size
   // indefinite, and we have a %-block-size child, so we need to miss the
   // cache.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitColumnFlexBoxMeasureAndLayout) {
+TEST_F(LayoutResultCachingTest, HitColumnFlexBoxMeasureAndLayout) {
   SetBodyInnerHTML(R"HTML(
     <!DOCTYPE html>
     <style>
@@ -1502,17 +1502,17 @@
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   // "src1" only had one "measure" pass performed, and should hit the "measure"
   // cache-slot for "test1".
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   EXPECT_EQ(space.CacheSlot(), LayoutResultCacheSlot::kMeasure);
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   // "src2" had both a "measure" and "layout" pass performed, and should hit
@@ -1521,11 +1521,11 @@
   result = TestCachedLayoutResult(test1, space, &cache_status);
 
   EXPECT_EQ(space.CacheSlot(), LayoutResultCacheSlot::kLayout);
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitRowFlexBoxMeasureAndLayout) {
+TEST_F(LayoutResultCachingTest, HitRowFlexBoxMeasureAndLayout) {
   SetBodyInnerHTML(R"HTML(
     <!DOCTYPE html>
     <style>
@@ -1554,17 +1554,17 @@
   auto* src1 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src1"));
   auto* src2 = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src2"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
 
   // "src1" only had one "measure" pass performed, and should hit the "measure"
   // cache-slot for "test1".
   ConstraintSpace space =
       src1->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test1, space, &cache_status);
 
   EXPECT_EQ(space.CacheSlot(), LayoutResultCacheSlot::kMeasure);
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 
   // "src2" had both a "measure" and "layout" pass performed, and should hit
@@ -1573,11 +1573,11 @@
   result = TestCachedLayoutResult(test1, space, &cache_status);
 
   EXPECT_EQ(space.CacheSlot(), LayoutResultCacheSlot::kLayout);
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitFlexLegacyImg) {
+TEST_F(LayoutResultCachingTest, HitFlexLegacyImg) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flex; flex-direction: column; width: 300px; }
@@ -1598,17 +1598,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitFlexLegacyGrid) {
+TEST_F(LayoutResultCachingTest, HitFlexLegacyGrid) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flex; flex-direction: column; width: 300px; }
@@ -1630,17 +1630,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitFlexDefiniteChange) {
+TEST_F(LayoutResultCachingTest, HitFlexDefiniteChange) {
   SetBodyInnerHTML(R"HTML(
     <div style="display: flex; flex-direction: column;">
       <div style="height: 200px;" id=target1>
@@ -1651,17 +1651,17 @@
 
   auto* target1 = To<LayoutBlock>(GetLayoutObjectByElementId("target1"));
 
-  const NGLayoutResult* result1 = target1->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure1 = target1->GetCachedMeasureResult();
+  const LayoutResult* result1 = target1->GetSingleCachedLayoutResult();
+  const LayoutResult* measure1 = target1->GetCachedMeasureResult();
   EXPECT_EQ(measure1->IntrinsicBlockSize(), 100);
-  EXPECT_EQ(result1->PhysicalFragment().Size().height, 200);
+  EXPECT_EQ(result1->GetPhysicalFragment().Size().height, 200);
 
   EXPECT_EQ(result1->GetConstraintSpaceForCaching().CacheSlot(),
             LayoutResultCacheSlot::kMeasure);
   EXPECT_EQ(result1, measure1);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitOrthogonalRoot) {
+TEST_F(LayoutResultCachingTest, HitOrthogonalRoot) {
   SetBodyInnerHTML(R"HTML(
     <style>
       span { display: inline-block; width: 20px; height: 250px }
@@ -1675,18 +1675,18 @@
 
   auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       target->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(target, space, &cache_status);
 
   // We should hit the cache using the same constraint space.
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, SimpleTable) {
+TEST_F(LayoutResultCachingTest, SimpleTable) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <td id="target1">abc</td>
@@ -1699,22 +1699,22 @@
 
   // Both "target1", and "target1" should have  only had one "measure" pass
   // performed.
-  const NGLayoutResult* result1 = target1->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure1 = target1->GetCachedMeasureResult();
+  const LayoutResult* result1 = target1->GetSingleCachedLayoutResult();
+  const LayoutResult* measure1 = target1->GetCachedMeasureResult();
   EXPECT_EQ(result1->GetConstraintSpaceForCaching().CacheSlot(),
             LayoutResultCacheSlot::kMeasure);
   EXPECT_NE(result1, nullptr);
   EXPECT_EQ(result1, measure1);
 
-  const NGLayoutResult* result2 = target2->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure2 = target2->GetCachedMeasureResult();
+  const LayoutResult* result2 = target2->GetSingleCachedLayoutResult();
+  const LayoutResult* measure2 = target2->GetCachedMeasureResult();
   EXPECT_EQ(result2->GetConstraintSpaceForCaching().CacheSlot(),
             LayoutResultCacheSlot::kMeasure);
   EXPECT_NE(result2, nullptr);
   EXPECT_EQ(result2, measure2);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTableCellMiddleAlignment) {
+TEST_F(LayoutResultCachingTest, MissTableCellMiddleAlignment) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <td id="target" style="vertical-align: middle;">abc</td>
@@ -1725,8 +1725,8 @@
   auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
 
   // "target" should be stretched, and miss the measure cache.
-  const NGLayoutResult* result = target->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure = target->GetCachedMeasureResult();
+  const LayoutResult* result = target->GetSingleCachedLayoutResult();
+  const LayoutResult* measure = target->GetCachedMeasureResult();
   EXPECT_NE(measure, nullptr);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(measure->GetConstraintSpaceForCaching().CacheSlot(),
@@ -1736,7 +1736,7 @@
   EXPECT_NE(result, measure);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTableCellBottomAlignment) {
+TEST_F(LayoutResultCachingTest, MissTableCellBottomAlignment) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <td id="target" style="vertical-align: bottom;">abc</td>
@@ -1747,8 +1747,8 @@
   auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
 
   // "target" should be stretched, and miss the measure cache.
-  const NGLayoutResult* result = target->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure = target->GetCachedMeasureResult();
+  const LayoutResult* result = target->GetSingleCachedLayoutResult();
+  const LayoutResult* measure = target->GetCachedMeasureResult();
   EXPECT_NE(measure, nullptr);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(measure->GetConstraintSpaceForCaching().CacheSlot(),
@@ -1758,7 +1758,7 @@
   EXPECT_NE(result, measure);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitTableCellBaselineAlignment) {
+TEST_F(LayoutResultCachingTest, HitTableCellBaselineAlignment) {
   SetBodyInnerHTML(R"HTML(
     <style>
       td { vertical-align: baseline; }
@@ -1772,15 +1772,15 @@
   auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
 
   // "target" should align to the baseline, but hit the cache.
-  const NGLayoutResult* result = target->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure = target->GetCachedMeasureResult();
+  const LayoutResult* result = target->GetSingleCachedLayoutResult();
+  const LayoutResult* measure = target->GetCachedMeasureResult();
   EXPECT_EQ(result->GetConstraintSpaceForCaching().CacheSlot(),
             LayoutResultCacheSlot::kMeasure);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(result, measure);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTableCellBaselineAlignment) {
+TEST_F(LayoutResultCachingTest, MissTableCellBaselineAlignment) {
   SetBodyInnerHTML(R"HTML(
     <style>
       td { vertical-align: baseline; }
@@ -1794,8 +1794,8 @@
   auto* target = To<LayoutBlock>(GetLayoutObjectByElementId("target"));
 
   // "target" should align to the baseline, but miss the cache.
-  const NGLayoutResult* result = target->GetSingleCachedLayoutResult();
-  const NGLayoutResult* measure = target->GetCachedMeasureResult();
+  const LayoutResult* result = target->GetSingleCachedLayoutResult();
+  const LayoutResult* measure = target->GetCachedMeasureResult();
   EXPECT_NE(measure, nullptr);
   EXPECT_NE(result, nullptr);
   EXPECT_EQ(measure->GetConstraintSpaceForCaching().CacheSlot(),
@@ -1805,7 +1805,7 @@
   EXPECT_NE(result, measure);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTablePercent) {
+TEST_F(LayoutResultCachingTest, MissTablePercent) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .bfc { display: flow-root; width: 100px; }
@@ -1829,17 +1829,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitTableRowAdd) {
+TEST_F(LayoutResultCachingTest, HitTableRowAdd) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tr><td>a</td><td>b</td></tr>
@@ -1853,17 +1853,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTableRowAdd) {
+TEST_F(LayoutResultCachingTest, MissTableRowAdd) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tr><td>longwordhere</td><td>b</td></tr>
@@ -1877,17 +1877,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitTableRowRemove) {
+TEST_F(LayoutResultCachingTest, HitTableRowRemove) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tr id="test"><td>text</td><td>more text</td></tr>
@@ -1901,17 +1901,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissTableRowRemove) {
+TEST_F(LayoutResultCachingTest, MissTableRowRemove) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tr id="test"><td>text</td><td>more text</td></tr>
@@ -1925,17 +1925,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitTableSectionAdd) {
+TEST_F(LayoutResultCachingTest, HitTableSectionAdd) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tbody><tr><td>a</td><td>b</td></tr></tbody>
@@ -1949,17 +1949,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitTableSectionRemove) {
+TEST_F(LayoutResultCachingTest, HitTableSectionRemove) {
   SetBodyInnerHTML(R"HTML(
     <table>
       <tbody id="test"><tr><td>text</td><td>more text</td></tr></tbody>
@@ -1973,17 +1973,17 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, FragmentainerSizeChange) {
+TEST_F(LayoutResultCachingTest, FragmentainerSizeChange) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; column-fill:auto; }
@@ -2000,49 +2000,49 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  const NGLayoutResult* test_result1 = test->GetCachedLayoutResult(nullptr);
+  const LayoutResult* test_result1 = test->GetCachedLayoutResult(nullptr);
   ASSERT_TRUE(test_result1);
   const ConstraintSpace& test_space1 =
       test_result1->GetConstraintSpaceForCaching();
   const auto* test_break_token1 =
-      To<BlockBreakToken>(test_result1->PhysicalFragment().GetBreakToken());
+      To<BlockBreakToken>(test_result1->GetPhysicalFragment().GetBreakToken());
   ASSERT_TRUE(test_break_token1);
-  const NGLayoutResult* test_result2 =
+  const LayoutResult* test_result2 =
       test->GetCachedLayoutResult(test_break_token1);
   ASSERT_TRUE(test_result2);
   const ConstraintSpace& test_space2 =
       test_result2->GetConstraintSpaceForCaching();
   const auto* test_break_token2 =
-      To<BlockBreakToken>(test_result2->PhysicalFragment().GetBreakToken());
+      To<BlockBreakToken>(test_result2->GetPhysicalFragment().GetBreakToken());
   ASSERT_TRUE(test_break_token2);
-  const NGLayoutResult* test_result3 =
+  const LayoutResult* test_result3 =
       test->GetCachedLayoutResult(test_break_token2);
   ASSERT_TRUE(test_result3);
   const ConstraintSpace& test_space3 =
       test_result3->GetConstraintSpaceForCaching();
-  EXPECT_FALSE(test_result3->PhysicalFragment().GetBreakToken());
+  EXPECT_FALSE(test_result3->GetPhysicalFragment().GetBreakToken());
 
-  const NGLayoutResult* src_result1 = src->GetCachedLayoutResult(nullptr);
+  const LayoutResult* src_result1 = src->GetCachedLayoutResult(nullptr);
   ASSERT_TRUE(src_result1);
   const ConstraintSpace& src_space1 =
       src_result1->GetConstraintSpaceForCaching();
   const auto* src_break_token1 =
-      To<BlockBreakToken>(src_result1->PhysicalFragment().GetBreakToken());
+      To<BlockBreakToken>(src_result1->GetPhysicalFragment().GetBreakToken());
   ASSERT_TRUE(src_break_token1);
-  const NGLayoutResult* src_result2 =
+  const LayoutResult* src_result2 =
       src->GetCachedLayoutResult(src_break_token1);
   ASSERT_TRUE(src_result2);
   const ConstraintSpace& src_space2 =
       src_result2->GetConstraintSpaceForCaching();
   const auto* src_break_token2 =
-      To<BlockBreakToken>(src_result2->PhysicalFragment().GetBreakToken());
+      To<BlockBreakToken>(src_result2->GetPhysicalFragment().GetBreakToken());
   ASSERT_TRUE(src_break_token2);
-  const NGLayoutResult* src_result3 =
+  const LayoutResult* src_result3 =
       src->GetCachedLayoutResult(src_break_token2);
   ASSERT_TRUE(src_result3);
   const ConstraintSpace& src_space3 =
       src_result3->GetConstraintSpaceForCaching();
-  EXPECT_FALSE(src_result3->PhysicalFragment().GetBreakToken());
+  EXPECT_FALSE(src_result3->GetPhysicalFragment().GetBreakToken());
 
   // If the extrinsic constraints are unchanged, hit the cache, even if
   // fragmented:
@@ -2060,7 +2060,7 @@
                                                     test_break_token2));
 }
 
-TEST_F(NGLayoutResultCachingTest, BlockOffsetChangeInFragmentainer) {
+TEST_F(LayoutResultCachingTest, BlockOffsetChangeInFragmentainer) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; column-fill:auto; height:100px; }
@@ -2109,7 +2109,7 @@
   EXPECT_FALSE(TestCachedLayoutResult(src, test3_space));
 }
 
-TEST_F(NGLayoutResultCachingTest, BfcRootBlockOffsetChangeInFragmentainer) {
+TEST_F(LayoutResultCachingTest, BfcRootBlockOffsetChangeInFragmentainer) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; column-fill:auto; height:100px; }
@@ -2158,7 +2158,7 @@
   EXPECT_FALSE(TestCachedLayoutResult(src, test3_space));
 }
 
-TEST_F(NGLayoutResultCachingTest, HitBlockOffsetUnchangedInFragmentainer) {
+TEST_F(LayoutResultCachingTest, HitBlockOffsetUnchangedInFragmentainer) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; column-fill:auto; height:100px; }
@@ -2179,19 +2179,19 @@
   auto* test = To<LayoutBlockFlow>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlockFlow>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ASSERT_NE(src->GetSingleCachedLayoutResult(), nullptr);
   ASSERT_NE(test->GetSingleCachedLayoutResult(), nullptr);
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, HitNewFormattingContextInFragmentainer) {
+TEST_F(LayoutResultCachingTest, HitNewFormattingContextInFragmentainer) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; }
@@ -2210,20 +2210,20 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ASSERT_NE(src->GetSingleCachedLayoutResult(), nullptr);
   ASSERT_NE(test->GetSingleCachedLayoutResult(), nullptr);
   const ConstraintSpace& space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
   EXPECT_TRUE(space.IsInitialColumnBalancingPass());
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kHit);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kHit);
   EXPECT_NE(result, nullptr);
 }
 
-TEST_F(NGLayoutResultCachingTest, MissMonolithicChangeInFragmentainer) {
+TEST_F(LayoutResultCachingTest, MissMonolithicChangeInFragmentainer) {
   SetBodyInnerHTML(R"HTML(
     <style>
       .multicol { columns:2; column-fill:auto; height:100px; }
@@ -2253,7 +2253,7 @@
   EXPECT_FALSE(TestCachedLayoutResult(test, src_space));
 }
 
-TEST_F(NGLayoutResultCachingTest, MissGridIncorrectIntrinsicSize) {
+TEST_F(LayoutResultCachingTest, MissGridIncorrectIntrinsicSize) {
   SetBodyInnerHTML(R"HTML(
     <!DOCTYPE html>
     <div style="display: flex; width: 100px; height: 200px; align-items: stretch;">
@@ -2271,13 +2271,13 @@
   auto* test = To<LayoutBlock>(GetLayoutObjectByElementId("test"));
   auto* src = To<LayoutBlock>(GetLayoutObjectByElementId("src"));
 
-  NGLayoutCacheStatus cache_status;
+  LayoutCacheStatus cache_status;
   ConstraintSpace space =
       src->GetSingleCachedLayoutResult()->GetConstraintSpaceForCaching();
-  const NGLayoutResult* result =
+  const LayoutResult* result =
       TestCachedLayoutResult(test, space, &cache_status);
 
-  EXPECT_EQ(cache_status, NGLayoutCacheStatus::kNeedsLayout);
+  EXPECT_EQ(cache_status, LayoutCacheStatus::kNeedsLayout);
   EXPECT_EQ(result, nullptr);
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
index 9d69dff..ba86765f 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -28,7 +28,7 @@
                                   LengthResolveType type,
                                   const ConstraintSpace& new_space,
                                   const ConstraintSpace& old_space,
-                                  const NGLayoutResult& layout_result) {
+                                  const LayoutResult& layout_result) {
   DCHECK_EQ(new_space.InlineAutoBehavior(), old_space.InlineAutoBehavior());
 
   bool is_unspecified =
@@ -76,7 +76,7 @@
 bool BlockSizeMayChange(const BlockNode& node,
                         const ConstraintSpace& new_space,
                         const ConstraintSpace& old_space,
-                        const NGLayoutResult& layout_result) {
+                        const LayoutResult& layout_result) {
   DCHECK_EQ(new_space.IsFixedBlockSize(), old_space.IsFixedBlockSize());
   DCHECK_EQ(new_space.IsInitialBlockSizeIndefinite(),
             old_space.IsInitialBlockSizeIndefinite());
@@ -100,7 +100,7 @@
       return true;
     // We only need to check if the PercentageResolutionBlockSizes match if the
     // layout result has explicitly marked itself as dependent.
-    if (layout_result.PhysicalFragment().DependsOnPercentageBlockSize()) {
+    if (layout_result.GetPhysicalFragment().DependsOnPercentageBlockSize()) {
       if (new_space.PercentageResolutionBlockSize() !=
           old_space.PercentageResolutionBlockSize())
         return true;
@@ -119,7 +119,7 @@
 bool SizeMayChange(const BlockNode& node,
                    const ConstraintSpace& new_space,
                    const ConstraintSpace& old_space,
-                   const NGLayoutResult& layout_result) {
+                   const LayoutResult& layout_result) {
   DCHECK_EQ(new_space.IsFixedInlineSize(), old_space.IsFixedInlineSize());
   DCHECK_EQ(new_space.BlockAutoBehavior(), old_space.BlockAutoBehavior());
 
@@ -168,30 +168,30 @@
 }
 
 // Given the pre-computed |fragment_geometry| calcuates the
-// |NGLayoutCacheStatus| based on this sizing information. Returns:
-//  - |NGLayoutCacheStatus::kNeedsLayout| if the |new_space| will produce a
+// |LayoutCacheStatus| based on this sizing information. Returns:
+//  - |LayoutCacheStatus::kNeedsLayout| if the |new_space| will produce a
 //    different sized fragment, or if any %-block-size children will change
 //    size.
-//  - |NGLayoutCacheStatus::kNeedsSimplifiedLayout| if the block-size of the
+//  - |LayoutCacheStatus::kNeedsSimplifiedLayout| if the block-size of the
 //    fragment will change, *without* affecting any descendants (no descendants
 //    have %-block-sizes).
-//  - |NGLayoutCacheStatus::kHit| otherwise.
-NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
+//  - |LayoutCacheStatus::kHit| otherwise.
+LayoutCacheStatus CalculateSizeBasedLayoutCacheStatusWithGeometry(
     const BlockNode& node,
     const FragmentGeometry& fragment_geometry,
-    const NGLayoutResult& layout_result,
+    const LayoutResult& layout_result,
     const ConstraintSpace& new_space,
     const ConstraintSpace& old_space) {
   const ComputedStyle& style = node.Style();
-  const NGPhysicalBoxFragment& physical_fragment =
-      To<NGPhysicalBoxFragment>(layout_result.PhysicalFragment());
+  const auto& physical_fragment =
+      To<NGPhysicalBoxFragment>(layout_result.GetPhysicalFragment());
   LogicalBoxFragment fragment(style.GetWritingDirection(), physical_fragment);
 
   if (fragment_geometry.border_box_size.inline_size != fragment.InlineSize())
-    return NGLayoutCacheStatus::kNeedsLayout;
+    return LayoutCacheStatus::kNeedsLayout;
 
   if (style.MayHavePadding() && fragment_geometry.padding != fragment.Padding())
-    return NGLayoutCacheStatus::kNeedsLayout;
+    return LayoutCacheStatus::kNeedsLayout;
 
   // Tables are special - we can't determine the final block-size ahead of time
   // (or based on the previous intrinsic size).
@@ -203,8 +203,8 @@
   if (node.IsTable()) {
     if (!new_space.AreBlockSizeConstraintsEqual(old_space) ||
         BlockSizeMayChange(node, new_space, old_space, layout_result))
-      return NGLayoutCacheStatus::kNeedsLayout;
-    return NGLayoutCacheStatus::kHit;
+      return LayoutCacheStatus::kNeedsLayout;
+    return LayoutCacheStatus::kHit;
   }
 
   LayoutUnit block_size = fragment_geometry.border_box_size.block_size;
@@ -239,7 +239,7 @@
     // the new block-size.
     //
     // TODO(ikilpatrick): Similar to %-block-size descendants we could store a
-    // bit on the |NGLayoutResult| which indicates if it had a child which
+    // bit on the |LayoutResult| which indicates if it had a child which
     // sized itself based on the parent's block-size.
     // We should consider this optimization if we are missing this cache often
     // within this branch (and could have re-used the result).
@@ -276,7 +276,7 @@
         intrinsic_block_size, fragment_geometry.border_box_size.inline_size);
 
     if (block_size == kIndefiniteSize)
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
   }
 
   bool is_block_size_equal = block_size == fragment.BlockSize();
@@ -284,29 +284,29 @@
   if (!is_block_size_equal) {
     // Only block-flow supports changing the block-size for simplified layout.
     if (!node.IsBlockFlow() || node.IsCustom()) {
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
     }
 
     // Fieldsets stretch their content to the final block-size, which might
     // affect scrollbars.
     if (node.IsFieldsetContainer())
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
 
     if (node.IsBlockFlow() && style.AlignContentBlockCenter()) {
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
     }
 
     // If we are the document or body element in quirks mode, changing our size
     // means that a scrollbar was added/removed. Require full layout.
     if (node.IsQuirkyAndFillsViewport())
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
 
     // If a block (within a formatting-context) changes to/from an empty-block,
     // margins may collapse through this node, requiring full layout. We
     // approximate this check by checking if the block-size is/was zero.
     if (!physical_fragment.IsFormattingContextRoot() &&
         !block_size != !fragment.BlockSize())
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
   }
 
   const bool has_descendant_that_depends_on_percentage_block_size =
@@ -325,7 +325,7 @@
   if (is_old_initial_block_size_indefinite !=
       is_initial_block_size_indefinite) {
     if (node.IsGrid() || has_descendant_that_depends_on_percentage_block_size)
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
   }
 
   if (has_descendant_that_depends_on_percentage_block_size) {
@@ -333,7 +333,7 @@
     // block-size we'll affect any descendant that depends on the resulting
     // percentage block-size.
     if (!is_block_size_equal && !is_initial_block_size_indefinite)
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
 
     DCHECK(is_block_size_equal || is_initial_block_size_indefinite);
 
@@ -353,10 +353,10 @@
       DCHECK(is_old_initial_block_size_indefinite);
       if (new_space.PercentageResolutionBlockSize() !=
           old_space.PercentageResolutionBlockSize())
-        return NGLayoutCacheStatus::kNeedsLayout;
+        return LayoutCacheStatus::kNeedsLayout;
       if (new_space.ReplacedPercentageResolutionBlockSize() !=
           old_space.ReplacedPercentageResolutionBlockSize())
-        return NGLayoutCacheStatus::kNeedsLayout;
+        return LayoutCacheStatus::kNeedsLayout;
     }
   }
 
@@ -388,26 +388,26 @@
         // If we only have an old alignment baseline set, we need layout, as we
         // can't determine where the un-adjusted baseline is.
         if (!new_alignment_baseline && old_alignment_baseline)
-          return NGLayoutCacheStatus::kNeedsLayout;
+          return LayoutCacheStatus::kNeedsLayout;
 
         // We've been provided a new alignment baseline, just check that it
         // matches the previously generated baseline.
         if (!old_alignment_baseline) {
           if (*new_alignment_baseline != physical_fragment.FirstBaseline())
-            return NGLayoutCacheStatus::kNeedsLayout;
+            return LayoutCacheStatus::kNeedsLayout;
           break;
         }
 
         // If the alignment baselines differ at this stage, we need layout.
         if (*new_alignment_baseline != *old_alignment_baseline)
-          return NGLayoutCacheStatus::kNeedsLayout;
+          return LayoutCacheStatus::kNeedsLayout;
         break;
       }
       case EVerticalAlign::kMiddle:
       case EVerticalAlign::kBottom:
         // 'middle', and 'bottom' vertical alignment depend on the block-size.
         if (!is_block_size_equal)
-          return NGLayoutCacheStatus::kNeedsLayout;
+          return LayoutCacheStatus::kNeedsLayout;
         break;
     }
   } else {
@@ -421,7 +421,7 @@
       case BlockContentAlignment::kUnsafeEnd:
       case BlockContentAlignment::kSafeEnd:
         if (!is_block_size_equal) {
-          return NGLayoutCacheStatus::kNeedsLayout;
+          return LayoutCacheStatus::kNeedsLayout;
         }
         break;
     }
@@ -431,14 +431,14 @@
   // ourselves without affecting any of our children.
   // In that case we may be able to perform "simplified" layout.
   DCHECK(!node.IsTable());
-  return is_block_size_equal ? NGLayoutCacheStatus::kHit
-                             : NGLayoutCacheStatus::kNeedsSimplifiedLayout;
+  return is_block_size_equal ? LayoutCacheStatus::kHit
+                             : LayoutCacheStatus::kNeedsSimplifiedLayout;
 }
 
 bool IntrinsicSizeWillChange(
     const BlockNode& node,
     const BlockBreakToken* break_token,
-    const NGLayoutResult& cached_layout_result,
+    const LayoutResult& cached_layout_result,
     const ConstraintSpace& new_space,
     absl::optional<FragmentGeometry>* fragment_geometry) {
   const ComputedStyle& style = node.Style();
@@ -452,7 +452,7 @@
 
   LayoutUnit inline_size =
       LogicalFragment(style.GetWritingDirection(),
-                      cached_layout_result.PhysicalFragment())
+                      cached_layout_result.GetPhysicalFragment())
           .InlineSize();
 
   if ((*fragment_geometry)->border_box_size.inline_size != inline_size)
@@ -463,36 +463,36 @@
 
 }  // namespace
 
-NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatus(
+LayoutCacheStatus CalculateSizeBasedLayoutCacheStatus(
     const BlockNode& node,
     const BlockBreakToken* break_token,
-    const NGLayoutResult& cached_layout_result,
+    const LayoutResult& cached_layout_result,
     const ConstraintSpace& new_space,
     absl::optional<FragmentGeometry>* fragment_geometry) {
-  DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(cached_layout_result.Status(), LayoutResult::kSuccess);
 
   const ConstraintSpace& old_space =
       cached_layout_result.GetConstraintSpaceForCaching();
 
   if (!new_space.MaySkipLayout(old_space))
-    return NGLayoutCacheStatus::kNeedsLayout;
+    return LayoutCacheStatus::kNeedsLayout;
 
   if (new_space.AreInlineSizeConstraintsEqual(old_space) &&
       new_space.AreBlockSizeConstraintsEqual(old_space)) {
     // It is possible that our intrinsic size has changed, check for that here.
     if (IntrinsicSizeWillChange(node, break_token, cached_layout_result,
                                 new_space, fragment_geometry))
-      return NGLayoutCacheStatus::kNeedsLayout;
+      return LayoutCacheStatus::kNeedsLayout;
 
     // We don't have to check our style if we know the constraint space sizes
     // will remain the same.
     if (new_space.AreSizesEqual(old_space))
-      return NGLayoutCacheStatus::kHit;
+      return LayoutCacheStatus::kHit;
 
     // TODO(ikilpatrick): Always miss the cache for tables whose block
     // size-constraints change.
     if (!SizeMayChange(node, new_space, old_space, cached_layout_result))
-      return NGLayoutCacheStatus::kHit;
+      return LayoutCacheStatus::kHit;
   }
 
   if (!*fragment_geometry) {
@@ -505,12 +505,12 @@
 }
 
 bool MaySkipLayoutWithinBlockFormattingContext(
-    const NGLayoutResult& cached_layout_result,
+    const LayoutResult& cached_layout_result,
     const ConstraintSpace& new_space,
     absl::optional<LayoutUnit>* bfc_block_offset,
     LayoutUnit* block_offset_delta,
     MarginStrut* end_margin_strut) {
-  DCHECK_EQ(cached_layout_result.Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(cached_layout_result.Status(), LayoutResult::kSuccess);
   DCHECK(bfc_block_offset);
   DCHECK(block_offset_delta);
   DCHECK(end_margin_strut);
@@ -568,7 +568,7 @@
     return false;
 
   const auto& physical_fragment =
-      To<NGPhysicalBoxFragment>(cached_layout_result.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(cached_layout_result.GetPhysicalFragment());
 
   // Check we have a descendant that *may* be positioned above the block-start
   // edge. We abort if either the old or new space has floats, as we don't keep
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
index ba53060..46a59ec 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.h
@@ -11,34 +11,34 @@
 namespace blink {
 
 class ConstraintSpace;
-class NGLayoutResult;
+class LayoutResult;
 struct MarginStrut;
 
-// NGLayoutCacheStatus indicates what type of cache hit/miss occurred. For
+// LayoutCacheStatus indicates what type of cache hit/miss occurred. For
 // various types of misses we may be able to perform less work than a full
 // layout.
 //
 // See |SimplifiedLayoutAlgorithm| for details about the
 // |kNeedsSimplifiedLayout| cache miss type.
-enum class NGLayoutCacheStatus {
+enum class LayoutCacheStatus {
   kHit,                    // Cache hit, no additional work required.
   kNeedsLayout,            // Cache miss, full layout required.
   kNeedsSimplifiedLayout,  // Cache miss, simplified layout required.
   kCanReuseLines           // Cache miss, may be possible to reuse lines.
 };
 
-// Calculates the |NGLayoutCacheStatus| based on sizing information. Returns:
-//  - |NGLayoutCacheStatus::kHit| if the size will be the same as
+// Calculates the |LayoutCacheStatus| based on sizing information. Returns:
+//  - |LayoutCacheStatus::kHit| if the size will be the same as
 //    |cached_layout_result|, and therefore might be able to skip layout.
-//  - |NGLayoutCacheStatus::kNeedsSimplifiedLayout| if a simplified layout may
+//  - |LayoutCacheStatus::kNeedsSimplifiedLayout| if a simplified layout may
 //    be possible (just based on the sizing information at this point).
-//  - |NGLayoutCacheStatus::kNeedsLayout| if a full layout is required.
+//  - |LayoutCacheStatus::kNeedsLayout| if a full layout is required.
 //
 // May pre-compute the |fragment_geometry| while calculating this status.
-NGLayoutCacheStatus CalculateSizeBasedLayoutCacheStatus(
+LayoutCacheStatus CalculateSizeBasedLayoutCacheStatus(
     const BlockNode& node,
     const BlockBreakToken* break_token,
-    const NGLayoutResult& cached_layout_result,
+    const LayoutResult& cached_layout_result,
     const ConstraintSpace& new_space,
     absl::optional<FragmentGeometry>* fragment_geometry);
 
@@ -54,7 +54,7 @@
 // If this function returns false, |bfc_block_offset|, |block_offset_delta|,
 // and |end_margin_strut| are in an undefined state and should not be used.
 bool MaySkipLayoutWithinBlockFormattingContext(
-    const NGLayoutResult& cached_layout_result,
+    const LayoutResult& cached_layout_result,
     const ConstraintSpace& new_space,
     absl::optional<LayoutUnit>* bfc_block_offset,
     LayoutUnit* block_offset_delta,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 8d143966..b4b68c9 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -475,8 +475,9 @@
   // OOF fragmentation depends on LayoutBox data being up-to-date, which isn't
   // the case if side-effects are disabled. So we cannot safely do anything
   // here.
-  if (NGDisableSideEffectsScope::IsDisabled())
+  if (DisableLayoutSideEffectsScope::IsDisabled()) {
     return;
+  }
 
   if (!column_balancing_info &&
       (!container_builder_->IsBlockFragmentationContextRoot() ||
@@ -972,7 +973,7 @@
             node_info,
             CalculateOffset(node_info, /* is_first_run */ false,
                             needs_anchor_queries ? &*anchor_queries : nullptr)};
-        const NGLayoutResult* result = LayoutOOFNode(node_to_layout);
+        const LayoutResult* result = LayoutOOFNode(node_to_layout);
         PhysicalBoxStrut physical_margins =
             node_to_layout.offset_info.node_dimensions.margins
                 .ConvertToPhysical(
@@ -989,8 +990,9 @@
         }
         if (needs_anchor_queries) {
           DCHECK(anchor_queries);
-          if (result->PhysicalFragment().HasAnchorQueryToPropagate())
+          if (result->GetPhysicalFragment().HasAnchorQueryToPropagate()) {
             anchor_queries->SetChildren(container_builder_->Children(), items);
+          }
         }
       } else {
         container_builder_->AddOutOfFlowDescendant(candidate);
@@ -1250,12 +1252,14 @@
     LayoutBox& box = *last_fragment_with_fragmentainer->MutableOwnerLayoutBox();
     wtf_size_t fragment_count = box.PhysicalFragmentCount();
     DCHECK_GE(fragment_count, 1u);
-    const NGLayoutResult* old_result = nullptr;
+    const LayoutResult* old_result = nullptr;
     wtf_size_t fragment_idx = fragment_count - 1;
     do {
       old_result = box.GetLayoutResult(fragment_idx);
-      if (&old_result->PhysicalFragment() == last_fragment_with_fragmentainer)
+      if (&old_result->GetPhysicalFragment() ==
+          last_fragment_with_fragmentainer) {
         break;
+      }
       DCHECK_GT(fragment_idx, 0u);
       fragment_idx--;
     } while (true);
@@ -1276,7 +1280,7 @@
     algorithm.CloneOldChildren();
 
     WritingModeConverter converter(constraint_space.GetWritingDirection(),
-                                   old_result->PhysicalFragment().Size());
+                                   old_result->GetPhysicalFragment().Size());
     LayoutUnit additional_column_block_size;
     // Then append the new fragmentainers.
     for (wtf_size_t i = old_fragment_count; i < new_fragment_count; i++) {
@@ -1294,7 +1298,7 @@
 
     // Create a new multicol container fragment and replace all references to
     // the old one with this new one.
-    const NGLayoutResult* new_result =
+    const LayoutResult* new_result =
         algorithm.CreateResultAfterManualChildLayout();
     ReplaceFragment(std::move(new_result), *last_fragment_with_fragmentainer,
                     fragment_idx);
@@ -1692,7 +1696,7 @@
                   oof_node.requires_content_before_breaking);
 }
 
-const NGLayoutResult* OutOfFlowLayoutPart::LayoutOOFNode(
+const LayoutResult* OutOfFlowLayoutPart::LayoutOOFNode(
     NodeToLayout& oof_node_to_layout,
     const ConstraintSpace* fragmentainer_constraint_space,
     bool is_last_fragmentainer_so_far) {
@@ -1704,7 +1708,7 @@
   }
 
   BoxStrut scrollbars_before = ComputeScrollbarsForNonAnonymous(node_info.node);
-  const NGLayoutResult* layout_result =
+  const LayoutResult* layout_result =
       Layout(oof_node_to_layout, fragmentainer_constraint_space,
              is_last_fragmentainer_so_far);
 
@@ -1883,7 +1887,7 @@
   // Note: Only check for cache results if this is our first layout pass.
   if (is_first_run && !try_fit_available_space && allow_first_tier_oof_cache_ &&
       !node_info.inline_container) {
-    if (const NGLayoutResult* cached_result =
+    if (const LayoutResult* cached_result =
             node_info.node.CachedLayoutResultForOutOfFlowPositioned(
                 container_content_size_in_candidate_writing_mode)) {
       OffsetInfo offset_info;
@@ -2113,13 +2117,13 @@
   return offset_info;
 }
 
-const NGLayoutResult* OutOfFlowLayoutPart::Layout(
+const LayoutResult* OutOfFlowLayoutPart::Layout(
     const NodeToLayout& oof_node_to_layout,
     const ConstraintSpace* fragmentainer_constraint_space,
     bool is_last_fragmentainer_so_far) {
   const OffsetInfo& offset_info = oof_node_to_layout.offset_info;
 
-  const NGLayoutResult* layout_result = offset_info.initial_layout_result;
+  const LayoutResult* layout_result = offset_info.initial_layout_result;
   // Reset the layout result computed earlier to allow fragmentation in the next
   // layout pass, if needed. Also do this if we're inside repeatable content, as
   // the pre-computed layout result is unusable then.
@@ -2136,7 +2140,7 @@
                          is_last_fragmentainer_so_far);
   }
 
-  DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
 
   layout_result->GetMutableForOutOfFlow().SetOutOfFlowInsetsForGetComputedStyle(
       offset_info.insets_for_get_computed_style,
@@ -2182,7 +2186,7 @@
 //    container's available size.
 // 2. To compute final fragment, when block size is known from the absolute
 //    position calculation.
-const NGLayoutResult* OutOfFlowLayoutPart::GenerateFragment(
+const LayoutResult* OutOfFlowLayoutPart::GenerateFragment(
     const NodeToLayout& oof_node_to_layout,
     const ConstraintSpace* fragmentainer_constraint_space,
     bool is_last_fragmentainer_so_far) {
@@ -2367,9 +2371,9 @@
     bool* has_actual_break_inside,
     SimplifiedOofLayoutAlgorithm* algorithm,
     HeapVector<NodeToLayout>* fragmented_descendants) {
-  const NGLayoutResult* result = LayoutOOFNode(descendant, fragmentainer_space,
-                                               is_last_fragmentainer_so_far);
-  DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess);
+  const LayoutResult* result = LayoutOOFNode(descendant, fragmentainer_space,
+                                             is_last_fragmentainer_so_far);
+  DCHECK_EQ(result->Status(), LayoutResult::kSuccess);
 
   // Apply the relative positioned offset now that fragmentation is complete.
   LogicalOffset oof_offset = result->OutOfFlowPositionedOffset();
@@ -2421,7 +2425,7 @@
   }
 
   const auto& physical_fragment =
-      To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
   const BlockBreakToken* break_token = physical_fragment.GetBreakToken();
   if (break_token) {
     // We must continue layout in the next fragmentainer. Update any information
@@ -2472,9 +2476,9 @@
   LayoutUnit containing_block_adjustment =
       container_builder_->BlockOffsetAdjustmentForFragmentainer(
           fragmentainer_consumed_block_size_);
-  if (result->PhysicalFragment().NeedsOOFPositionedInfoPropagation()) {
+  if (result->GetPhysicalFragment().NeedsOOFPositionedInfoPropagation()) {
     container_builder_->PropagateOOFPositionedInfo(
-        result->PhysicalFragment(), oof_offset, relative_offset,
+        result->GetPhysicalFragment(), oof_offset, relative_offset,
         offset_adjustment,
         /* inline_container */ nullptr, containing_block_adjustment,
         &descendant.node_info.containing_block,
@@ -2524,11 +2528,11 @@
     return;
 
   if (create_new_fragment) {
-    const NGLayoutResult* new_result = algorithm->Layout();
-    container_builder_->AddChild(new_result->PhysicalFragment(), offset);
+    const LayoutResult* new_result = algorithm->Layout();
+    container_builder_->AddChild(new_result->GetPhysicalFragment(), offset);
   } else {
-    const NGLayoutResult* new_result = algorithm->Layout();
-    const NGPhysicalFragment* new_fragment = &new_result->PhysicalFragment();
+    const LayoutResult* new_result = algorithm->Layout();
+    const NGPhysicalFragment* new_fragment = &new_result->GetPhysicalFragment();
     container_builder_->ReplaceChild(index, *new_fragment, offset);
 
     if (multicol_children_ && index < multicol_children_->size()) {
@@ -2703,7 +2707,7 @@
 }
 
 void OutOfFlowLayoutPart::ReplaceFragment(
-    const NGLayoutResult* new_result,
+    const LayoutResult* new_result,
     const NGPhysicalBoxFragment& old_fragment,
     wtf_size_t index) {
   // Replace the LayoutBox entry.
@@ -2756,7 +2760,7 @@
          parent.GetMutableChildrenForOutOfFlow().Children()) {
       if (child_link.fragment != &old_fragment)
         continue;
-      child_link.fragment = &new_result->PhysicalFragment();
+      child_link.fragment = &new_result->GetPhysicalFragment();
       return true;
     }
     return false;
@@ -2786,7 +2790,7 @@
         // an OOF inside.
         if (FragmentItems::ReplaceBoxFragment(
                 old_fragment,
-                To<NGPhysicalBoxFragment>(new_result->PhysicalFragment()),
+                To<NGPhysicalBoxFragment>(new_result->GetPhysicalFragment()),
                 parent_fragment)) {
           return;
         }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
index 6ff88d6..fde21b3a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -26,7 +26,7 @@
 class BlockBreakToken;
 class LayoutBox;
 class LayoutObject;
-class NGLayoutResult;
+class LayoutResult;
 template <typename OffsetType>
 class OofContainingBlock;
 class SimplifiedOofLayoutAlgorithm;
@@ -205,7 +205,7 @@
     // layout result if we needed to know the size in order to calculate the
     // offset. If an initial result is set, it will either be re-used or
     // replaced in the final layout pass.
-    Member<const NGLayoutResult> initial_layout_result;
+    Member<const LayoutResult> initial_layout_result;
     // The |block_estimate| is wrt. the candidate's writing mode.
     absl::optional<LayoutUnit> block_estimate;
     LogicalOofDimensions node_dimensions;
@@ -305,7 +305,7 @@
 
   NodeInfo SetupNodeInfo(const LogicalOofPositionedNode& oof_node);
 
-  const NGLayoutResult* LayoutOOFNode(
+  const LayoutResult* LayoutOOFNode(
       NodeToLayout& oof_node_to_layout,
       const ConstraintSpace* fragmentainer_constraint_space = nullptr,
       bool is_last_fragmentainer_so_far = false);
@@ -328,14 +328,14 @@
       bool is_first_run,
       NonOverflowingScrollRange* out_scroll_range);
 
-  const NGLayoutResult* Layout(
+  const LayoutResult* Layout(
       const NodeToLayout& oof_node_to_layout,
       const ConstraintSpace* fragmentainer_constraint_space,
       bool is_last_fragmentainer_so_far);
 
   bool IsContainingBlockForCandidate(const LogicalOofPositionedNode&);
 
-  const NGLayoutResult* GenerateFragment(
+  const LayoutResult* GenerateFragment(
       const NodeToLayout& oof_node_to_layout,
       const ConstraintSpace* fragmentainer_constraint_space,
       bool is_last_fragmentainer_so_far);
@@ -382,7 +382,7 @@
       wtf_size_t* start_index,
       LogicalOffset* offset) const;
 
-  void ReplaceFragment(const NGLayoutResult* new_result,
+  void ReplaceFragment(const LayoutResult* new_result,
                        const NGPhysicalBoxFragment& old_fragment,
                        wtf_size_t index);
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
index 9045319..5ece7a55 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
@@ -84,10 +84,11 @@
   // Test whether the oof fragments have been collected at NG->Legacy boundary.
   Element* rel = GetDocument().getElementById(AtomicString("rel"));
   auto* block_flow = To<LayoutBlockFlow>(rel->GetLayoutObject());
-  const NGLayoutResult* result = block_flow->GetSingleCachedLayoutResult();
+  const LayoutResult* result = block_flow->GetSingleCachedLayoutResult();
   EXPECT_TRUE(result);
-  EXPECT_EQ(result->PhysicalFragment().OutOfFlowPositionedDescendants().size(),
-            2u);
+  EXPECT_EQ(
+      result->GetPhysicalFragment().OutOfFlowPositionedDescendants().size(),
+      2u);
 
   // Test the final result.
   Element* fixed_1 = GetDocument().getElementById(AtomicString("fixed1"));
diff --git a/third_party/blink/renderer/core/layout/ng/ng_outline_type.h b/third_party/blink/renderer/core/layout/ng/ng_outline_type.h
index a4b82ad..1d69de8 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_outline_type.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_outline_type.h
@@ -8,19 +8,19 @@
 namespace blink {
 
 // Outline styles
-enum class NGOutlineType {
-  kDontIncludeBlockVisualOverflow,       // Standard outline
-  kIncludeBlockVisualOverflow,           // Focus outline
-  kIncludeBlockVisualOverflowForAnchor,  // Focus outline for anchor
+enum class OutlineType {
+  kDontIncludeBlockInkOverflow,       // Standard outline
+  kIncludeBlockInkOverflow,           // Focus outline
+  kIncludeBlockInkOverflowForAnchor,  // Focus outline for anchor
 };
 
-inline bool ShouldIncludeBlockVisualOverflow(NGOutlineType type) {
-  return type == NGOutlineType::kIncludeBlockVisualOverflow ||
-         type == NGOutlineType::kIncludeBlockVisualOverflowForAnchor;
+inline bool ShouldIncludeBlockInkOverflow(OutlineType type) {
+  return type == OutlineType::kIncludeBlockInkOverflow ||
+         type == OutlineType::kIncludeBlockInkOverflowForAnchor;
 }
 
-inline bool ShouldIncludeBlockVisualOverflowForAnchorOnly(NGOutlineType type) {
-  return type == NGOutlineType::kIncludeBlockVisualOverflowForAnchor;
+inline bool ShouldIncludeBlockInkOverflowForAnchorOnly(OutlineType type) {
+  return type == OutlineType::kIncludeBlockInkOverflowForAnchor;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
index dd0cfce..080cd3a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -19,7 +19,7 @@
 PageLayoutAlgorithm::PageLayoutAlgorithm(const LayoutAlgorithmParams& params)
     : LayoutAlgorithm(params) {}
 
-const NGLayoutResult* PageLayoutAlgorithm::Layout() {
+const LayoutResult* PageLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken());
   auto writing_direction = GetConstraintSpace().GetWritingDirection();
   const BlockBreakToken* break_token = nullptr;
@@ -99,8 +99,8 @@
   BlockLayoutAlgorithm child_algorithm(
       {Node(), fragment_geometry, child_space, break_token});
   child_algorithm.SetBoxType(NGPhysicalFragment::kPageBox);
-  const NGLayoutResult* result = child_algorithm.Layout();
-  return &To<NGPhysicalBoxFragment>(result->PhysicalFragment());
+  const LayoutResult* result = child_algorithm.Layout();
+  return &To<NGPhysicalBoxFragment>(result->GetPhysicalFragment());
 }
 
 ConstraintSpace PageLayoutAlgorithm::CreateConstraintSpaceForPages(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
index 2f31abbf..ac991ab 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.h
@@ -22,7 +22,7 @@
  public:
   explicit PageLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
index 6bd0b2c..e941520 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -572,8 +572,9 @@
 const NGPhysicalBoxFragment* NGPhysicalBoxFragment::PostLayout() const {
   // While side effects are disabled, new fragments are not copied to
   // |LayoutBox|. Just return the given fragment.
-  if (NGDisableSideEffectsScope::IsDisabled())
+  if (DisableLayoutSideEffectsScope::IsDisabled()) {
     return this;
+  }
 
   const auto* layout_object = GetSelfOrContainerLayoutObject();
   if (UNLIKELY(!layout_object)) {
@@ -1215,7 +1216,7 @@
     LayoutObject::OutlineInfo info;
     // The result rects are in coordinates of this object's border box.
     AddSelfOutlineRects(PhysicalOffset(),
-                        style.OutlineRectsShouldIncludeBlockVisualOverflow(),
+                        style.OutlineRectsShouldIncludeBlockInkOverflow(),
                         collector, &info);
     PhysicalRect rect = collector.Rect();
     rect.Inflate(LayoutUnit(OutlinePainter::OutlineOutsetExtent(style, info)));
@@ -1232,7 +1233,7 @@
 
 void NGPhysicalBoxFragment::AddSelfOutlineRects(
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     OutlineRectCollector& collector,
     LayoutObject::OutlineInfo* info) const {
   if (info) {
@@ -1242,9 +1243,9 @@
       *info = LayoutObject::OutlineInfo::GetFromStyle(Style());
   }
 
-  if (ShouldIncludeBlockVisualOverflow(outline_type) &&
+  if (ShouldIncludeBlockInkOverflow(outline_type) &&
       IsA<HTMLAnchorElement>(GetNode())) {
-    outline_type = NGOutlineType::kIncludeBlockVisualOverflowForAnchor;
+    outline_type = OutlineType::kIncludeBlockInkOverflowForAnchor;
   }
 
   AddOutlineRects(additional_offset, outline_type,
@@ -1253,7 +1254,7 @@
 
 void NGPhysicalBoxFragment::AddOutlineRects(
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     OutlineRectCollector& collector) const {
   AddOutlineRects(additional_offset, outline_type,
                   /* container_relative */ true, collector);
@@ -1261,7 +1262,7 @@
 
 void NGPhysicalBoxFragment::AddOutlineRects(
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     bool inline_container_relative,
     OutlineRectCollector& collector) const {
   DCHECK_EQ(PostLayout(), this);
@@ -1285,8 +1286,8 @@
     }
   }
 
-  if (ShouldIncludeBlockVisualOverflow(outline_type) &&
-      !HasNonVisibleOverflow() && !HasControlClip(*this)) {
+  if (ShouldIncludeBlockInkOverflow(outline_type) && !HasNonVisibleOverflow() &&
+      !HasControlClip(*this)) {
     // Tricky code ahead: we pass a 0,0 additional_offset to
     // AddOutlineRectsForNormalChildren, and add it in after the call.
     // This is necessary because AddOutlineRectsForNormalChildren expects
@@ -1299,7 +1300,7 @@
         To<LayoutBoxModelObject>(GetLayoutObject()));
     collector.Combine(child_collector, additional_offset);
 
-    if (ShouldIncludeBlockVisualOverflowForAnchorOnly(outline_type)) {
+    if (ShouldIncludeBlockInkOverflowForAnchorOnly(outline_type)) {
       for (const auto& child : PostLayoutChildren()) {
         if (!child->IsOutOfFlowPositioned()) {
           continue;
@@ -1317,7 +1318,7 @@
 
 void NGPhysicalBoxFragment::AddOutlineRectsForInlineBox(
     PhysicalOffset additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     bool container_relative,
     OutlineRectCollector& collector) const {
   DCHECK_EQ(PostLayout(), this);
@@ -1381,7 +1382,7 @@
     additional_offset -= this_offset_in_container;
   collector.Combine(cursor_collector, additional_offset);
 
-  if (ShouldIncludeBlockVisualOverflowForAnchorOnly(outline_type) &&
+  if (ShouldIncludeBlockInkOverflowForAnchorOnly(outline_type) &&
       !HasNonVisibleOverflow() && !HasControlClip(*this)) {
     if (!RuntimeEnabledFeatures::LayoutNewContainingBlockEnabled() &&
         container->IsAnonymousBlock()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index 94c03a1..a089626c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -27,7 +27,7 @@
 namespace blink {
 
 class BoxFragmentBuilder;
-enum class NGOutlineType;
+enum class OutlineType;
 struct FrameSetLayoutData;
 
 class CORE_EXPORT NGPhysicalBoxFragment final : public NGPhysicalFragment {
@@ -372,13 +372,13 @@
   // Fragment offset is this fragment's offset from parent.
   // Needed to compensate for LayoutInline Legacy code offsets.
   void AddSelfOutlineRects(const PhysicalOffset& additional_offset,
-                           NGOutlineType include_block_overflows,
+                           OutlineType include_block_overflows,
                            OutlineRectCollector& collector,
                            LayoutObject::OutlineInfo* info) const;
   // Same as |AddSelfOutlineRects|, except when |this.IsInlineBox()|, in which
   // case the coordinate system is relative to the inline formatting context.
   void AddOutlineRects(const PhysicalOffset& additional_offset,
-                       NGOutlineType include_block_overflows,
+                       OutlineType include_block_overflows,
                        OutlineRectCollector& collector) const;
 
   PositionWithAffinity PositionForPoint(PhysicalOffset) const;
@@ -489,7 +489,7 @@
 
   class MutableForCloning {
     STACK_ALLOCATED();
-    friend class NGFragmentRepeater;
+    friend class FragmentRepeater;
     friend class NGPhysicalBoxFragment;
 
    public:
@@ -602,11 +602,11 @@
   PhysicalRect ComputeSelfInkOverflow() const;
 
   void AddOutlineRects(const PhysicalOffset& additional_offset,
-                       NGOutlineType include_block_overflows,
+                       OutlineType include_block_overflows,
                        bool inline_container_relative,
                        OutlineRectCollector& collector) const;
   void AddOutlineRectsForInlineBox(PhysicalOffset additional_offset,
-                                   NGOutlineType include_block_overflows,
+                                   OutlineType include_block_overflows,
                                    bool inline_container_relative,
                                    OutlineRectCollector& collector) const;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
index 53e5b6e..853f87cb 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -768,7 +768,7 @@
 void NGPhysicalFragment::AddOutlineRectsForNormalChildren(
     OutlineRectCollector& collector,
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     const LayoutBoxModelObject* containing_block) const {
   if (const auto* box = DynamicTo<NGPhysicalBoxFragment>(this)) {
     DCHECK_EQ(box->PostLayout(), box);
@@ -800,7 +800,7 @@
 void NGPhysicalFragment::AddOutlineRectsForCursor(
     OutlineRectCollector& collector,
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     const LayoutBoxModelObject* containing_block,
     InlineCursor* cursor) const {
   const auto* const text_combine =
@@ -821,7 +821,7 @@
       }
       case FragmentItem::kGeneratedText:
       case FragmentItem::kText: {
-        if (!ShouldIncludeBlockVisualOverflow(outline_type)) {
+        if (!ShouldIncludeBlockInkOverflow(outline_type)) {
           break;
         }
         PhysicalRect rect = item.RectInContainerFragment();
@@ -955,7 +955,7 @@
     const PhysicalFragmentLink& descendant,
     OutlineRectCollector& collector,
     const PhysicalOffset& additional_offset,
-    NGOutlineType outline_type,
+    OutlineType outline_type,
     const LayoutBoxModelObject* containing_block) const {
   DCHECK(!descendant->IsLayoutObjectDestroyedOrMoved());
   if (descendant->IsListMarker())
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
index a68d01b2..d5408de 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -36,12 +36,11 @@
 class FragmentItem;
 class Node;
 class PaintLayer;
+enum class OutlineType;
 struct FragmentedOofData;
 struct LogicalRect;
 struct PhysicalOofPositionedNode;
 
-enum class NGOutlineType;
-
 // The NGPhysicalFragment contains the output geometry from layout. The
 // fragment stores all of its information in the physical coordinate system for
 // use by paint, hit-testing etc.
@@ -739,18 +738,18 @@
   void AddOutlineRectsForNormalChildren(
       OutlineRectCollector& collector,
       const PhysicalOffset& additional_offset,
-      NGOutlineType outline_type,
+      OutlineType outline_type,
       const LayoutBoxModelObject* containing_block) const;
   void AddOutlineRectsForCursor(OutlineRectCollector& collector,
                                 const PhysicalOffset& additional_offset,
-                                NGOutlineType outline_type,
+                                OutlineType outline_type,
                                 const LayoutBoxModelObject* containing_block,
                                 InlineCursor* cursor) const;
   void AddOutlineRectsForDescendant(
       const PhysicalFragmentLink& descendant,
       OutlineRectCollector& collector,
       const PhysicalOffset& additional_offset,
-      NGOutlineType outline_type,
+      OutlineType outline_type,
       const LayoutBoxModelObject* containing_block) const;
 
   static bool DependsOnPercentageBlockSize(const FragmentBuilder&);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc
index ae1469ba..2c31ed04 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.cc
@@ -17,7 +17,8 @@
   if (break_before_token) {
     return break_before_token.Get();
   }
-  return To<BlockBreakToken>(layout_result->PhysicalFragment().GetBreakToken());
+  return To<BlockBreakToken>(
+      layout_result->GetPhysicalFragment().GetBreakToken());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
index f892c2b8..aaafd821 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_positioned_float.h
@@ -12,7 +12,7 @@
 
 namespace blink {
 
-class NGLayoutResult;
+class LayoutResult;
 
 // Contains the information necessary for copying back data to a FloatingObject.
 struct CORE_EXPORT PositionedFloat {
@@ -20,7 +20,7 @@
 
  public:
   PositionedFloat() = default;
-  PositionedFloat(const NGLayoutResult* layout_result,
+  PositionedFloat(const LayoutResult* layout_result,
                   const BlockBreakToken* break_before_token,
                   const BfcOffset& bfc_offset,
                   LayoutUnit minimum_space_shortage)
@@ -37,7 +37,7 @@
 
   const BlockBreakToken* BreakToken() const;
 
-  Member<const NGLayoutResult> layout_result;
+  Member<const LayoutResult> layout_result;
   Member<const BlockBreakToken> break_before_token;
   BfcOffset bfc_offset;
   LayoutUnit minimum_space_shortage;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.cc
index 8772c84..f2d0a97 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.cc
@@ -17,7 +17,7 @@
   DCHECK(params.space.IsNewFormattingContext());
 }
 
-const NGLayoutResult* ReplacedLayoutAlgorithm::Layout() {
+const LayoutResult* ReplacedLayoutAlgorithm::Layout() {
   DCHECK(!GetBreakToken() || GetBreakToken()->IsBreakBefore());
   // TODO(crbug.com/1252693): kIgnoreBlockLengths applies inline constraints
   // through the aspect ratio. But the aspect ratio is ignored when computing
@@ -82,10 +82,10 @@
     space_builder.SetIsFixedInlineSize(true);
     space_builder.SetIsFixedBlockSize(true);
 
-    const NGLayoutResult* result =
+    const LayoutResult* result =
         To<BlockNode>(child).Layout(space_builder.ToConstraintSpace());
-    LogicalOffset offset =
-        converter.ToLogical(new_rect.offset, result->PhysicalFragment().Size());
+    LogicalOffset offset = converter.ToLogical(
+        new_rect.offset, result->GetPhysicalFragment().Size());
     container_builder_.AddResult(*result, offset);
   }
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.h
index f72cda7..20bb28e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_replaced_layout_algorithm.h
@@ -21,7 +21,7 @@
   explicit ReplacedLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
  private:
   void LayoutMediaChildren();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
index afc83303..9ee7daa 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.cc
@@ -23,7 +23,7 @@
 
 SimplifiedLayoutAlgorithm::SimplifiedLayoutAlgorithm(
     const LayoutAlgorithmParams& params,
-    const NGLayoutResult& result,
+    const LayoutResult& result,
     bool keep_old_size)
     : LayoutAlgorithm(params),
       previous_result_(result),
@@ -32,7 +32,7 @@
 
   const bool is_block_flow = Node().IsBlockFlow();
   const NGPhysicalBoxFragment& physical_fragment =
-      To<NGPhysicalBoxFragment>(result.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(result.GetPhysicalFragment());
 
   container_builder_.SetIsNewFormattingContext(
       physical_fragment.IsFormattingContextRoot());
@@ -206,7 +206,7 @@
 
 void SimplifiedLayoutAlgorithm::CloneOldChildren() {
   const auto& previous_fragment =
-      To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(previous_result_.GetPhysicalFragment());
   for (const auto& child_link : previous_fragment.Children()) {
     const auto& child_fragment = *child_link.get();
     AddChildFragment(child_link, child_fragment);
@@ -219,23 +219,23 @@
   container_builder_.AddChild(fragment, offset);
 }
 
-const NGLayoutResult*
+const LayoutResult*
 SimplifiedLayoutAlgorithm::CreateResultAfterManualChildLayout() {
-  const NGLayoutResult* result = container_builder_.ToBoxFragment();
-  if (result->PhysicalFragment().IsOutOfFlowPositioned()) {
+  const LayoutResult* result = container_builder_.ToBoxFragment();
+  if (result->GetPhysicalFragment().IsOutOfFlowPositioned()) {
     result->CopyMutableOutOfFlowData(previous_result_);
   }
   return result;
 }
 
-const NGLayoutResult* SimplifiedLayoutAlgorithm::Layout() {
+const LayoutResult* SimplifiedLayoutAlgorithm::Layout() {
   // Since simplified layout's |Layout()| function deals with laying out
   // children, we can early out if we are display-locked.
   if (Node().ChildLayoutBlockedByDisplayLock())
     return container_builder_.ToBoxFragment();
 
   const auto& previous_fragment =
-      To<NGPhysicalBoxFragment>(previous_result_.PhysicalFragment());
+      To<NGPhysicalBoxFragment>(previous_result_.GetPhysicalFragment());
 
   for (const auto& child_link : previous_fragment.Children()) {
     const auto& child_fragment = *child_link.get();
@@ -251,7 +251,7 @@
     }
 
     // Add the (potentially updated) layout result.
-    const NGLayoutResult* result =
+    const LayoutResult* result =
         BlockNode(To<LayoutBox>(child_fragment.GetMutableLayoutObject()))
             .SimplifiedLayout(child_fragment);
 
@@ -263,11 +263,11 @@
 
     const MarginStrut end_margin_strut = result->EndMarginStrut();
     // No margins should pierce outside formatting-context roots.
-    DCHECK(!result->PhysicalFragment().IsFormattingContextRoot() ||
+    DCHECK(!result->GetPhysicalFragment().IsFormattingContextRoot() ||
            end_margin_strut.IsEmpty());
 
-    AddChildFragment(child_link, result->PhysicalFragment(), &end_margin_strut,
-                     result->IsSelfCollapsing());
+    AddChildFragment(child_link, result->GetPhysicalFragment(),
+                     &end_margin_strut, result->IsSelfCollapsing());
   }
 
   // Iterate through all our OOF-positioned children and add them as candidates.
@@ -323,11 +323,11 @@
   return container_builder_.ToBoxFragment();
 }
 
-NOINLINE const NGLayoutResult*
+NOINLINE const LayoutResult*
 SimplifiedLayoutAlgorithm::LayoutWithItemsBuilder() {
   FragmentItemsBuilder items_builder(writing_direction_);
   container_builder_.SetItemsBuilder(&items_builder);
-  const NGLayoutResult* result = Layout();
+  const LayoutResult* result = Layout();
   // Ensure stack-allocated |FragmentItemsBuilder| is not used anymore.
   // TODO(kojii): Revisit when the storage of |FragmentItemsBuilder| is
   // finalized.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
index 0a4f7f3..3b73830 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_layout_algorithm.h
@@ -28,7 +28,7 @@
 //
 // This algorithm effectively performs a (convoluted) "copy" of the previous
 // layout result. It will:
-//  1. Copy data from the previous |NGLayoutResult| into the
+//  1. Copy data from the previous |LayoutResult| into the
 //     |BoxFragmentBuilder|, (e.g. flags, end margin strut, etc).
 //  2. Iterate through all the children and:
 //    a. If OOF-positioned determine the static-position and add it as an
@@ -40,7 +40,7 @@
     : public LayoutAlgorithm<BlockNode, BoxFragmentBuilder, BlockBreakToken> {
  public:
   SimplifiedLayoutAlgorithm(const LayoutAlgorithmParams&,
-                            const NGLayoutResult&,
+                            const LayoutResult&,
                             bool keep_old_size = false);
 
   // Perform a simple copy of all children of the old fragment.
@@ -50,19 +50,19 @@
 
   // Just create a new layout result based on the current builder state. To be
   // used after CloneOldChildren() / AppendNewChildFragment().
-  const NGLayoutResult* CreateResultAfterManualChildLayout();
+  const LayoutResult* CreateResultAfterManualChildLayout();
 
   // Attempt to perform simplified layout on all children and return a new
   // result. If nullptr is returned, it means that simplified layout isn't
   // possible.
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override {
     NOTREACHED();
     return MinMaxSizesResult();
   }
 
-  NOINLINE const NGLayoutResult* LayoutWithItemsBuilder();
+  NOINLINE const LayoutResult* LayoutWithItemsBuilder();
 
  private:
   void AddChildFragment(const PhysicalFragmentLink& old_fragment,
@@ -70,7 +70,7 @@
                         const MarginStrut* margin_strut = nullptr,
                         bool is_self_collapsing = false);
 
-  const NGLayoutResult& previous_result_;
+  const LayoutResult& previous_result_;
   BoxStrut border_scrollbar_padding_;
 
   const WritingDirectionMode writing_direction_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
index 6209f482..86392fe 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.cc
@@ -75,14 +75,14 @@
       previous_fragment.MayHaveDescendantAboveBlockStart());
 }
 
-const NGLayoutResult* SimplifiedOofLayoutAlgorithm::Layout() {
+const LayoutResult* SimplifiedOofLayoutAlgorithm::Layout() {
   FinishFragmentationForFragmentainer(GetConstraintSpace(),
                                       &container_builder_);
   return container_builder_.ToBoxFragment();
 }
 
 void SimplifiedOofLayoutAlgorithm::AppendOutOfFlowResult(
-    const NGLayoutResult* result) {
+    const LayoutResult* result) {
   container_builder_.AddResult(*result, result->OutOfFlowPositionedOffset());
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
index 79a7cd2..f040b64 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_simplified_oof_layout_algorithm.h
@@ -28,13 +28,13 @@
                                const NGPhysicalBoxFragment&,
                                bool is_new_fragment);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override {
     NOTREACHED();
     return MinMaxSizesResult();
   }
 
-  void AppendOutOfFlowResult(const NGLayoutResult* child);
+  void AppendOutOfFlowResult(const LayoutResult* child);
 
  private:
   void AddChildFragment(const PhysicalFragmentLink& old_fragment);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc b/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
index e919177..4ce95bf 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
@@ -44,7 +44,7 @@
 
 }  // namespace
 
-int NGTextDecorationOffset::ComputeUnderlineOffsetForUnder(
+int TextDecorationOffset::ComputeUnderlineOffsetForUnder(
     const Length& style_underline_offset,
     float computed_font_size,
     const SimpleFontData* font_data,
@@ -80,7 +80,7 @@
              : offset_int - 1 - floorf(text_decoration_thickness);
 }
 
-int NGTextDecorationOffset::ComputeUnderlineOffset(
+int TextDecorationOffset::ComputeUnderlineOffset(
     ResolvedUnderlinePosition underline_position,
     float computed_font_size,
     const SimpleFontData* font_data,
@@ -116,7 +116,7 @@
 }
 
 /* static */
-float NGTextDecorationOffset::StyleUnderlineOffsetToPixels(
+float TextDecorationOffset::StyleUnderlineOffsetToPixels(
     const Length& style_underline_offset,
     float font_size) {
   if (style_underline_offset.IsAuto()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h b/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
index 3ac96ca..7f14d59c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h
@@ -18,13 +18,13 @@
 enum class ResolvedUnderlinePosition;
 
 // Class for computing the decoration offset for text fragments in LayoutNG.
-class CORE_EXPORT NGTextDecorationOffset {
+class CORE_EXPORT TextDecorationOffset {
   STACK_ALLOCATED();
 
  public:
-  explicit NGTextDecorationOffset(const ComputedStyle& text_style)
+  explicit TextDecorationOffset(const ComputedStyle& text_style)
       : text_style_(text_style) {}
-  ~NGTextDecorationOffset() = default;
+  ~TextDecorationOffset() = default;
 
   int ComputeUnderlineOffsetForUnder(const Length& style_underline_offset,
                                      float computed_font_size,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
index 9a12af3..ba0917e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
@@ -55,7 +55,7 @@
 
   // layout_result and margins are used as a cache when measuring the
   // inline_size of a float in an inline context.
-  const NGLayoutResult* layout_result = nullptr;
+  const LayoutResult* layout_result = nullptr;
   BoxStrut margins;
 
   bool IsLineLeft(TextDirection cb_direction) const {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
index 29d8d55..9e11ad5f 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
@@ -151,7 +151,7 @@
   // Any propagated sticky-descendants may have invalid sticky-constraints.
   // Clear them now.
   if (const auto* sticky_descendants =
-          result->PhysicalFragment().PropagatedStickyDescendants()) {
+          result->GetPhysicalFragment().PropagatedStickyDescendants()) {
     for (const auto& sticky_descendant : *sticky_descendants) {
       sticky_descendant->SetStickyConstraints(nullptr);
     }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
index f1c94c47..372917f 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
@@ -148,7 +148,7 @@
 void LayoutSVGInline::AddOutlineRects(OutlineRectCollector& collector,
                                       OutlineInfo* info,
                                       const PhysicalOffset& additional_offset,
-                                      NGOutlineType outline_type) const {
+                                      OutlineType outline_type) const {
   if (!IsInLayoutNGInlineFormattingContext()) {
     LayoutInline::AddOutlineRects(collector, nullptr, additional_offset,
                                   outline_type);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
index 47d3c72a..ccf785c1 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
@@ -61,7 +61,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const final;
+                       OutlineType) const final;
 
  private:
   void WillBeDestroyed() final;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index 443e11e..15a12c6 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -83,7 +83,7 @@
 void LayoutSVGModelObject::AddOutlineRects(OutlineRectCollector& collector,
                                            OutlineInfo* info,
                                            const PhysicalOffset&,
-                                           NGOutlineType) const {
+                                           OutlineType) const {
   NOT_DESTROYED();
   gfx::RectF visual_rect = VisualRectInLocalSVGCoordinates();
   bool was_empty = visual_rect.IsEmpty();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
index 7d4e37b..d65a763 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -93,7 +93,7 @@
   void AddOutlineRects(OutlineRectCollector&,
                        OutlineInfo*,
                        const PhysicalOffset& additional_offset,
-                       NGOutlineType) const final;
+                       OutlineType) const final;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/table/layout_table.cc b/third_party/blink/renderer/core/layout/table/layout_table.cc
index a1f2aa0..98f5668 100644
--- a/third_party/blink/renderer/core/layout/table/layout_table.cc
+++ b/third_party/blink/renderer/core/layout/table/layout_table.cc
@@ -167,7 +167,7 @@
 
 wtf_size_t LayoutTable::ColumnCount() const {
   NOT_DESTROYED();
-  const NGLayoutResult* cached_layout_result = GetCachedLayoutResult(nullptr);
+  const LayoutResult* cached_layout_result = GetCachedLayoutResult(nullptr);
   if (!cached_layout_result)
     return 0;
   return cached_layout_result->TableColumnCount();
diff --git a/third_party/blink/renderer/core/layout/table/table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/table/table_layout_algorithm.cc
index 3258e86..88238e4 100644
--- a/third_party/blink/renderer/core/layout/table/table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/table/table_layout_algorithm.cc
@@ -98,12 +98,12 @@
     BoxStrut margins,
     const BlockBreakToken* break_token = nullptr,
     const EarlyBreak* early_break = nullptr) {
-  const NGLayoutResult* layout_result =
+  const LayoutResult* layout_result =
       caption.Layout(caption_constraint_space, break_token, early_break);
-  DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
+  DCHECK_EQ(layout_result->Status(), LayoutResult::kSuccess);
 
   LogicalFragment fragment(table_constraint_space.GetWritingDirection(),
-                           layout_result->PhysicalFragment());
+                           layout_result->GetPhysicalFragment());
   ResolveInlineAutoMargins(caption.Style(), table_style, table_inline_size,
                            fragment.InlineSize(), &margins);
 
@@ -151,7 +151,7 @@
     //
     // TODO(mstensho): We can remove this if we only perform this operation once
     // per table node (and e.g. store the table data in the break tokens).
-    absl::optional<NGDisableSideEffectsScope> disable_side_effects;
+    absl::optional<DisableLayoutSideEffectsScope> disable_side_effects;
     if ((!captions && !caption.GetLayoutBox()->NeedsLayout()) ||
         InvolvedInBlockFragmentation(table_builder)) {
       disable_side_effects.emplace();
@@ -160,8 +160,9 @@
     TableLayoutAlgorithm::CaptionResult caption_result =
         LayoutCaption(table_constraint_space, table_style, table_inline_size,
                       caption_constraint_space, caption, margins);
-    LogicalFragment fragment(table_constraint_space.GetWritingDirection(),
-                             caption_result.layout_result->PhysicalFragment());
+    LogicalFragment fragment(
+        table_constraint_space.GetWritingDirection(),
+        caption_result.layout_result->GetPhysicalFragment());
     captions_block_size +=
         fragment.BlockSize() + caption_result.margins.BlockSum();
     if (captions)
@@ -552,7 +553,7 @@
   return captions_block_size;
 }
 
-const NGLayoutResult* TableLayoutAlgorithm::Layout() {
+const LayoutResult* TableLayoutAlgorithm::Layout() {
   const bool is_fixed_layout = Style().IsFixedTableLayout();
   const LogicalSize border_spacing = Style().TableBorderSpacing();
   TableGroupedChildren grouped_children(Node());
@@ -656,15 +657,16 @@
   }
 #endif
 
-  const NGLayoutResult* result = GenerateFragment(
+  const LayoutResult* result = GenerateFragment(
       container_builder_.InlineSize(), minimal_table_grid_block_size,
       grouped_children, column_locations, rows, cell_block_constraints,
       sections, captions, *table_borders,
       is_grid_empty ? LogicalSize() : border_spacing);
 
-  if (result->Status() == NGLayoutResult::kNeedsRelayoutAsLastTableBox)
+  if (result->Status() == LayoutResult::kNeedsRelayoutAsLastTableBox) {
     return RelayoutAsLastTableBox();
-  if (result->Status() == NGLayoutResult::kNeedsEarlierBreak) {
+  }
+  if (result->Status() == LayoutResult::kNeedsEarlierBreak) {
     // We shouldn't insert early-breaks when we're relaying out as the last
     // table-box fragment. That should take place *first*.
     DCHECK(!is_known_to_be_last_table_box_);
@@ -713,7 +715,7 @@
                            /* depends_on_block_constraints */ false};
 }
 
-const NGLayoutResult* TableLayoutAlgorithm::RelayoutAsLastTableBox() {
+const LayoutResult* TableLayoutAlgorithm::RelayoutAsLastTableBox() {
   DCHECK(!is_known_to_be_last_table_box_);
   LayoutAlgorithmParams params(
       Node(), container_builder_.InitialFragmentGeometry(),
@@ -888,7 +890,7 @@
 // |     table border/padding       |
 // |     bottom caption fragments   |
 // +--------------------------------+
-const NGLayoutResult* TableLayoutAlgorithm::GenerateFragment(
+const LayoutResult* TableLayoutAlgorithm::GenerateFragment(
     const LayoutUnit table_inline_size,
     LayoutUnit minimal_table_grid_block_size,
     const TableGroupedChildren& grouped_children,
@@ -960,10 +962,11 @@
         LogicalOffset(caption.margins.inline_start, *block_offset),
         caption.margins);
 
-    *block_offset += LogicalFragment(table_writing_direction,
-                                     caption.layout_result->PhysicalFragment())
-                         .BlockSize() +
-                     caption.margins.block_end;
+    *block_offset +=
+        LogicalFragment(table_writing_direction,
+                        caption.layout_result->GetPhysicalFragment())
+            .BlockSize() +
+        caption.margins.block_end;
   };
 
   // We have already laid out the captions, in order to calculate the table grid
@@ -1069,7 +1072,7 @@
   // if side-effects are disabled, as that machinery depends on updating and
   // reading the physical fragments vector of the LayoutBox.
   if (!GetConstraintSpace().IsInsideRepeatableContent() &&
-      !NGDisableSideEffectsScope::IsDisabled() &&
+      !DisableLayoutSideEffectsScope::IsDisabled() &&
       (grouped_children.header || grouped_children.footer)) {
     LayoutUnit max_section_block_size =
         GetConstraintSpace().FragmentainerBlockSize() / 4;
@@ -1176,7 +1179,7 @@
     }
 
     const BlockBreakToken* child_break_token = entry.GetBreakToken();
-    const NGLayoutResult* child_result;
+    const LayoutResult* child_result;
     absl::optional<LayoutUnit> offset_before_repeated_header;
     LayoutUnit child_inline_offset;
 
@@ -1230,7 +1233,7 @@
       CaptionResult caption = LayoutCaption(
           constraint_space, Style(), container_builder_.InlineSize(),
           child_space, child, margins, child_break_token, early_break_in_child);
-      DCHECK_EQ(caption.layout_result->Status(), NGLayoutResult::kSuccess);
+      DCHECK_EQ(caption.layout_result->Status(), LayoutResult::kSuccess);
       child_result = caption.layout_result;
       child_inline_offset = caption.margins.inline_start;
 
@@ -1332,7 +1335,7 @@
       child_inline_offset = section_inline_offset;
 
       border_spacing_after_last_section = border_spacing.block_size;
-      if (To<NGPhysicalBoxFragment>(child_result->PhysicalFragment())
+      if (To<NGPhysicalBoxFragment>(child_result->GetPhysicalFragment())
               .HasDescendantsForTablePart()) {
         // We want to add border-spacing after this section, but not if the
         // current fragment is past the block-end of the section. This might
@@ -1360,7 +1363,7 @@
           constraint_space, child, *child_result, fragmentainer_block_offset,
           has_container_separation, &container_builder_);
       if (break_status == BreakStatus::kNeedsEarlierBreak) {
-        return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+        return container_builder_.Abort(LayoutResult::kNeedsEarlierBreak);
       }
       if (break_status == BreakStatus::kBrokeBefore) {
         broke_inside = true;
@@ -1370,7 +1373,7 @@
     }
 
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(child_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(child_result->GetPhysicalFragment());
     LogicalBoxFragment fragment(table_writing_direction, physical_fragment);
     if (child.IsTableSection()) {
       if (!is_repeated_section) {
@@ -1485,7 +1488,7 @@
     ConstraintSpace child_space = CreateSectionConstraintSpace(
         grouped_children.footer, offset.block_offset, entry.GetSectionIndex(),
         /* reserved_space */ LayoutUnit(), kMayRepeatAgain);
-    const NGLayoutResult* result = grouped_children.footer.LayoutRepeatableRoot(
+    const LayoutResult* result = grouped_children.footer.LayoutRepeatableRoot(
         child_space, entry.GetBreakToken());
 
     BreakStatus break_status = BreakStatus::kContinue;
@@ -1614,7 +1617,7 @@
         FinishFragmentation(Node(), constraint_space, border_padding.block_end,
                             fragmentainer_space_at_start, &container_builder_);
     if (status == BreakStatus::kNeedsEarlierBreak) {
-      return container_builder_.Abort(NGLayoutResult::kNeedsEarlierBreak);
+      return container_builder_.Abort(LayoutResult::kNeedsEarlierBreak);
     }
 
     DCHECK_EQ(status, BreakStatus::kContinue);
@@ -1685,8 +1688,7 @@
     // outgoing "repeat" break token). However, we managed to finish the table
     // box in this fragment, so it shouldn't repeat anymore. We now need to
     // re-layout, with this in mind.
-    return container_builder_.Abort(
-        NGLayoutResult::kNeedsRelayoutAsLastTableBox);
+    return container_builder_.Abort(LayoutResult::kNeedsRelayoutAsLastTableBox);
   }
 
   return container_builder_.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/table/table_layout_algorithm.h b/third_party/blink/renderer/core/layout/table/table_layout_algorithm.h
index 5ad5fd5f..a978c46 100644
--- a/third_party/blink/renderer/core/layout/table/table_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/table/table_layout_algorithm.h
@@ -22,7 +22,7 @@
  public:
   explicit TableLayoutAlgorithm(const LayoutAlgorithmParams& params)
       : LayoutAlgorithm(params) {}
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override;
 
@@ -48,12 +48,12 @@
     }
 
     BlockNode node;
-    Member<const NGLayoutResult> layout_result;
+    Member<const LayoutResult> layout_result;
     const BoxStrut margins;
   };
 
  private:
-  const NGLayoutResult* RelayoutAsLastTableBox();
+  const LayoutResult* RelayoutAsLastTableBox();
 
   void ComputeRows(const LayoutUnit table_grid_inline_size,
                    const TableGroupedChildren& grouped_children,
@@ -75,7 +75,7 @@
       const LogicalRect& table_grid_rect,
       LayoutUnit table_grid_block_size);
 
-  const NGLayoutResult* GenerateFragment(
+  const LayoutResult* GenerateFragment(
       LayoutUnit table_inline_size,
       LayoutUnit minimal_table_grid_block_size,
       const TableGroupedChildren& grouped_children,
diff --git a/third_party/blink/renderer/core/layout/table/table_layout_utils.cc b/third_party/blink/renderer/core/layout/table/table_layout_utils.cc
index e92f2d9..0670e77 100644
--- a/third_party/blink/renderer/core/layout/table/table_layout_utils.cc
+++ b/third_party/blink/renderer/core/layout/table/table_layout_utils.cc
@@ -230,11 +230,11 @@
         LayoutResultCacheSlot::kMeasure, &space_builder);
 
     const auto cell_space = space_builder.ToConstraintSpace();
-    const NGLayoutResult* layout_result = cell.Layout(cell_space);
+    const LayoutResult* layout_result = cell.Layout(cell_space);
 
     const LogicalBoxFragment fragment(
         table_writing_direction,
-        To<NGPhysicalBoxFragment>(layout_result->PhysicalFragment()));
+        To<NGPhysicalBoxFragment>(layout_result->GetPhysicalFragment()));
     const Length& cell_specified_block_length =
         IsParallelWritingMode(table_writing_direction.GetWritingMode(),
                               cell_style.GetWritingMode())
diff --git a/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.cc b/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.cc
index d230a2d2..f57cc18d 100644
--- a/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.cc
@@ -21,10 +21,10 @@
   DISALLOW_NEW();
 
  public:
-  Member<const NGLayoutResult> result;
+  Member<const LayoutResult> result;
   LogicalOffset offset;
 
-  ResultWithOffset(const NGLayoutResult* result, LogicalOffset offset)
+  ResultWithOffset(const LayoutResult* result, LogicalOffset offset)
       : result(result), offset(offset) {}
 
   void Trace(Visitor* visitor) const { visitor->Trace(result); }
@@ -34,7 +34,7 @@
     const LayoutAlgorithmParams& params)
     : LayoutAlgorithm(params) {}
 
-const NGLayoutResult* TableRowLayoutAlgorithm::Layout() {
+const LayoutResult* TableRowLayoutAlgorithm::Layout() {
   const TableConstraintSpaceData& table_data =
       *GetConstraintSpace().TableData();
   const auto& row = table_data.rows[GetConstraintSpace().TableRowIndex()];
@@ -138,8 +138,8 @@
     results.clear();
     has_inflow_break_inside = false;
 
-    NGBlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken(),
-                                        /* calculate_child_idx */ true);
+    BlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken(),
+                                      /* calculate_child_idx */ true);
     for (auto entry = child_iterator.NextChild();
          BlockNode cell = To<BlockNode>(entry.node);
          entry = child_iterator.NextChild()) {
@@ -155,9 +155,9 @@
       const auto cell_space = CreateCellConstraintSpace(
           cell, cell_break_token, cell_data, row_block_size, row_baseline,
           min_block_size_should_encompass_intrinsic_size);
-      const NGLayoutResult* cell_result =
+      const LayoutResult* cell_result =
           cell.Layout(cell_space, cell_break_token);
-      DCHECK_EQ(cell_result->Status(), NGLayoutResult::kSuccess);
+      DCHECK_EQ(cell_result->Status(), LayoutResult::kSuccess);
 
       const LogicalOffset offset(
           table_data.column_locations[cell_data.start_column].offset -
@@ -181,7 +181,7 @@
 
       bool has_rowspan = cell_data.rowspan_block_size != kIndefiniteSize;
       const auto& physical_fragment =
-          To<NGPhysicalBoxFragment>(cell_result->PhysicalFragment());
+          To<NGPhysicalBoxFragment>(cell_result->GetPhysicalFragment());
       const LogicalBoxFragment fragment(table_data.table_writing_direction,
                                         physical_fragment);
       row_baseline_tabulator.ProcessCell(
diff --git a/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.h b/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.h
index b28d27a..587ac149 100644
--- a/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/table/table_row_layout_algorithm.h
@@ -21,7 +21,7 @@
  public:
   explicit TableRowLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override {
     // Table layout doesn't compute min/max sizes on table rows.
diff --git a/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.cc b/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.cc
index 4f0403f2..8deb05f 100644
--- a/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.cc
@@ -30,7 +30,7 @@
 // |  +--------------------+  |
 // |       vspacing           |
 // +--------------------------+
-const NGLayoutResult* TableSectionLayoutAlgorithm::Layout() {
+const LayoutResult* TableSectionLayoutAlgorithm::Layout() {
   const auto& constraint_space = GetConstraintSpace();
   const TableConstraintSpaceData& table_data = *constraint_space.TableData();
   const auto& section =
@@ -48,8 +48,8 @@
   Vector<LayoutUnit> row_offsets = {LayoutUnit()};
   wtf_size_t actual_start_row_index = 0u;
 
-  NGBlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken(),
-                                      /* calculate_child_idx */ true);
+  BlockChildIterator child_iterator(Node().FirstChild(), GetBreakToken(),
+                                    /* calculate_child_idx */ true);
   for (auto entry = child_iterator.NextChild();
        BlockNode row = To<BlockNode>(entry.node);
        entry = child_iterator.NextChild()) {
@@ -87,7 +87,7 @@
     }
 
     ConstraintSpace row_space = row_space_builder.ToConstraintSpace();
-    const NGLayoutResult* row_result = row.Layout(row_space, row_break_token);
+    const LayoutResult* row_result = row.Layout(row_space, row_break_token);
 
     if (constraint_space.HasBlockFragmentation()) {
       LayoutUnit fragmentainer_block_offset =
@@ -106,7 +106,7 @@
     }
 
     const auto& physical_fragment =
-        To<NGPhysicalBoxFragment>(row_result->PhysicalFragment());
+        To<NGPhysicalBoxFragment>(row_result->GetPhysicalFragment());
     const LogicalBoxFragment fragment(table_data.table_writing_direction,
                                       physical_fragment);
 
diff --git a/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.h b/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.h
index 1d1218e1..e14b6f6 100644
--- a/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/table/table_section_layout_algorithm.h
@@ -21,7 +21,7 @@
  public:
   explicit TableSectionLayoutAlgorithm(const LayoutAlgorithmParams& params);
 
-  const NGLayoutResult* Layout() override;
+  const LayoutResult* Layout() override;
 
   MinMaxSizesResult ComputeMinMaxSizes(const MinMaxSizesFloatInput&) override {
     // Table layout doesn't compute min/max sizes on table sections.
diff --git a/third_party/blink/renderer/core/loader/document_loader_auto_speculation_rules_test.cc b/third_party/blink/renderer/core/loader/document_loader_auto_speculation_rules_test.cc
index 0b1367c3..4591f18 100644
--- a/third_party/blink/renderer/core/loader/document_loader_auto_speculation_rules_test.cc
+++ b/third_party/blink/renderer/core/loader/document_loader_auto_speculation_rules_test.cc
@@ -46,6 +46,27 @@
   WebViewImpl* web_view_impl_;
 };
 
+enum class OptOutRuleSetType { kInline, kExternal };
+class DocumentLoaderAutoSpeculationRulesOptOutTest
+    : public DocumentLoaderAutoSpeculationRulesTest,
+      public testing::WithParamInterface<OptOutRuleSetType> {
+ public:
+  SpeculationRuleSet* GetOptOutRuleSet() const {
+    switch (GetParam()) {
+      case OptOutRuleSetType::kInline:
+        return SpeculationRuleSet::Parse(
+            SpeculationRuleSet::Source::FromInlineScript("{}", GetDocument(),
+                                                         0),
+            GetLocalFrame().DomWindow());
+      case OptOutRuleSetType::kExternal:
+        return SpeculationRuleSet::Parse(
+            SpeculationRuleSet::Source::FromRequest(
+                "{}", KURL("https://example.com/speculation-rules.json"), 0u),
+            GetLocalFrame().DomWindow());
+    }
+  }
+};
+
 TEST_F(DocumentLoaderAutoSpeculationRulesTest, InvalidJSON) {
   test::AutoSpeculationRulesConfigOverride override(R"(
   {
@@ -88,8 +109,7 @@
   // the speculation rules tests.
 }
 
-TEST_F(DocumentLoaderAutoSpeculationRulesTest,
-       ExistingFromInlineScriptRuleSetOptsOut) {
+TEST_P(DocumentLoaderAutoSpeculationRulesOptOutTest, ExistingRuleSetOptsOut) {
   test::AutoSpeculationRulesConfigOverride override(R"(
   {
     "framework_to_speculation_rules": {
@@ -101,9 +121,7 @@
   auto& rules = GetDocumentSpeculationRules();
   CHECK_EQ(rules.rule_sets().size(), 0u);
 
-  auto* rule_set = SpeculationRuleSet::Parse(
-      SpeculationRuleSet::Source::FromInlineScript("{}", GetDocument(), 0),
-      GetLocalFrame().DomWindow());
+  auto* rule_set = GetOptOutRuleSet();
   rules.AddRuleSet(rule_set);
 
   EXPECT_EQ(rules.rule_sets().size(), 1u);
@@ -127,46 +145,56 @@
       /*expected_bucket_count=*/1);
 }
 
-TEST_F(DocumentLoaderAutoSpeculationRulesTest,
-       ExistingFromRequestRuleSetOptsOut) {
+TEST_P(DocumentLoaderAutoSpeculationRulesOptOutTest, AddedLaterRuleSetOptsOut) {
+  // Test 2 auto speculation rule sets to ensure we remove both of them
+  // correctly.
   test::AutoSpeculationRulesConfigOverride override(R"(
   {
     "framework_to_speculation_rules": {
-      "1": "{\"prefetch\":[{\"source\":\"list\", \"urls\":[\"https://example.com/foo.html\"]}]}"
+      "1": "{\"prefetch\":[{\"source\":\"list\", \"urls\":[\"https://example.com/foo.html\"]}]}",
+      "3": "{\"prefetch\":[{\"source\":\"list\", \"urls\":[\"https://example.com/baz.html\"]}]}"
     }
   }
   )");
 
+  base::HistogramTester histogram_tester;
+
   auto& rules = GetDocumentSpeculationRules();
   CHECK_EQ(rules.rule_sets().size(), 0u);
 
-  auto* rule_set = SpeculationRuleSet::Parse(
-      SpeculationRuleSet::Source::FromRequest(
-          "{}", KURL("https://example.com/speculation-rules.json"), 0u),
-      GetLocalFrame().DomWindow());
-  rules.AddRuleSet(rule_set);
+  static_assert(base::to_underlying(mojom::JavaScriptFramework::kVuePress) ==
+                1);
+  static_assert(base::to_underlying(mojom::JavaScriptFramework::kGatsby) == 3);
+  GetDocumentLoader().DidObserveJavaScriptFrameworks(
+      {{{mojom::JavaScriptFramework::kVuePress, kNoFrameworkVersionDetected},
+        {mojom::JavaScriptFramework::kGatsby, kNoFrameworkVersionDetected}}});
 
-  EXPECT_EQ(rules.rule_sets().size(), 1u);
+  EXPECT_EQ(rules.rule_sets().size(), 2u);
   EXPECT_FALSE(
       GetDocument().IsUseCounted(WebFeature::kAutoSpeculationRulesOptedOut));
 
-  base::HistogramTester histogram_tester;
+  auto* manually_added_rule_set = GetOptOutRuleSet();
+  rules.AddRuleSet(manually_added_rule_set);
 
-  static_assert(base::to_underlying(mojom::JavaScriptFramework::kVuePress) ==
-                1);
-  GetDocumentLoader().DidObserveJavaScriptFrameworks(
-      {{{mojom::JavaScriptFramework::kVuePress, kNoFrameworkVersionDetected}}});
-
-  // Still just one, but now the UseCounter and histogram have triggered.
   EXPECT_EQ(rules.rule_sets().size(), 1u);
+  EXPECT_EQ(rules.rule_sets().at(0), manually_added_rule_set);
+
   EXPECT_TRUE(
       GetDocument().IsUseCounted(WebFeature::kAutoSpeculationRulesOptedOut));
-  histogram_tester.ExpectUniqueSample(
-      "Blink.SpeculationRules.LoadOutcome",
-      SpeculationRulesLoadOutcome::kAutoSpeculationRulesOptedOut,
-      /*expected_bucket_count=*/1);
+
+  // The load outcome should not be AutoSpeculationRulesOptedOut, since it did
+  // load correctly. Instead, we should get 3 succeses: 2 auto speculation rules
+  // + 1 normal speculation rule.
+  histogram_tester.ExpectUniqueSample("Blink.SpeculationRules.LoadOutcome",
+                                      SpeculationRulesLoadOutcome::kSuccess,
+                                      /*expected_bucket_count=*/3);
 }
 
+INSTANTIATE_TEST_SUITE_P(FromInlineOrExternal,
+                         DocumentLoaderAutoSpeculationRulesOptOutTest,
+                         testing::Values(OptOutRuleSetType::kInline,
+                                         OptOutRuleSetType::kExternal));
+
 TEST_F(DocumentLoaderAutoSpeculationRulesTest, MultipleRules) {
   test::AutoSpeculationRulesConfigOverride override(R"(
   {
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index ca7fd9b..66e40f6b 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -305,7 +305,7 @@
     const auto* fragment = iterator.GetFragmentData();
     ScopedDisplayItemFragment scoped_fragment(context, index);
     Vector<PhysicalRect> rects = object->CollectOutlineRectsAndAdvance(
-        NGOutlineType::kIncludeBlockVisualOverflow, iterator);
+        OutlineType::kIncludeBlockInkOverflow, iterator);
     if (rects.size() > 1)
       use_rounded_rects = false;
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 740377b1..e40bd84 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -390,7 +390,7 @@
 PhysicalRect NGBoxFragmentPainter::InkOverflowIncludingFilters() const {
   if (box_item_)
     return box_item_->SelfInkOverflowRect();
-  const NGPhysicalFragment& fragment = PhysicalFragment();
+  const auto& fragment = GetPhysicalFragment();
   DCHECK(!fragment.IsInlineBox());
   return To<LayoutBox>(fragment.GetLayoutObject())
       ->VisualOverflowRectIncludingFilters();
@@ -403,10 +403,11 @@
 }
 
 void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
-  if (PhysicalFragment().IsHiddenForPaint())
+  if (GetPhysicalFragment().IsHiddenForPaint()) {
     return;
+  }
   auto* layout_object = box_fragment_.GetLayoutObject();
-  if (PhysicalFragment().IsPaintedAtomically() &&
+  if (GetPhysicalFragment().IsPaintedAtomically() &&
       !box_fragment_.HasSelfPaintingLayer() &&
       paint_info.phase != PaintPhase::kOverlayOverflowControls) {
     PaintAllPhasesAtomically(paint_info);
@@ -556,7 +557,8 @@
   if (!box_fragment_.IsScrollContainer())
     return false;
 
-  return ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea())
+  return ScrollableAreaPainter(
+             *GetPhysicalFragment().Layer()->GetScrollableArea())
       .PaintOverflowControls(paint_info, ToRoundedVector2d(paint_offset),
                              box_fragment_.GetFragmentData());
 }
@@ -575,8 +577,8 @@
     const PaintInfo& paint_info) {
   // Some conditions are checked in ObjectPainter::RecordHitTestData().
   // Table rows/sections do not participate in hit testing.
-  return !PhysicalFragment().IsTableRow() &&
-         !PhysicalFragment().IsTableSection();
+  return !GetPhysicalFragment().IsTableRow() &&
+         !GetPhysicalFragment().IsTableSection();
 }
 
 void NGBoxFragmentPainter::PaintObject(
@@ -584,7 +586,7 @@
     const PhysicalOffset& paint_offset,
     bool suppress_box_decoration_background) {
   const PaintPhase paint_phase = paint_info.phase;
-  const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+  const NGPhysicalBoxFragment& fragment = GetPhysicalFragment();
   if (fragment.IsFrameSet()) {
     NGFrameSetPainter(fragment, display_item_client_)
         .PaintObject(paint_info, paint_offset);
@@ -972,15 +974,15 @@
 }
 
 void NGBoxFragmentPainter::PaintFloats(const PaintInfo& paint_info) {
-  DCHECK(PhysicalFragment().HasFloatingDescendantsForPaint() ||
-         !PhysicalFragment().IsInlineFormattingContext());
-  PaintFloatingChildren(PhysicalFragment(), paint_info);
+  DCHECK(GetPhysicalFragment().HasFloatingDescendantsForPaint() ||
+         !GetPhysicalFragment().IsInlineFormattingContext());
+  PaintFloatingChildren(GetPhysicalFragment(), paint_info);
 }
 
 void NGBoxFragmentPainter::PaintMask(const PaintInfo& paint_info,
                                      const PhysicalOffset& paint_offset) {
   DCHECK_EQ(PaintPhase::kMask, paint_info.phase);
-  const NGPhysicalBoxFragment& physical_box_fragment = PhysicalFragment();
+  const NGPhysicalBoxFragment& physical_box_fragment = GetPhysicalFragment();
   const ComputedStyle& style = physical_box_fragment.Style();
   if (!style.HasMask() || !IsVisibleToPaint(physical_box_fragment, style))
     return;
@@ -1164,11 +1166,11 @@
   DrawingRecorder recorder(paint_info.context, background_client,
                            display_item_type, visual_rect);
 
-  if (PhysicalFragment().IsFieldsetContainer()) {
+  if (GetPhysicalFragment().IsFieldsetContainer()) {
     NGFieldsetPainter(box_fragment_)
         .PaintBoxDecorationBackground(paint_info, paint_rect,
                                       box_decoration_data);
-  } else if (PhysicalFragment().IsTablePart()) {
+  } else if (GetPhysicalFragment().IsTablePart()) {
     if (box_fragment_.IsTableCell()) {
       NGTableCellPainter(box_fragment_)
           .PaintBoxDecorationBackground(paint_info, paint_rect,
@@ -1482,7 +1484,7 @@
 void NGBoxFragmentPainter::PaintAllPhasesAtomically(
     const PaintInfo& paint_info) {
   // Self-painting AtomicInlines should go to normal paint logic.
-  DCHECK(!(PhysicalFragment().IsPaintedAtomically() &&
+  DCHECK(!(GetPhysicalFragment().IsPaintedAtomically() &&
            box_fragment_.HasSelfPaintingLayer()));
 
   // Pass PaintPhaseSelection and PaintPhaseTextClip is handled by the regular
@@ -1571,7 +1573,7 @@
   ScopedDisplayItemFragment display_item_fragment(paint_info.context,
                                                   line_fragment_id);
   if (ShouldRecordHitTestData(paint_info)) {
-    ObjectPainter(*PhysicalFragment().GetLayoutObject())
+    ObjectPainter(*GetPhysicalFragment().GetLayoutObject())
         .RecordHitTestData(paint_info, ToPixelSnappedRect(border_box),
                            display_item_client);
   }
@@ -1586,7 +1588,7 @@
   // Paint the background of the `::first-line` line box.
   if (NGLineBoxFragmentPainter::NeedsPaint(line_box_fragment)) {
     NGLineBoxFragmentPainter line_box_painter(line_box_fragment, line_box_item,
-                                              PhysicalFragment());
+                                              GetPhysicalFragment());
     line_box_painter.PaintBackgroundBorderShadow(paint_info, child_offset);
   }
 }
@@ -1657,7 +1659,7 @@
 
   // Only paint backplates behind text when forced-color-adjust is auto and the
   // element is visible.
-  const ComputedStyle& style = PhysicalFragment().Style();
+  const ComputedStyle& style = GetPhysicalFragment().Style();
   if (style.ForcedColorAdjust() != EForcedColorAdjust::kAuto ||
       style.Visibility() != EVisibility::kVisible)
     return;
@@ -1667,7 +1669,7 @@
           DisplayItem::kForcedColorsModeBackplate))
     return;
 
-  Color backplate_color = PhysicalFragment()
+  Color backplate_color = GetPhysicalFragment()
                               .GetLayoutObject()
                               ->GetDocument()
                               .GetStyleEngine()
@@ -1843,7 +1845,7 @@
     const PhysicalRect& rect) {
   PhysicalRect scrolled_paint_rect = rect;
   GraphicsContext& context = paint_info.context;
-  const NGPhysicalBoxFragment& physical = PhysicalFragment();
+  const NGPhysicalBoxFragment& physical = GetPhysicalFragment();
 
   // Clip to the overflow area.
   if (info.is_clipped_with_local_scrolling &&
@@ -1863,15 +1865,15 @@
 }
 
 PhysicalBoxStrut NGBoxFragmentPainter::ComputeBorders() const {
-  return PhysicalFragment().Borders();
+  return GetPhysicalFragment().Borders();
 }
 
 PhysicalBoxStrut NGBoxFragmentPainter::ComputePadding() const {
-  return PhysicalFragment().Padding();
+  return GetPhysicalFragment().Padding();
 }
 
 PhysicalBoxStrut NGBoxFragmentPainter::ComputeMargins() const {
-  return PhysicalFragment().Margins();
+  return GetPhysicalFragment().Margins();
 }
 
 BoxPainterBase::FillLayerInfo NGBoxFragmentPainter::GetFillLayerInfo(
@@ -1879,7 +1881,7 @@
     const FillLayer& bg_layer,
     BackgroundBleedAvoidance bleed_avoidance,
     bool is_painting_background_in_contents_space) const {
-  const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+  const NGPhysicalBoxFragment& fragment = GetPhysicalFragment();
   const ComputedStyle& style = fragment.Style();
   RespectImageOrientationEnum respect_orientation = style.ImageOrientation();
   if (auto* style_image = bg_layer.GetImage()) {
@@ -1937,7 +1939,7 @@
 
 bool NGBoxFragmentPainter::NodeAtPoint(const HitTestContext& hit_test,
                                        const PhysicalOffset& physical_offset) {
-  const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+  const NGPhysicalBoxFragment& fragment = GetPhysicalFragment();
   // TODO(mstensho): Make sure that we never create an NGBoxFragmentPainter for
   // a fragment that doesn't intersect, and turn this into a DCHECK.
   if (!fragment.MayIntersect(*hit_test.result, hit_test.location,
@@ -1964,7 +1966,7 @@
     // foreground rect for intersection if a layer is self painting,
     // so only do the overflow clip check here for non-self-painting layers.
     if (!box_fragment_.HasSelfPaintingLayer() &&
-        !hit_test.location.Intersects(PhysicalFragment().OverflowClipRect(
+        !hit_test.location.Intersects(GetPhysicalFragment().OverflowClipRect(
             physical_offset, kExcludeOverlayScrollbarSizeForHitTesting))) {
       skip_children = true;
     }
@@ -1984,7 +1986,7 @@
       const PhysicalOffset scrolled_offset =
           physical_offset -
           PhysicalOffset(
-              PhysicalFragment().PixelSnappedScrolledContentOffset());
+              GetPhysicalFragment().PixelSnappedScrolledContentOffset());
       HitTestContext adjusted_hit_test{hit_test.phase, hit_test.location,
                                        scrolled_offset, hit_test.result};
       if (HitTestChildren(adjusted_hit_test, scrolled_offset))
@@ -2001,8 +2003,8 @@
   if (hit_test_self) {
     // Table row and table section are never a hit target.
     // SVG <text> is not a hit target except if 'pointer-events: bounding-box'.
-    if (PhysicalFragment().IsTableRow() ||
-        PhysicalFragment().IsTableSection()) {
+    if (GetPhysicalFragment().IsTableRow() ||
+        GetPhysicalFragment().IsTableSection()) {
       hit_test_self = false;
     } else if (fragment.IsSvgText()) {
       pointer_events_bounding_box =
@@ -2041,7 +2043,7 @@
     }
     if (UNLIKELY(pointer_events_bounding_box)) {
       bounds_rect = PhysicalRect::EnclosingRect(
-          PhysicalFragment().GetLayoutObject()->ObjectBoundingBox());
+          GetPhysicalFragment().GetLayoutObject()->ObjectBoundingBox());
     }
     // TODO(kojii): Don't have good explanation why only inline box needs to
     // snap, but matches to legacy and fixes crbug.com/976606.
@@ -2075,7 +2077,7 @@
 bool NGBoxFragmentPainter::UpdateHitTestResultForView(
     const PhysicalRect& bounds_rect,
     const HitTestContext& hit_test) const {
-  const LayoutObject* layout_object = PhysicalFragment().GetLayoutObject();
+  const LayoutObject* layout_object = GetPhysicalFragment().GetLayoutObject();
   if (!layout_object || !layout_object->IsLayoutView() ||
       hit_test.result->InnerNode()) {
     return false;
@@ -2083,7 +2085,7 @@
   auto* element = layout_object->GetDocument().documentElement();
   if (!element)
     return false;
-  const auto children = PhysicalFragment().Children();
+  const auto children = GetPhysicalFragment().Children();
   auto it = base::ranges::find(children, element, &NGPhysicalFragment::GetNode);
   if (it == children.end())
     return false;
@@ -2168,9 +2170,10 @@
   if (!hit_test.location.Intersects(overflow_rect))
     return false;
 
-  if (HitTestChildren(hit_test, PhysicalFragment(),
-                      cursor.CursorForDescendants(), physical_offset))
+  if (HitTestChildren(hit_test, GetPhysicalFragment(),
+                      cursor.CursorForDescendants(), physical_offset)) {
     return true;
+  }
 
   if (hit_test.phase != HitTestPhase::kForeground)
     return false;
@@ -2209,9 +2212,10 @@
     HitTestResult result;
     HitTestContext hit_test_float{HitTestPhase::kFloat, hit_test.location,
                                   hit_test.inline_root_offset, &result};
-    if (HitTestChildren(hit_test_float, PhysicalFragment(),
-                        cursor.CursorForDescendants(), physical_offset))
+    if (HitTestChildren(hit_test_float, GetPhysicalFragment(),
+                        cursor.CursorForDescendants(), physical_offset)) {
       return false;
+    }
   }
 
   // |physical_offset| is inside line, but
@@ -2318,13 +2322,13 @@
   if (UNLIKELY(inline_box_cursor_)) {
     InlineCursor descendants = inline_box_cursor_->CursorForDescendants();
     if (descendants) {
-      return HitTestChildren(hit_test, PhysicalFragment(), descendants,
+      return HitTestChildren(hit_test, GetPhysicalFragment(), descendants,
                              accumulated_offset);
     }
     return false;
   }
   if (items_) {
-    const NGPhysicalBoxFragment& fragment = PhysicalFragment();
+    const NGPhysicalBoxFragment& fragment = GetPhysicalFragment();
     InlineCursor cursor(fragment, *items_);
     return HitTestChildren(hit_test, fragment, cursor, accumulated_offset);
   }
@@ -2611,7 +2615,7 @@
     const HitTestLocation& hit_test_location,
     const PhysicalOffset& border_box_location) const {
   const ComputedStyle& style = box_fragment_.Style();
-  PhysicalRect rect(PhysicalOffset(), PhysicalFragment().Size());
+  PhysicalRect rect(PhysicalOffset(), GetPhysicalFragment().Size());
   rect.Move(border_box_location);
   return !hit_test_location.Intersects(
       RoundedBorderGeometry::PixelSnappedRoundedBorder(
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
index f2655a76..98a77683 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h
@@ -300,7 +300,7 @@
   bool UpdateHitTestResultForView(const PhysicalRect& bounds_rect,
                                   const HitTestContext& hit_test) const;
 
-  const NGPhysicalBoxFragment& PhysicalFragment() const {
+  const NGPhysicalBoxFragment& GetPhysicalFragment() const {
     return box_fragment_;
   }
   const DisplayItemClient& GetDisplayItemClient() const {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
index 29b7f98d..3be9314 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_fragment_painter.cc
@@ -21,7 +21,7 @@
   VectorOutlineRectCollector collector;
   LayoutObject::OutlineInfo info;
   fragment.AddSelfOutlineRects(
-      paint_offset, style_to_use.OutlineRectsShouldIncludeBlockVisualOverflow(),
+      paint_offset, style_to_use.OutlineRectsShouldIncludeBlockInkOverflow(),
       collector, &info);
 
   VectorOf<PhysicalRect> outline_rects = collector.TakeRects();
@@ -51,7 +51,7 @@
     return;
 
   auto outline_rects = fragment.GetLayoutObject()->OutlineRects(
-      nullptr, paint_offset, NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, paint_offset, OutlineType::kIncludeBlockInkOverflow);
   gfx::Rect rect = ToPixelSnappedRect(UnionRect(outline_rects));
   if (rect.IsEmpty())
     return;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
index 672c073..5fa4080 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
@@ -50,7 +50,7 @@
 }  // namespace
 
 PhysicalBoxSides NGInlineBoxFragmentPainter::SidesToInclude() const {
-  return PhysicalFragment().SidesToInclude();
+  return BoxFragment().SidesToInclude();
 }
 
 void NGInlineBoxFragmentPainter::Paint(const PaintInfo& paint_info,
@@ -79,7 +79,7 @@
                                                      inline_context_);
   DCHECK(inline_box_cursor_);
   NGBoxFragmentPainter box_painter(*inline_box_cursor_, inline_box_item_,
-                                   PhysicalFragment(), inline_context_);
+                                   BoxFragment(), inline_context_);
   box_painter.PaintObject(paint_info, adjusted_paint_offset,
                           suppress_box_decoration_background);
 }
@@ -108,7 +108,7 @@
 
   DCHECK(inline_box_cursor_);
   NGBoxFragmentPainter box_painter(*inline_box_cursor_, inline_box_item_,
-                                   PhysicalFragment(), inline_context_);
+                                   BoxFragment(), inline_context_);
 
   BackgroundImageGeometry geometry(
       static_cast<const LayoutBoxModelObject&>(layout_object));
@@ -220,7 +220,7 @@
   // the height of inline box does not. The box "behaves similar to that of an
   // inline-level element".
   // https://drafts.csswg.org/css-pseudo-4/#first-line-styling
-  const PhysicalLineBoxFragment& line_box = PhysicalFragment();
+  const PhysicalLineBoxFragment& line_box = LineBoxFragment();
   const FontHeight line_metrics = line_box.Metrics();
   const FontHeight text_metrics = line_style_.GetFontHeight();
   const WritingMode writing_mode = line_style_.GetWritingMode();
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
index 81ad23d..4786c21c 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
@@ -198,7 +198,7 @@
  private:
   void PaintMask(const PaintInfo&, const PhysicalOffset& paint_offset);
 
-  const NGPhysicalBoxFragment& PhysicalFragment() const {
+  const NGPhysicalBoxFragment& BoxFragment() const {
     return static_cast<const NGPhysicalBoxFragment&>(inline_box_fragment_);
   }
 
@@ -261,7 +261,7 @@
     DCHECK(layout_block_flow.IsLayoutNGObject());
   }
 
-  const PhysicalLineBoxFragment& PhysicalFragment() const {
+  const PhysicalLineBoxFragment& LineBoxFragment() const {
     return static_cast<const PhysicalLineBoxFragment&>(inline_box_fragment_);
   }
 
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc
index e6b655fd..ff1c4b9 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_combine_painter.cc
@@ -102,7 +102,7 @@
   // Setup arguments for painting text decorations
   TextDecorationInfo decoration_info(text_origin_, width, style_,
                                      /* inline_context */ nullptr, {});
-  const NGTextDecorationOffset decoration_offset(style_);
+  const TextDecorationOffset decoration_offset(style_);
 
   // Paint underline and overline text decorations
   PaintUnderOrOverLineDecorations(NGTextFragmentPaintInfo{}, decoration_offset,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
index ef52c88..5ce9dd96 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_painter.cc
@@ -276,7 +276,7 @@
                                   ~TextDecorationLine::kLineThrough))
     return;
 
-  const NGTextDecorationOffset decoration_offset(text_item.Style());
+  const TextDecorationOffset decoration_offset(text_item.Style());
 
   if (svg_text_paint_state_.has_value() &&
       !decoration_info.HasDecorationOverride()) {
@@ -448,7 +448,7 @@
 
 void NGTextPainter::PaintSvgDecorationsExceptLineThrough(
     const NGTextFragmentPaintInfo& fragment_paint_info,
-    const NGTextDecorationOffset& decoration_offset,
+    const TextDecorationOffset& decoration_offset,
     TextDecorationInfo& decoration_info,
     TextDecorationLine lines_to_paint,
     const PaintInfo& paint_info,
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_painter.h b/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
index e5f3a037..6d74430 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_painter.h
@@ -137,7 +137,7 @@
                             const AutoDarkMode& auto_dark_mode);
   void PaintSvgDecorationsExceptLineThrough(
       const NGTextFragmentPaintInfo&,
-      const NGTextDecorationOffset& decoration_offset,
+      const TextDecorationOffset& decoration_offset,
       TextDecorationInfo& decoration_info,
       TextDecorationLine lines_to_paint,
       const PaintInfo& paint_info,
diff --git a/third_party/blink/renderer/core/paint/object_painter.cc b/third_party/blink/renderer/core/paint/object_painter.cc
index 649f2b9..c7cea66 100644
--- a/third_party/blink/renderer/core/paint/object_painter.cc
+++ b/third_party/blink/renderer/core/paint/object_painter.cc
@@ -39,7 +39,7 @@
   LayoutObject::OutlineInfo info;
   auto outline_rects = layout_object_.OutlineRects(
       &info, paint_offset,
-      style_to_use.OutlineRectsShouldIncludeBlockVisualOverflow());
+      style_to_use.OutlineRectsShouldIncludeBlockInkOverflow());
   if (outline_rects.empty())
     return;
 
@@ -73,7 +73,7 @@
     return;
 
   auto outline_rects = layout_object_.OutlineRects(
-      nullptr, paint_offset, NGOutlineType::kIncludeBlockVisualOverflow);
+      nullptr, paint_offset, OutlineType::kIncludeBlockInkOverflow);
   gfx::Rect bounding_rect = ToPixelSnappedRect(UnionRect(outline_rects));
   if (bounding_rect.IsEmpty()) {
     return;
diff --git a/third_party/blink/renderer/core/paint/outline_painter_test.cc b/third_party/blink/renderer/core/paint/outline_painter_test.cc
index 94cacbdb..957b04a8 100644
--- a/third_party/blink/renderer/core/paint/outline_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/outline_painter_test.cc
@@ -41,7 +41,7 @@
   )HTML");
   LayoutObject::OutlineInfo info;
   GetLayoutObjectByElementId("target")->OutlineRects(
-      &info, PhysicalOffset(), NGOutlineType::kDontIncludeBlockVisualOverflow);
+      &info, PhysicalOffset(), OutlineType::kDontIncludeBlockInkOverflow);
   const auto& style = GetLayoutObjectByElementId("target")->StyleRef();
   EXPECT_TRUE(style.HasOutline());
   EXPECT_EQ(LayoutUnit::Max().ToInt() * 2,
diff --git a/third_party/blink/renderer/core/paint/text_decoration_info.cc b/third_party/blink/renderer/core/paint/text_decoration_info.cc
index 3c12404..fbcdfbb 100644
--- a/third_party/blink/renderer/core/paint/text_decoration_info.cc
+++ b/third_party/blink/renderer/core/paint/text_decoration_info.cc
@@ -458,7 +458,7 @@
 }
 
 void TextDecorationInfo::SetUnderlineLineData(
-    const NGTextDecorationOffset& decoration_offset) {
+    const TextDecorationOffset& decoration_offset) {
   DCHECK(HasUnderline());
   // Don't apply text-underline-offset to overlines. |line_offset| is zero.
   const Length line_offset = UNLIKELY(flip_underline_and_overline_)
@@ -475,7 +475,7 @@
 }
 
 void TextDecorationInfo::SetOverlineLineData(
-    const NGTextDecorationOffset& decoration_offset) {
+    const TextDecorationOffset& decoration_offset) {
   DCHECK(HasOverline());
   // Don't apply text-underline-offset to overline.
   const Length line_offset = UNLIKELY(flip_underline_and_overline_)
@@ -502,7 +502,7 @@
 }
 
 void TextDecorationInfo::SetSpellingOrGrammarErrorLineData(
-    const NGTextDecorationOffset& decoration_offset) {
+    const TextDecorationOffset& decoration_offset) {
   DCHECK(HasSpellingOrGrammerError());
   DCHECK(!HasUnderline());
   DCHECK(!HasOverline());
diff --git a/third_party/blink/renderer/core/paint/text_decoration_info.h b/third_party/blink/renderer/core/paint/text_decoration_info.h
index c396030c..2763561f 100644
--- a/third_party/blink/renderer/core/paint/text_decoration_info.h
+++ b/third_party/blink/renderer/core/paint/text_decoration_info.h
@@ -27,8 +27,8 @@
 class Font;
 class NGDecoratingBox;
 class NGInlinePaintContext;
-class NGTextDecorationOffset;
 class SimpleFontData;
+class TextDecorationOffset;
 
 enum class ResolvedUnderlinePosition {
   kNearAlphabeticBaselineAuto,
@@ -101,10 +101,10 @@
   // through. Must be called before trying to paint or compute bounds
   // for a line.
   void SetLineData(TextDecorationLine line, float line_offset);
-  void SetUnderlineLineData(const NGTextDecorationOffset& decoration_offset);
-  void SetOverlineLineData(const NGTextDecorationOffset& decoration_offset);
+  void SetUnderlineLineData(const TextDecorationOffset& decoration_offset);
+  void SetOverlineLineData(const TextDecorationOffset& decoration_offset);
   void SetLineThroughLineData();
-  void SetSpellingOrGrammarErrorLineData(const NGTextDecorationOffset&);
+  void SetSpellingOrGrammarErrorLineData(const TextDecorationOffset&);
 
   // These methods do not depend on |SetDecorationIndex|.
   LayoutUnit Width() const { return width_; }
diff --git a/third_party/blink/renderer/core/paint/text_painter_base.cc b/third_party/blink/renderer/core/paint/text_painter_base.cc
index 0ab09849..8c213af 100644
--- a/third_party/blink/renderer/core/paint/text_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/text_painter_base.cc
@@ -247,7 +247,7 @@
 //   3. Paint line through
 void TextPainterBase::PaintUnderOrOverLineDecorations(
     const NGTextFragmentPaintInfo& fragment_paint_info,
-    const NGTextDecorationOffset& decoration_offset,
+    const TextDecorationOffset& decoration_offset,
     TextDecorationInfo& decoration_info,
     TextDecorationLine lines_to_paint,
     const PaintInfo& paint_info,
@@ -282,7 +282,7 @@
 
 void TextPainterBase::PaintUnderOrOverLineDecorationShadows(
     const NGTextFragmentPaintInfo& fragment_paint_info,
-    const NGTextDecorationOffset& decoration_offset,
+    const TextDecorationOffset& decoration_offset,
     TextDecorationInfo& decoration_info,
     TextDecorationLine lines_to_paint,
     const cc::PaintFlags* flags,
@@ -321,7 +321,7 @@
 
 void TextPainterBase::PaintUnderOrOverLineDecorations(
     const NGTextFragmentPaintInfo& fragment_paint_info,
-    const NGTextDecorationOffset& decoration_offset,
+    const TextDecorationOffset& decoration_offset,
     TextDecorationInfo& decoration_info,
     TextDecorationLine lines_to_paint,
     const cc::PaintFlags* flags,
diff --git a/third_party/blink/renderer/core/paint/text_painter_base.h b/third_party/blink/renderer/core/paint/text_painter_base.h
index 1007a2c..687fd09 100644
--- a/third_party/blink/renderer/core/paint/text_painter_base.h
+++ b/third_party/blink/renderer/core/paint/text_painter_base.h
@@ -110,7 +110,7 @@
   //   3. Paint line through text decoration
   void PaintUnderOrOverLineDecorations(
       const NGTextFragmentPaintInfo& fragment_paint_info,
-      const NGTextDecorationOffset& decoration_offset,
+      const TextDecorationOffset& decoration_offset,
       TextDecorationInfo& decoration_info,
       TextDecorationLine lines_to_paint,
       const PaintInfo& paint_info,
@@ -142,7 +142,7 @@
 
   void PaintUnderOrOverLineDecorationShadows(
       const NGTextFragmentPaintInfo& fragment_paint_info,
-      const NGTextDecorationOffset& decoration_offset,
+      const TextDecorationOffset& decoration_offset,
       TextDecorationInfo& decoration_info,
       TextDecorationLine lines_to_paint,
       const cc::PaintFlags* flags,
@@ -151,7 +151,7 @@
 
   void PaintUnderOrOverLineDecorations(
       const NGTextFragmentPaintInfo& fragment_paint_info,
-      const NGTextDecorationOffset& decoration_offset,
+      const TextDecorationOffset& decoration_offset,
       TextDecorationInfo& decoration_info,
       TextDecorationLine lines_to_paint,
       const cc::PaintFlags* flags,
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
index 23c91559..2473ab0 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -233,6 +233,23 @@
   QueueUpdateSpeculationCandidates();
 
   probe::DidAddSpeculationRuleSet(*GetSupplementable(), *rule_set);
+
+  if (!rule_set->source()->IsFromBrowserInjected()) {
+    HeapVector<Member<SpeculationRuleSet>> to_remove;
+    for (const auto& other_rule_set : rule_sets_) {
+      if (other_rule_set->source()->IsFromBrowserInjected()) {
+        to_remove.push_back(other_rule_set);
+      }
+    }
+
+    if (!to_remove.empty()) {
+      UseCounter::Count(GetSupplementable(),
+                        WebFeature::kAutoSpeculationRulesOptedOut);
+      for (const auto& to_remove_rule_set : to_remove) {
+        RemoveRuleSet(to_remove_rule_set);
+      }
+    }
+  }
 }
 
 void DocumentSpeculationRules::RemoveRuleSet(SpeculationRuleSet* rule_set) {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index b889f8e..aac32db 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -649,12 +649,11 @@
 
   // For history and compatibility reasons, we draw outline:auto (for focus
   // rings) and normal style outline differently.
-  // Focus rings enclose block visual overflows (of line boxes and descendants),
+  // Focus rings enclose block ink overflows (of line boxes and descendants),
   // while normal outlines don't.
-  NGOutlineType OutlineRectsShouldIncludeBlockVisualOverflow() const {
-    return OutlineStyleIsAuto()
-               ? NGOutlineType::kIncludeBlockVisualOverflow
-               : NGOutlineType::kDontIncludeBlockVisualOverflow;
+  OutlineType OutlineRectsShouldIncludeBlockInkOverflow() const {
+    return OutlineStyleIsAuto() ? OutlineType::kIncludeBlockInkOverflow
+                                : OutlineType::kDontIncludeBlockInkOverflow;
   }
 
   // position-fallback
diff --git a/third_party/blink/renderer/modules/formatted_text/formatted_text.cc b/third_party/blink/renderer/modules/formatted_text/formatted_text.cc
index 7527be0..ccb1102 100644
--- a/third_party/blink/renderer/modules/formatted_text/formatted_text.cc
+++ b/third_party/blink/renderer/modules/formatted_text/formatted_text.cc
@@ -193,9 +193,9 @@
   LogicalSize available_size = {inline_constraint_, block_constraint_};
   builder.SetAvailableSize(available_size);
   ConstraintSpace space = builder.ToConstraintSpace();
-  const NGLayoutResult* block_results = block_node.Layout(space, nullptr);
+  const LayoutResult* block_results = block_node.Layout(space, nullptr);
   const auto& fragment =
-      To<NGPhysicalBoxFragment>(block_results->PhysicalFragment());
+      To<NGPhysicalBoxFragment>(block_results->GetPhysicalFragment());
   block_->RecalcVisualOverflow();
   bounds = gfx::RectF{block_->VisualOverflowRect()};
   auto* paint_record_builder = MakeGarbageCollected<PaintRecordBuilder>();
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
index 1eb6a64..9ec120b 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -991,7 +991,8 @@
     }
   }
   DCHECK_EQ(allocation.GetSumBps(), parameters.bitrate.get_sum_bps());
-  video_encoder_->RequestEncodingParametersChange(allocation, framerate);
+  video_encoder_->RequestEncodingParametersChange(allocation, framerate,
+                                                  absl::nullopt);
 }
 
 void RTCVideoEncoder::Impl::RecordTimestampMatchUMA() const {
diff --git a/third_party/blink/web_tests/ChromeTestExpectations b/third_party/blink/web_tests/ChromeTestExpectations
index 1f527fc7..fb75d35 100644
--- a/third_party/blink/web_tests/ChromeTestExpectations
+++ b/third_party/blink/web_tests/ChromeTestExpectations
@@ -34,6 +34,7 @@
 external/wpt/webdriver/tests/bidi/browsing_context/traverse_history/context.py [ Failure ]
 external/wpt/webdriver/tests/bidi/browsing_context/traverse_history/delta.py [ Failure ]
 external/wpt/webdriver/tests/bidi/browsing_context/traverse_history/invalid.py [ Failure ]
+external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py [ Failure ]
 
 # Chrome specific failures
 crbug.com/1499775 external/wpt/css/css-text/text-transform/text-transform-capitalize-014.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 3ee7d7d..b9490d4 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1547,7 +1547,6 @@
 crbug.com/1488371 virtual/deprecate-unload/http/tests/xmlhttprequest/frame-load-cancelled-abort.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/http/tests/xmlhttprequest/frame-unload-abort-crash.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/document-picture-in-picture/clears-session-on-close.https.html [ Failure Skip Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/navigating-across-documents/navigate-to-unparseable-url.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/001.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/unloading-documents/002.html [ Failure Skip Timeout ]
@@ -1561,7 +1560,6 @@
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/close-method.window.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/open-close/close_unload.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/browsers/the-window-object/self-et-al.window.html [ Failure Skip Timeout ]
-crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-origin.sub.window.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-exception-vs-return-xml.window.html [ Failure Skip Timeout ]
 crbug.com/1488371 virtual/deprecate-unload/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.html [ Failure Skip Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 0dae889..e65d264 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -6524,6 +6524,13 @@
        {}
       ]
      ],
+     "first-letter-contributed-to-ancestor.html": [
+      "f50841d94a781cddb8bc49ec446b6c04803e5f1b",
+      [
+       null,
+       {}
+      ]
+     ],
      "fixed-pos-children.html": [
       "773439d6f3e9bd29d0e56fe2f06f9b446804e8e1",
       [
@@ -283423,6 +283430,32 @@
         {}
        ]
       ],
+      "use-data-url-set-attributeName.tentative.svg": [
+       "248f218bd792e1ffd07711095b3612c45ecb7a6c",
+       [
+        null,
+        [
+         [
+          "/svg/struct/reftests/reference/green-100x100.svg",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "use-data-url-setAttribute.tentative.html": [
+       "b28dd0ecf5b9e798ad8af8c5d6e2c01aea07b7e6",
+       [
+        null,
+        [
+         [
+          "/svg/struct/reftests/reference/green-100x100.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "use-data-url.tentative.svg": [
        "04414030a3e65ee05314386e90e75184e8c80042",
        [
@@ -283501,6 +283534,19 @@
         {}
        ]
       ],
+      "use-ref-inside-data-url.tentative.html": [
+       "d6ac2e3654a6f1ae2591c47415b38f8c279b3b37",
+       [
+        null,
+        [
+         [
+          "/svg/struct/reftests/reference/green-100x100.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "use-same-origin.svg": [
        "0aa1ec83afd68b3ea6022d33f6ec6f8103d99661",
        [
@@ -366617,6 +366663,10 @@
        "select-willvalidate-readonly-attribute-expected.txt": [
         "33210c7ac09736ca139ba7c0f8924bcb6d8c152a",
         []
+       ],
+       "show-picker-being-rendered-expected.txt": [
+        "b3b679ac010e3faec753aa2de379ccec67198060",
+        []
        ]
       },
       "the-selectlist-element": {
@@ -460865,6 +460915,13 @@
         {}
        ]
       ],
+      "rotate-parsing-computed.html": [
+       "ae1cade666c7f218caaa29a37251aa7f0911da25",
+       [
+        null,
+        {}
+       ]
+      ],
       "rotate-parsing-invalid.html": [
        "4b6d7cf2ad5f21091e3bd8d47388d28ae964d73a",
        [
@@ -460879,6 +460936,13 @@
         {}
        ]
       ],
+      "scale-parsing-computed.html": [
+       "e01550b396f49771726761e66da2432e09878fb7",
+       [
+        null,
+        {}
+       ]
+      ],
       "scale-parsing-invalid.html": [
        "a36db1b5a968694a581dea645f82b6b13ad9634a",
        [
@@ -460956,6 +461020,13 @@
         {}
        ]
       ],
+      "translate-parsing-computed.html": [
+       "a88cc652fa4a9d5e59b128a97c81c1a1df5388e7",
+       [
+        null,
+        {}
+       ]
+      ],
       "translate-parsing-invalid.html": [
        "d47cd5b6961ecd25092b38f7c1cb947fdf3756b1",
        [
@@ -563888,6 +563959,15 @@
          {}
         ]
        ],
+       "show-picker-being-rendered.html": [
+        "e7be4aea526f2b13fcc80dec9bd4c62d8d8b6611",
+        [
+         null,
+         {
+          "testdriver": true
+         }
+        ]
+       ],
        "show-picker-cross-origin-iframe.tentative.html": [
         "3f710b39c60beb205ac131929849442fac2cf430",
         [
@@ -563925,7 +564005,7 @@
         ]
        ],
        "show-picker-user-gesture.tentative.html": [
-        "24ccd72c8ae83d4fbad2bebd271869b83b494c71",
+        "e917fe2a612d937e3c1ae429633f0d6ec415ac28",
         [
          null,
          {
@@ -695799,14 +695879,14 @@
        },
        "set_viewport": {
         "device_pixel_ratio.py": [
-         "604c96685567fb60d3233d7646db4459ead68e03",
+         "e4db779bd5dd5492af4997531fdc9c397718795b",
          [
           null,
           {}
          ]
         ],
         "invalid.py": [
-         "b918deb668c7f299095a08046f607c1f30780c6a",
+         "2a90af4da0b1b6e63b5cb01d4e9f013e287a8fe1",
          [
           null,
           {
@@ -695814,8 +695894,8 @@
           }
          ]
         ],
-        "set_viewport.py": [
-         "51203db1d61c159399c7574c2aaecfc79f8a3c85",
+        "viewport.py": [
+         "60f9e47040fc23f5f741ddd87128103227b3cb11",
          [
           null,
           {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/rotate-parsing-computed.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/rotate-parsing-computed.html
new file mode 100644
index 0000000..ae1cade
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/rotate-parsing-computed.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Transform Module Level 2: rotate computed values.</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-rotate">
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<meta name="assert" content="rotate supports the full grammar 'none | <number>{3}? <angle>'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization
+
+// Serialize as the keyword none if and only if none was originally specified.
+test_computed_value("rotate", "none");
+
+// If a 2d rotation is specified, the property must serialize as just an <angle>.
+test_computed_value("rotate", "0deg");
+
+// If a 3d rotation is specified, the property must serialize with an axis specified.
+test_computed_value("rotate", "100 200 300 400grad", "100 200 300 360deg");
+test_computed_value("rotate", "400grad 100 200 300", "100 200 300 360deg");
+test_computed_value("rotate", "0 0 0 400grad", "0 0 0 360deg");
+
+// If the axis is parallel with the x or y axis, it must serialize as the appropriate keyword.
+test_computed_value("rotate", "x 400grad", "x 360deg");
+test_computed_value("rotate", "400grad x", "x 360deg");
+test_computed_value("rotate", "0.5 0 0 400grad", "x 360deg");
+test_computed_value("rotate", "1 0 0 400grad", "x 360deg");
+
+test_computed_value("rotate", "y 400grad", "y 360deg");
+test_computed_value("rotate", "400grad y", "y 360deg");
+test_computed_value("rotate", "0 0.5 0 400grad", "y 360deg");
+test_computed_value("rotate", "0 1 0 400grad", "y 360deg");
+
+// If the axis is parallel with the z axis the property must serialize as just an <angle>.
+test_computed_value("rotate", "400grad", "360deg");
+test_computed_value("rotate", "400grad z", "360deg");
+test_computed_value("rotate", "0 0 0.5 400grad", "360deg");
+test_computed_value("rotate", "0 0 1 400grad", "360deg");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/scale-parsing-computed.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/scale-parsing-computed.html
new file mode 100644
index 0000000..e01550b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/scale-parsing-computed.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Transform Module Level 2: scale computed values.</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-scale">
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<meta name="assert" content="scale supports the full grammar 'none | <number>{1,3}'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("scale", "none");
+
+test_computed_value("scale", "1");
+test_computed_value("scale", "1%", "0.01");
+
+test_computed_value("scale", "100");
+test_computed_value("scale", "100%", "1");
+test_computed_value("scale", "100 100", "100");
+test_computed_value("scale", "100% 100%", "1");
+test_computed_value("scale", "100 100 1", "100");
+test_computed_value("scale", "100% 100% 1", "1");
+
+test_computed_value("scale", "-100");
+test_computed_value("scale", "-100%", "-1");
+test_computed_value("scale", "-100 -100", "-100");
+test_computed_value("scale", "-100% -100%", "-1");
+test_computed_value("scale", "-100 -100 1", "-100");
+test_computed_value("scale", "-100% -100% 1", "-1");
+
+test_computed_value("scale", "100 200");
+test_computed_value("scale", "100% 200%", "1 2");
+test_computed_value("scale", "100 200 1", "100 200");
+test_computed_value("scale", "100% 200% 1", "1 2");
+test_computed_value("scale", "100 200 300");
+test_computed_value("scale", "100 100 2", "100 100 2");
+test_computed_value("scale", "100% 200% 300%", "1 2 3");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/translate-parsing-computed.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/translate-parsing-computed.html
new file mode 100644
index 0000000..a88cc65
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/parsing/translate-parsing-computed.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Transform Module Level 2: translate computed values.</title>
+<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#propdef-translate">
+<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+<meta name="assert" content="translate supports the full grammar 'none | <length-percentage> [ <length-percentage> <length>? ]?'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("translate", "none");
+
+test_computed_value("translate", "0px");
+test_computed_value("translate", "100%");
+
+test_computed_value("translate", "100px 0px", "100px");
+test_computed_value("translate", "100px 0.1px", "100px 0.1px");
+test_computed_value("translate", "100px 0%");
+test_computed_value("translate", "100px calc(10px - 10%)", "100px calc(-10% + 10px)");
+test_computed_value("translate", "100px 200%");
+test_computed_value("translate", "100% 200px");
+
+test_computed_value("translate", "100px 200px 0px", "100px 200px");
+test_computed_value("translate", "100px 0px 300px", "100px 0px 300px");
+test_computed_value("translate", "100px 0px 0px", "100px");
+test_computed_value("translate", "100px 200px 300px");
+test_computed_value("translate", "100% 200% 300px");
+
+test_computed_value("translate", "100% 0% 200px", "100% 0% 200px");
+test_computed_value("translate", "0% 0% 100px", "0% 0% 100px");
+test_computed_value("translate", "0em 0em 100px", "0px 0px 100px");
+
+test_computed_value("translate", "0", "0px");
+test_computed_value("translate", "1px 2px 0", "1px 2px");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.js b/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.js
index ca3028d..a8519b5d 100644
--- a/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.js
@@ -21,9 +21,9 @@
       <body></body>
       `;
 
-      const popup_unloaded = new Promise(r => window.popup.onunload = e => r());
+      const popup_navigated = new Promise(r => window.popup.onpagehide = e => r());
       document.body.append(iframe);
-      await popup_unloaded;  // This makes sure the old child has unloaded, but
+      await popup_navigated;  // This makes sure the old child has unloaded, but
                              // with the timeout below it's really not needed.
 
       // This is necessary, or else the test times out. The about:blank load
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered-expected.txt
new file mode 100644
index 0000000..b3b679ac0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+[FAIL] select showPicker() throws when not being rendered
+  assert_throws_dom: function "() => { select.showPicker(); }" did not throw
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered.html
new file mode 100644
index 0000000..e7be4ae
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-being-rendered.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Test showPicker() being rendered requirement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<select id="select" style="display: none;">
+    <option>Item 1</option>
+</select>
+<script>
+promise_test(async t => {
+    await test_driver.bless('show picker');
+    assert_throws_dom('NotSupportedError', () => { select.showPicker(); });
+
+    // Test that dynamically changing to actually being rendered works.
+    await test_driver.bless('show picker');
+    select.style.display = 'inline-block';
+    select.showPicker();
+    select.blur();
+}, 'select showPicker() throws when not being rendered');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-user-gesture.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-user-gesture.tentative.html
index 24ccd72..e917fe2 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-user-gesture.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/show-picker-user-gesture.tentative.html
@@ -15,6 +15,7 @@
 
     promise_test(async t => {
         const select = document.createElement("select");
+        document.body.append(select)
 
         await test_driver.bless('show picker');
         select.showPicker();
diff --git a/third_party/blink/web_tests/external/wpt/mathml/crashtests/first-letter-contributed-to-ancestor.html b/third_party/blink/web_tests/external/wpt/mathml/crashtests/first-letter-contributed-to-ancestor.html
new file mode 100644
index 0000000..f50841d9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/crashtests/first-letter-contributed-to-ancestor.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1495811">
+<style>
+  math {
+    display: inline-block;
+  }
+  math::first-letter {
+    background-color: blue;
+  }
+</style>
+<math>
+  <mo id="mo">%</mo>
+</math>
+<script>
+  mo.appendChild(document.createTextNode("A"));
+  document.body.innerText += "";
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-set-attributeName.tentative.svg b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-set-attributeName.tentative.svg
new file mode 100644
index 0000000..248f218
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-set-attributeName.tentative.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <title>&#x3c;use&#x3e; with a data: URL resource loaded by &#x3c;set attributeName&#x3e;</title>
+  <h:link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseElementHrefAttribute"/>
+  <h:link rel="match" href="reference/green-100x100.svg"/>
+  <rect width="100" height="100" fill="green"/>
+  <use>
+    <set attributeName="href" to="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IGlkPSJyZWQtcmVjdCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9InJlZCIvPgo8L3N2Zz4=#red-rect"/>
+  </use>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-setAttribute.tentative.html b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-setAttribute.tentative.html
new file mode 100644
index 0000000..b28dd0e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-data-url-setAttribute.tentative.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+<meta charset="utf-8">
+<title>Testcase for changing a valid &#x3c;use&#x3e; to a data URL:</title>
+<link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseElementHrefAttribute">
+<link rel="match" href="reference/green-100x100.html">
+<script>
+  function go() {
+    const use = document.querySelector("use");
+    use.setAttribute("href", "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IGlkPSJvcmFuZ2UtcmVjdCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9Im9yYW5nZSIvPgo8L3N2Zz4=#orange-rect");
+  }
+</script>
+<body onload="go()">
+  <svg id="mySVG">
+    <rect id="red" width="100" height="100" fill="red"></rect>
+    <rect id="green" width="100" height="100" fill="green"></rect>
+    <use x="100" y="0" href="#red"></use>
+  </svg>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-ref-inside-data-url.tentative.html b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-ref-inside-data-url.tentative.html
new file mode 100644
index 0000000..d6ac2e3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/struct/reftests/use-ref-inside-data-url.tentative.html
@@ -0,0 +1,15 @@
+<!doctype HTML>
+<meta charset="utf-8">
+<title>Testcase for where SVG loaded via data: uses #ref</title>
+<link rel="help" href="https://svgwg.org/svg2-draft/struct.html#UseElementHrefAttribute">
+<link rel="match" href="reference/green-100x100.html">
+<body>
+<!-- base64 SVG source:
+<svg xmlns="http://www.w3.org/2000/svg">
+  <rect id="green-rect" width="100" height="100" fill="green"/>
+  <rect width="100" height="100" fill="red"/>
+  <use href="#green-rect"/>
+</svg>
+-->
+<img src="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KICA8cmVjdCBpZD0iZ3JlZW4tcmVjdCIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiIGZpbGw9ImdyZWVuIi8+DQogIDxyZWN0IHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJyZWQiLz4NCiAgPHVzZSBocmVmPSIjZ3JlZW4tcmVjdCIvPg0KPC9zdmc+">
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/device_pixel_ratio.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/device_pixel_ratio.py
index 604c966..e4db779 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/device_pixel_ratio.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/device_pixel_ratio.py
@@ -4,10 +4,16 @@
 
 
 @pytest.mark.asyncio
-@pytest.mark.parametrize("device_pixel_ratio", [1, 2])
-async def test_device_pixel_ratio_only(bidi_session, new_tab, device_pixel_ratio):
+@pytest.mark.parametrize("device_pixel_ratio", [0.5, 2])
+async def test_device_pixel_ratio_only(bidi_session, inline, new_tab, device_pixel_ratio):
     viewport = await get_viewport_dimensions(bidi_session, new_tab)
 
+    # Load a page so that reflow is triggered when changing the DPR
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         device_pixel_ratio=device_pixel_ratio)
@@ -17,12 +23,20 @@
 
 
 @pytest.mark.asyncio
-@pytest.mark.parametrize("device_pixel_ratio", [1, 2])
-async def test_device_pixel_ratio_with_viewport(bidi_session, new_tab, device_pixel_ratio):
+@pytest.mark.parametrize("device_pixel_ratio", [0.5, 2])
+async def test_device_pixel_ratio_with_viewport(
+    bidi_session, inline, new_tab, device_pixel_ratio
+):
     test_viewport = {"width": 250, "height": 300}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
 
+    # Load a page so that reflow is triggered when changing the DPR
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         viewport=test_viewport,
@@ -33,10 +47,16 @@
 
 
 @pytest.mark.asyncio
-async def test_reset_device_pixel_ratio(bidi_session, new_tab):
+async def test_reset_device_pixel_ratio(bidi_session, inline, new_tab):
     original_dpr = await get_device_pixel_ratio(bidi_session, new_tab)
     test_dpr = original_dpr + 1
 
+    # Load a page so that reflow is triggered when changing the DPR
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         device_pixel_ratio=test_dpr)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/invalid.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/invalid.py
index b918deb6..2a90af4 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/invalid.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/invalid.py
@@ -76,10 +76,18 @@
 @pytest.mark.parametrize("device_pixel_ratio", [False, "", {}, []])
 async def test_params_devicePixelRatio_invalid_type(bidi_session, new_tab,device_pixel_ratio):
     with pytest.raises(error.InvalidArgumentException):
-        await bidi_session.browsing_context.set_viewport(context=new_tab["context"], device_pixel_ratio=device_pixel_ratio)
+        await bidi_session.browsing_context.set_viewport(
+            context=new_tab["context"],
+            device_pixel_ratio=device_pixel_ratio,
+            viewport=None
+        )
 
 
 @pytest.mark.parametrize("device_pixel_ratio", [0, -1])
 async def test_params_devicePixelRatio_invalid_value(bidi_session, new_tab, device_pixel_ratio):
     with pytest.raises(error.InvalidArgumentException):
-        await bidi_session.browsing_context.set_viewport(context=new_tab["context"], device_pixel_ratio=device_pixel_ratio)
+        await bidi_session.browsing_context.set_viewport(
+            context=new_tab["context"],
+            device_pixel_ratio=device_pixel_ratio,
+            viewport=None
+        )
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/set_viewport.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
similarity index 69%
rename from third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/set_viewport.py
rename to third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
index 51203db..60f9e47 100644
--- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/set_viewport.py
+++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/browsing_context/set_viewport/viewport.py
@@ -3,6 +3,7 @@
 
 from ... import get_viewport_dimensions
 
+
 @pytest.mark.asyncio
 async def test_set_viewport(bidi_session, new_tab):
     test_viewport = {"width": 250, "height": 300}
@@ -17,11 +18,17 @@
 
 
 @pytest.mark.asyncio
-async def test_set_viewport_same_dimensions(bidi_session, new_tab):
-    test_viewport = {"width": 250, "height": 300}
+async def test_undefined_viewport(bidi_session, inline, new_tab):
+    test_viewport = {"width": 499, "height": 599}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
 
+    # Load a page so that reflow is triggered when changing the viewport
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         viewport=test_viewport)
@@ -30,19 +37,57 @@
 
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
-        viewport=test_viewport)
+        viewport=UNDEFINED)
 
     assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
 
 
 @pytest.mark.asyncio
-async def test_set_viewport_reset(bidi_session, new_tab):
+@pytest.mark.parametrize("width, height", [
+    (250, 300),
+    (500, 300),
+    (250, 600),
+    (500, 600)
+], ids=["none", "width", "height", "both"])
+async def test_modified_dimensions(bidi_session, inline, new_tab, width, height):
+    start_viewport = {"width": 250, "height": 300}
+
+    assert await get_viewport_dimensions(bidi_session, new_tab) != start_viewport
+
+    # Load a page so that reflow is triggered when changing the viewport
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
+    await bidi_session.browsing_context.set_viewport(
+        context=new_tab["context"],
+        viewport=start_viewport)
+
+    assert await get_viewport_dimensions(bidi_session, new_tab) == start_viewport
+
+    modified_viewport = {"width": width, "height": height}
+    await bidi_session.browsing_context.set_viewport(
+        context=new_tab["context"],
+        viewport=modified_viewport)
+
+    assert await get_viewport_dimensions(bidi_session, new_tab) == modified_viewport
+
+
+@pytest.mark.asyncio
+async def test_reset_to_default(bidi_session, inline, new_tab):
     original_viewport = await get_viewport_dimensions(bidi_session, new_tab)
 
     test_viewport = {"width": 666, "height": 333}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
 
+    # Load a page so that reflow is triggered when changing the viewport
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         viewport=test_viewport
@@ -58,13 +103,19 @@
 
 
 @pytest.mark.asyncio
-async def test_set_viewport_affects_specific_context(bidi_session, top_context, new_tab):
+async def test_specific_context(bidi_session, inline, new_tab, top_context):
     original_viewport = await get_viewport_dimensions(bidi_session, top_context)
 
     test_viewport = {"width": 333, "height": 666}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
 
+    # Load a page so that reflow is triggered when changing the viewport
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         viewport=test_viewport
@@ -84,7 +135,7 @@
     "https coop"
 ])
 @pytest.mark.asyncio
-async def test_set_viewport_persists_on_navigation(bidi_session, new_tab, inline, protocol, parameters):
+async def test_persists_on_navigation(bidi_session, new_tab, inline, protocol, parameters):
     test_viewport = {"width": 499, "height": 599}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
@@ -111,11 +162,17 @@
 
 
 @pytest.mark.asyncio
-async def test_set_viewport_persists_on_reload(bidi_session, new_tab):
+async def test_persists_on_reload(bidi_session, inline, new_tab):
     test_viewport = {"width": 499, "height": 599}
 
     assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
 
+    # Load a page so that reflow is triggered when changing the viewport
+    url = inline("<div>foo</div>")
+    await bidi_session.browsing_context.navigate(
+        context=new_tab["context"], url=url, wait="complete"
+    )
+
     await bidi_session.browsing_context.set_viewport(
         context=new_tab["context"],
         viewport=test_viewport)
@@ -127,22 +184,3 @@
     )
 
     assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
-
-
-@pytest.mark.asyncio
-async def test_set_viewport_undefined(bidi_session, new_tab):
-    test_viewport = {"width": 499, "height": 599}
-
-    assert await get_viewport_dimensions(bidi_session, new_tab) != test_viewport
-
-    await bidi_session.browsing_context.set_viewport(
-        context=new_tab["context"],
-        viewport=test_viewport)
-
-    assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
-
-    await bidi_session.browsing_context.set_viewport(
-        context=new_tab["context"],
-        viewport=UNDEFINED)
-
-    assert await get_viewport_dimensions(bidi_session, new_tab) == test_viewport
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js
index f82d7ec..75e9f2c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js
@@ -40,11 +40,12 @@
       TestRunner.addSniffer(
           Sources.WatchExpressionsSidebarPane.WatchExpression.prototype, 'createWatchExpression',
           watchExpressionsUpdated);
-      let updateCount = 2;
-      function watchExpressionsUpdated(result, wasThrown) {
-        if (result !== undefined || wasThrown !== undefined) {
-          TestRunner.addResult(this.element.deepTextContent());
-          if (--updateCount === 0) {
+      const watches = [];
+      function watchExpressionsUpdated(result, exceptionDetails) {
+        if (result !== undefined || exceptionDetails !== undefined) {
+          watches.push(this.element.deepTextContent());
+          if (watches.length === 2) {
+            watches.sort().forEach(TestRunner.addResult);
             resolve();
             return;
           }
diff --git a/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
new file mode 100644
index 0000000..d2490db
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/deprecate-unload/external/wpt/html/browsers/browsing-the-web/back-forward-cache/events-expected.txt
@@ -0,0 +1,3 @@
+This is a testharness.js-based test.
+Harness: the test ran to completion.
+
diff --git a/third_party/cros-components/src b/third_party/cros-components/src
index a16ac80..5a66329 160000
--- a/third_party/cros-components/src
+++ b/third_party/cros-components/src
@@ -1 +1 @@
-Subproject commit a16ac80e606d001002ec77dfe847528a1cc5947b
+Subproject commit 5a6632957c5dc1b7b34d3099c33eafa1c356e40b
diff --git a/third_party/dawn b/third_party/dawn
index b268f52..9ffc1d9 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit b268f525fc231d4f545ae9a40f002b46276bdd17
+Subproject commit 9ffc1d92cb4b6a599dc8803a9d84f28821c5b27d
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal
index 831ddb2..beef3c6 160000
--- a/third_party/devtools-frontend-internal
+++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@
-Subproject commit 831ddb26c27ea70c10a67d34ddf4bd41276e667f
+Subproject commit beef3c68361522775e89249acd82afb5e576b8c4
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 189c44f..d52a379 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 189c44f9a96357461a594e16e6bf1d187174a3c4
+Subproject commit d52a3791eb93361fa24825670284e7bcfb520403
diff --git a/third_party/skia b/third_party/skia
index 7c6b949..5c037ee 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 7c6b9495b415e59d866df8d10f930b1d34654887
+Subproject commit 5c037eed36a24d282a03bd1f03d2dff74ff69410
diff --git a/tools/apply_cpplint_header_guard.py b/tools/apply_cpplint_header_guard.py
index bd3630ab..bef74b3 100755
--- a/tools/apply_cpplint_header_guard.py
+++ b/tools/apply_cpplint_header_guard.py
@@ -28,6 +28,10 @@
   root = "_".join(root.upper().strip(r'[/]+').split('/'))+"_"
   for entry in cpplint_data:
     entry = entry.split(':')
+    # The length of the entry may be less than 3,
+    # e.g the last line of text 'Total errors found: xx'.
+    if len(entry) < 3:
+      continue
     header = entry[0]
     line = entry[1]
     index = int(line) - 1
diff --git a/tools/clang/plugins/RawPtrHelpers.h b/tools/clang/plugins/RawPtrHelpers.h
index 42a380f..aa8e6ced 100644
--- a/tools/clang/plugins/RawPtrHelpers.h
+++ b/tools/clang/plugins/RawPtrHelpers.h
@@ -105,6 +105,10 @@
   if (filename.find("/third_party/blink/") != std::string::npos) {
     return false;
   }
+  // Dawn repo has started using raw_ptr.
+  if (filename.find("/third_party/dawn/") != std::string::npos) {
+    return false;
+  }
   // Otherwise, just check if the paths contains the "third_party" substring.
   // We don't want to rewrite content of such paths even if they are in the main
   // Chromium git repository.
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 0184b92..acec4e23 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -138,6 +138,10 @@
     "META": {"sizes": {"includes": [10],}},
     "includes": [2440],
   },
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/app_install/resources.grd": {
+    "META": {"sizes": {"includes": [5]}},
+    "includes": [2450],
+  },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/arc_account_picker/resources.grd": {
     "META": {"sizes": {"includes": [10],}},
     "includes": [2460],
@@ -241,10 +245,6 @@
     "META": {"sizes": {"includes": [5]}},
     "includes": [2980],
   },
-  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/web_app_install/resources.grd": {
-    "META": {"sizes": {"includes": [5]}},
-    "includes": [3000],
-  },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/commander/resources.grd": {
     "META": {"sizes": {"includes": [15]}},
     "includes": [3020],
diff --git a/tools/licenses/licenses.py b/tools/licenses/licenses.py
index 71dbd96..03015b8 100755
--- a/tools/licenses/licenses.py
+++ b/tools/licenses/licenses.py
@@ -56,6 +56,10 @@
     # Only binaries, used during development.
     os.path.join('third_party', 'valgrind'),
 
+    # Not actually a third party dependency. Supplies configuration for
+    # enabling or disabling field trials and features in Chromium projects.
+    os.path.join('third_party', 'chromium-variations'),
+
     # Used for development and test, not in the shipping product.
     os.path.join('build', 'secondary'),
     os.path.join('third_party', 'bison'),
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 9a5dadc..dbe1575 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -15526,12 +15526,12 @@
 
 <enum name="DownloadBubbleSubpageAction">
   <int value="0" label="Subpage shown"/>
-  <int value="1" label="Checkbox shown"/>
+  <int value="1" label="(Obsolete) Checkbox shown"/>
   <int value="2" label="Secondary Button shown"/>
   <int value="3" label="Primary Button shown"/>
   <int value="4" label="Back button pressed"/>
   <int value="5" label="Subpage closed"/>
-  <int value="6" label="Checkbox clicked"/>
+  <int value="6" label="(Obsolete) Checkbox clicked"/>
   <int value="7" label="Secondary button pressed"/>
   <int value="8" label="Primary button pressed"/>
 </enum>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 72b1e86..90d741e 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -719,17 +719,6 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.BrowserContext.UnexpectedGetUserByProfile" enum="Boolean"
-    expires_after="M122">
-  <owner>hidehiko@chromium.org</owner>
-  <owner>oshima@chromium.org</owner>
-  <summary>
-    Making sure nobody in the production calls ProfileHelper::GetUserByProfile()
-    for the Profile instance, which does not have corresponding User. This entry
-    will not have &quot;false&quot; status.
-  </summary>
-</histogram>
-
 <histogram name="Ash.BrowserDataBackMigrator.ElapsedTimeBetweenDataMigrations"
     units="ms" expires_after="2024-10-01">
   <owner>janagrill@google.com</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 48226e23..671457e 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -3648,6 +3648,11 @@
       queries.
     </summary>
   </metric>
+  <metric name="FieldLogEventCount">
+    <summary>
+      The total number of all the field log events created for this field.
+    </summary>
+  </metric>
   <metric name="FieldSessionIdentifier">
     <summary>
       A random variable assigned to a specific instance of a form control (e.g.
diff --git a/tools/pgo/OWNERS b/tools/pgo/OWNERS
new file mode 100644
index 0000000..d709125
--- /dev/null
+++ b/tools/pgo/OWNERS
@@ -0,0 +1,2 @@
+thakis@chromium.org
+wnwen@chromium.org
diff --git a/tools/traffic_annotation/OWNERS b/tools/traffic_annotation/OWNERS
index 3453802c..6f7434c 100644
--- a/tools/traffic_annotation/OWNERS
+++ b/tools/traffic_annotation/OWNERS
@@ -2,7 +2,5 @@
 rhalavati@chromium.org  # emeritus
 
 per-file safe_list.txt=crmullins@chromium.org
-# TODO(b/304802311): Remove jorgelo@ once other folks become committers.
-per-file safe_list.txt=jorgelo@chromium.org
 per-file safe_list.txt=nicolaso@chromium.org
 per-file safe_list.txt=ramyagopalan@google.com
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index 75d1812..b99bce0 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -126,6 +126,8 @@
   sources = [
     "test/animation_throughput_reporter_test_base.cc",
     "test/animation_throughput_reporter_test_base.h",
+    "test/begin_main_frame_waiter.cc",
+    "test/begin_main_frame_waiter.h",
     "test/direct_layer_tree_frame_sink.cc",
     "test/direct_layer_tree_frame_sink.h",
     "test/draw_waiter_for_test.cc",
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index b8098b7..638bff9 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -508,6 +508,8 @@
     return host_->saved_events_metrics_count_for_testing();
   }
 
+  const cc::LayerTreeHost* host_for_testing() const { return host_.get(); }
+
  private:
   friend class base::RefCounted<Compositor>;
   friend class TotalAnimationThroughputReporter;
diff --git a/ui/compositor/test/begin_main_frame_waiter.cc b/ui/compositor/test/begin_main_frame_waiter.cc
new file mode 100644
index 0000000..e84f526
--- /dev/null
+++ b/ui/compositor/test/begin_main_frame_waiter.cc
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/compositor/test/begin_main_frame_waiter.h"
+
+#include "ui/compositor/compositor.h"
+
+namespace ui {
+
+BeginMainFrameWaiter::BeginMainFrameWaiter(ui::Compositor* compositor)
+    : compositor_(compositor),
+      run_loop_(base::RunLoop::Type::kNestableTasksAllowed) {
+  compositor_->AddObserver(this);
+}
+
+BeginMainFrameWaiter::~BeginMainFrameWaiter() {
+  compositor_->RemoveObserver(this);
+}
+
+void BeginMainFrameWaiter::OnDidBeginMainFrame(ui::Compositor* compositor) {
+  DCHECK_EQ(compositor_, compositor);
+  begin_main_frame_received_ = true;
+  if (run_loop_.running()) {
+    run_loop_.Quit();
+  }
+}
+
+void BeginMainFrameWaiter::Wait() {
+  if (begin_main_frame_received_) {
+    return;
+  }
+  if (!run_loop_.running()) {
+    run_loop_.Run();
+  }
+}
+
+}  // namespace ui
diff --git a/ui/compositor/test/begin_main_frame_waiter.h b/ui/compositor/test/begin_main_frame_waiter.h
new file mode 100644
index 0000000..ede8f1c
--- /dev/null
+++ b/ui/compositor/test/begin_main_frame_waiter.h
@@ -0,0 +1,41 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_COMPOSITOR_TEST_BEGIN_MAIN_FRAME_WAITER_H_
+#define UI_COMPOSITOR_TEST_BEGIN_MAIN_FRAME_WAITER_H_
+
+#include "base/memory/raw_ptr.h"
+#include "base/run_loop.h"
+#include "ui/compositor/compositor_observer.h"
+
+namespace ui {
+
+class Compositor;
+
+class BeginMainFrameWaiter : public CompositorObserver {
+ public:
+  explicit BeginMainFrameWaiter(Compositor* compositor);
+
+  BeginMainFrameWaiter(const BeginMainFrameWaiter&) = delete;
+  BeginMainFrameWaiter& operator=(const BeginMainFrameWaiter&) = delete;
+
+  ~BeginMainFrameWaiter() override;
+
+  // ui::CompositorObserver
+  void OnDidBeginMainFrame(Compositor* compositor) override;
+
+  // True if BeginMainFrame has been received.
+  bool begin_main_frame_received() const { return begin_main_frame_received_; }
+
+  void Wait();
+
+ private:
+  raw_ptr<Compositor, ExperimentalAsh> compositor_;
+  bool begin_main_frame_received_ = false;
+  base::RunLoop run_loop_;
+};
+
+}  // namespace ui
+
+#endif  // UI_COMPOSITOR_TEST_BEGIN_MAIN_FRAME_WAITER_H_
diff --git a/ui/file_manager/file_manager/containers/directory_tree_container.ts b/ui/file_manager/file_manager/containers/directory_tree_container.ts
index a069061..6a95d0d 100644
--- a/ui/file_manager/file_manager/containers/directory_tree_container.ts
+++ b/ui/file_manager/file_manager/containers/directory_tree_container.ts
@@ -12,7 +12,7 @@
 import {recordEnum, recordUserAction} from '../common/js/metrics.js';
 import {str, strf} from '../common/js/translations.js';
 import {VolumeManagerCommon} from '../common/js/volume_manager_types.js';
-import {AndroidApp, CurrentDirectory, FileData, FileKey, NavigationKey, NavigationRoot, NavigationType, PropStatus, State} from '../externs/ts/state.js';
+import {AndroidApp, CurrentDirectory, FileData, FileKey, NavigationKey, NavigationRoot, NavigationType, PropStatus, SearchLocation, State} from '../externs/ts/state.js';
 import type {VolumeManager} from '../externs/volume_manager.js';
 import {constants} from '../foreground/js/constants.js';
 import {DirectoryModel} from '../foreground/js/directory_model.js';
@@ -22,6 +22,7 @@
 import {convertEntryToFileData, readSubDirectories, traverseAndExpandPathEntries} from '../state/ducks/all_entries.js';
 import {changeDirectory} from '../state/ducks/current_directory.js';
 import {refreshNavigationRoots, updateNavigationEntry} from '../state/ducks/navigation.js';
+import {clearSearch} from '../state/ducks/search.js';
 import {driveRootEntryListKey} from '../state/ducks/volumes.js';
 import {getEntry, getFileData, getStore, getVolume, getVolumeType, type Store} from '../state/store.js';
 import {type TreeSelectedChangedEvent, XfTree} from '../widgets/xf_tree.js';
@@ -178,13 +179,18 @@
 
     const {navigation: {roots}, androidApps, currentDirectory} = state;
 
-    // When current directory changes in the store, and the selected item in the
-    // tree is different from that, select the corresponding navigation item.
-    const selectedItemKey = this.tree.selectedItem?.dataset['navigationKey'];
-    if (currentDirectory?.key &&
-        currentDirectory.status === PropStatus.SUCCESS &&
-        currentDirectory.key !== selectedItemKey) {
-      await this.selectCurrentDirectoryItem_(currentDirectory);
+    if (this.shouldUnselectCurrentDirectoryItem_()) {
+      this.tree.selectedItem = null;
+    } else {
+      // When current directory changes in the store, and the selected item in
+      // the tree is different from that, select the corresponding navigation
+      // item.
+      const selectedItemKey = this.tree.selectedItem?.dataset['navigationKey'];
+      if (currentDirectory?.key &&
+          currentDirectory.status === PropStatus.SUCCESS &&
+          currentDirectory.key !== selectedItemKey) {
+        await this.selectCurrentDirectoryItem_(currentDirectory);
+      }
     }
 
     // When navigation roots data changes in the store, re-render all navigation
@@ -801,6 +807,15 @@
     // by other parts of the UI), we don't want to activate the directory again
     // because it's already activated.
     if (this.isCurrentDirectoryActive_(navigationKey)) {
+      // An unselected current directory item can be selected by:
+      //  1. either change search location back from others to THIS_FOLDER.
+      //  2. or users manually click the unselected current directory item to
+      //  select it.
+      // For 1, we don't need to clear the search, but for 2, we need to clear
+      // the search, hence the check here.
+      if (this.shouldUnselectCurrentDirectoryItem_()) {
+        this.store_.dispatch(clearSearch());
+      }
       return;
     }
     const navigationData = this.getNavigationDataFromKey_(navigationKey);
@@ -1203,4 +1218,27 @@
         currentDirectory.pathComponents.map(pathComponent => pathComponent.key);
     this.store_.dispatch(traverseAndExpandPathEntries(pathEntryKeys));
   }
+
+  /**
+   * Check if we need to unselect the current directory item in the tree.
+   * When searching is active and we are not searching current folder, we
+   * shouldn't have any tree item selected.
+   */
+  private shouldUnselectCurrentDirectoryItem_(): boolean {
+    const state = this.store_.getState();
+    const {search, currentDirectory} = state;
+    const isSearchActive = search?.status !== undefined && !!(search?.query);
+    let isCurrentDIrectoryInsideDrive = false;
+    if (currentDirectory?.key) {
+      const currentDirectoryEntry = getFileData(state, currentDirectory.key)!;
+      isCurrentDIrectoryInsideDrive = isEntryInsideDrive(currentDirectoryEntry);
+    }
+    const isSearchInCurrentFolder =
+        // When searching in Drive, the search location option will only include
+        // ROOT_FOLDER ("Google Drive"), not include THIS_FOLDER.
+        (isCurrentDIrectoryInsideDrive &&
+         search?.options?.location === SearchLocation.ROOT_FOLDER) ||
+        search?.options?.location === SearchLocation.THIS_FOLDER;
+    return isSearchActive && !isSearchInCurrentFolder;
+  }
 }
diff --git a/ui/file_manager/file_manager/foreground/js/actions_controller.js b/ui/file_manager/file_manager/foreground/js/actions_controller.js
deleted file mode 100644
index 5b4f540..0000000
--- a/ui/file_manager/file_manager/foreground/js/actions_controller.js
+++ /dev/null
@@ -1,357 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {getFocusedTreeItem} from '../../common/js/dom_utils.js';
-import {isNewDirectoryTreeEnabled} from '../../common/js/flags.js';
-import {XfTree} from '../../widgets/xf_tree.js';
-
-import {Action, ActionsModel} from './actions_model.js';
-import {DirectoryModel} from './directory_model.js';
-import {FileSelectionHandler} from './file_selection.js';
-import {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
-import {MetadataModel} from './metadata/metadata_model.js';
-import {contextMenuHandler} from './ui/context_menu_handler.js';
-import {FileManagerUI} from './ui/file_manager_ui.js';
-
-/**
- * Manages actions for the current selection.
- */
-export class ActionsController {
-  /**
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @param {!MetadataModel} metadataModel
-   * @param {!DirectoryModel} directoryModel
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {!FileSelectionHandler} selectionHandler
-   * @param {!FileManagerUI} ui
-   */
-  constructor(
-      volumeManager, metadataModel, directoryModel, shortcutsModel,
-      selectionHandler, ui) {
-    /**
-     * @private @const @type {!import('../../externs/volume_manager.js').VolumeManager}
-     */
-    this.volumeManager_ = volumeManager;
-
-    /** @private @const @type {!MetadataModel} */
-    this.metadataModel_ = metadataModel;
-
-    /** @private @const @type {!DirectoryModel} */
-    this.directoryModel_ = directoryModel;
-
-    /** @private @const @type {!FolderShortcutsDataModel} */
-    this.shortcutsModel_ = shortcutsModel;
-
-    /** @private @const @type {!FileSelectionHandler} */
-    this.selectionHandler_ = selectionHandler;
-
-    /** @private @const @type {!FileManagerUI} */
-    this.ui_ = ui;
-
-    /** @private @const @type {Map<string, ActionsModel>} */
-    this.readyModels_ = new Map();
-
-    /** @private @const @type {Map<string, Promise<ActionsModel>>} */
-    this.initializingdModels_ = new Map();
-
-    /**
-     * Key for in-memory state for current directory.
-     * @private @type {?string}
-     */
-    this.currentDirKey_ = null;
-
-    /**
-     * Key for in-memory state for current selection in the file list.
-     * @private @type {?string}
-     */
-    this.currentSelectionKey_ = null;
-
-    /**
-     * Id for an UI update, when an async update happens we only send the state
-     * to the DOM if the sequence hasn't changed since its start.
-     *
-     * @private @type {number}
-     */
-    this.updateUiSequence_ = 0;
-
-    // Attach listeners to non-user events which will only update the in-memory
-    // ActionsModel.
-    if (isNewDirectoryTreeEnabled()) {
-      // @ts-ignore: error TS2531: Object is possibly 'null'.
-      this.ui_.directoryTree.addEventListener(
-          XfTree.events.TREE_SELECTION_CHANGED,
-          this.onNavigationListSelectionChanged_.bind(this), true);
-    } else {
-      // @ts-ignore: error TS2531: Object is possibly 'null'.
-      this.ui_.directoryTree.addEventListener(
-          'change', this.onNavigationListSelectionChanged_.bind(this), true);
-    }
-    this.selectionHandler_.addEventListener(
-        FileSelectionHandler.EventType.CHANGE_THROTTLED,
-        this.onSelectionChanged_.bind(this));
-
-    // Attach listeners to events based on user action to show the menu, which
-    // updates the DOM.
-    contextMenuHandler.addEventListener(
-        'show', this.onContextMenuShow_.bind(this));
-    this.ui_.selectionMenuButton.addEventListener(
-        'menushow', this.onMenuShow_.bind(this));
-    this.ui_.gearButton.addEventListener(
-        'menushow', this.onMenuShow_.bind(this));
-
-    this.metadataModel_.addEventListener(
-        'update', this.onMetadataUpdated_.bind(this));
-  }
-
-  /**
-   * @param {Element} element
-   * @return {!Array<Entry|FileEntry>}
-   * @private
-   */
-  getEntriesFor_(element) {
-    // Element can be null, eg. when invoking a command via a keyboard shortcut.
-    if (!element) {
-      return [];
-    }
-
-    if (this.ui_.listContainer.element.contains(element) ||
-        this.ui_.toolbar.contains(element) ||
-        this.ui_.fileContextMenu.contains(element) ||
-        document.body === element) {
-      return this.selectionHandler_.selection.entries;
-    }
-    // @ts-ignore: error TS2531: Object is possibly 'null'.
-    if (this.ui_.directoryTree.contains(element) ||
-        // @ts-ignore: error TS2339: Property 'contextMenuForRootItems' does not
-        // exist on type 'XfTree | DirectoryTree'.
-        this.ui_.directoryTree.contextMenuForRootItems.contains(element) ||
-        // @ts-ignore: error TS2339: Property 'contextMenuForSubitems' does not
-        // exist on type 'XfTree | DirectoryTree'.
-        this.ui_.directoryTree.contextMenuForSubitems.contains(element)) {
-      // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-      // 'Element'.
-      if (element.entry) {
-        // DirectoryItem has "entry" attribute.
-        // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-        // 'Element'.
-        return [element.entry];
-      }
-      // DirectoryTree has the focused item.
-      const focusedItem = getFocusedTreeItem(element);
-      // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-      // 'XfTreeItem | DirectoryItem'.
-      if (focusedItem?.entry) {
-        // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-        // 'XfTreeItem | DirectoryItem'.
-        return [focusedItem.entry];
-      }
-    }
-
-    return [];
-  }
-
-  /**
-   * @param {!Array<Entry|FileEntry>} entries
-   * @return {string}
-   * @private
-   * */
-  getEntriesKey_(entries) {
-    return entries.map(entry => entry.toURL()).join(';');
-  }
-
-  /**
-   * @param {!string} key Key to be cleared.
-   * @private
-   */
-  clearLocalCache_(key) {
-    this.readyModels_.delete(key);
-    this.initializingdModels_.delete(key);
-  }
-
-  /**
-   * @param {Element} element
-   * @private
-   */
-  updateUI_(element) {
-    const entries = this.getEntriesFor_(/** @type {Element} */ (element));
-
-    // Try to update synchronously.
-    const actionsModel = this.getInitializedActionsForEntries(entries);
-    if (actionsModel) {
-      this.ui_.actionsSubmenu.setActionsModel(actionsModel, element);
-      return;
-    }
-
-    // Asynchronously update the UI, after fetching actions from the backend.
-    const sequence = ++this.updateUiSequence_;
-    this.getActionsForEntries(entries).then((actionsModel) => {
-      // Only update if there wasn't another UI update started while the promise
-      // was resolving, which could be for different entries and avoids multiple
-      // updates for the same entries.
-      if (sequence === this.updateUiSequence_) {
-        this.ui_.actionsSubmenu.setActionsModel(actionsModel, element);
-      }
-    });
-  }
-
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onContextMenuShow_(event) {
-    // @ts-ignore: error TS2339: Property 'element' does not exist on type
-    // 'Event'.
-    this.updateUI_(event.element);
-  }
-
-  /**
-   * @param {!Event} event
-   * @private
-   */
-  onMenuShow_(event) {
-    this.updateUI_(/** @type {Element} */ (event.target));
-  }
-
-  /**
-   * @private
-   */
-  onSelectionChanged_() {
-    const entries = this.selectionHandler_.selection.entries;
-
-    if (!entries.length) {
-      this.currentSelectionKey_ = null;
-      return;
-    }
-
-    const currentKey = this.getEntriesKey_(entries);
-    this.currentSelectionKey_ = currentKey;
-
-    this.getActionsForEntries(entries);
-  }
-
-  /**
-   * @private
-   */
-  onNavigationListSelectionChanged_() {
-    const focusedItem = getFocusedTreeItem(this.ui_.directoryTree);
-    // @ts-ignore: error TS2339: Property 'entry' does not exist on type
-    // 'XfTreeItem | DirectoryItem'.
-    const entry = focusedItem?.entry;
-
-    if (!entry) {
-      this.currentDirKey_ = null;
-      return;
-    }
-
-    // Force to recalculate for the new current directory.
-    const key = this.getEntriesKey_([entry]);
-    this.clearLocalCache_(key);
-    this.currentDirKey_ = key;
-
-    this.getActionsForEntries([entry]);
-  }
-
-  /**
-   * @param {?Event} event
-   * @private
-   */
-  onMetadataUpdated_(event) {
-    // @ts-ignore: error TS2339: Property 'names' does not exist on type
-    // 'Event'.
-    if (!event || !event.names.has('pinned')) {
-      return;
-    }
-
-    for (const key of this.readyModels_.keys()) {
-      // @ts-ignore: error TS2339: Property 'entriesMap' does not exist on type
-      // 'Event'.
-      if (key.split(';').some(url => event.entriesMap.has(url))) {
-        this.readyModels_.delete(key);
-      }
-    }
-    for (const key of this.initializingdModels_.keys()) {
-      // @ts-ignore: error TS2339: Property 'entriesMap' does not exist on type
-      // 'Event'.
-      if (key.split(';').some(url => event.entriesMap.has(url))) {
-        this.initializingdModels_.delete(key);
-      }
-    }
-  }
-
-  /**
-   * @param {!Array<Entry|FileEntry>} entries
-   * @return {?ActionsModel}
-   */
-  getInitializedActionsForEntries(entries) {
-    const key = this.getEntriesKey_(entries);
-    // @ts-ignore: error TS2322: Type 'ActionsModel | undefined' is not
-    // assignable to type 'ActionsModel | null'.
-    return this.readyModels_.get(key);
-  }
-
-  /**
-   * @param {!Array<Entry|FileEntry>} entries
-   * @return {Promise<ActionsModel>}
-   */
-  getActionsForEntries(entries) {
-    const key = this.getEntriesKey_(entries);
-    if (!key) {
-      // @ts-ignore: error TS2322: Type 'Promise<void>' is not assignable to
-      // type 'Promise<ActionsModel>'.
-      return Promise.resolve();
-    }
-
-    // If it's still initializing, return the cached promise.
-    const promise = this.initializingdModels_.get(key);
-    if (promise) {
-      return promise;
-    }
-
-    // If it's already initialized, resolve with the model.
-    let actionsModel = this.readyModels_.get(key);
-    if (actionsModel) {
-      return Promise.resolve(actionsModel);
-    }
-
-    actionsModel = new ActionsModel(
-        this.volumeManager_, this.metadataModel_, this.shortcutsModel_,
-        this.ui_, entries);
-
-    actionsModel.addEventListener('invalidated', () => {
-      this.clearLocalCache_(key);
-      this.selectionHandler_.onFileSelectionChanged();
-    }, {once: true});
-
-    // Once it's initialized, move to readyModels_ so we don't have to construct
-    // and initialized again.
-    const init = actionsModel.initialize().then(() => {
-      this.initializingdModels_.delete(key);
-      // @ts-ignore: error TS2345: Argument of type 'ActionsModel | undefined'
-      // is not assignable to parameter of type 'ActionsModel'.
-      this.readyModels_.set(key, actionsModel);
-      return actionsModel;
-    });
-
-    // Cache in the waiting initialization map.
-    // @ts-ignore: error TS2345: Argument of type 'Promise<ActionsModel |
-    // undefined>' is not assignable to parameter of type
-    // 'Promise<ActionsModel>'.
-    this.initializingdModels_.set(key, init);
-    // @ts-ignore: error TS2322: Type 'Promise<ActionsModel | undefined>' is not
-    // assignable to type 'Promise<ActionsModel>'.
-    return init;
-  }
-
-  /**
-   * @param {Action} action
-   */
-  executeAction(action) {
-    const entries = action.getEntries();
-    const key = this.getEntriesKey_(entries);
-    // Invalidate the model early so new UI has to refresh it.
-    this.readyModels_.delete(key);
-    action.execute();
-  }
-}
diff --git a/ui/file_manager/file_manager/foreground/js/actions_controller.ts b/ui/file_manager/file_manager/foreground/js/actions_controller.ts
new file mode 100644
index 0000000..0a0bfb0
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/actions_controller.ts
@@ -0,0 +1,252 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {getFocusedTreeItem} from '../../common/js/dom_utils.js';
+import {isNewDirectoryTreeEnabled} from '../../common/js/flags.js';
+import type {VolumeManager} from '../../externs/volume_manager.js';
+import {XfTree} from '../../widgets/xf_tree.js';
+
+import {Action, ActionsModel} from './actions_model.js';
+import {DirectoryModel} from './directory_model.js';
+import {FileSelectionHandler} from './file_selection.js';
+import {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
+import {MetadataSetEvent} from './metadata/metadata_cache_set.js';
+import {MetadataModel} from './metadata/metadata_model.js';
+import {contextMenuHandler} from './ui/context_menu_handler.js';
+import {DirectoryTree} from './ui/directory_tree.js';
+import {FileManagerUI} from './ui/file_manager_ui.js';
+
+/**
+ * Manages actions for the current selection.
+ */
+export class ActionsController {
+  private readyModels_ = new Map<string, ActionsModel>();
+  private initializingModels_ = new Map<string, Promise<ActionsModel>>();
+  /**
+   * Id for an UI update, when an async update happens we only send the state
+   * to the DOM if the sequence hasn't changed since its start.
+   */
+  private updateUiSequence_: number = 0;
+
+  constructor(
+      private readonly volumeManager_: VolumeManager,
+      private readonly metadataModel_: MetadataModel,
+      _directoryModel: DirectoryModel,
+      private readonly shortcutsModel_: FolderShortcutsDataModel,
+      private readonly selectionHandler_: FileSelectionHandler,
+      private readonly ui_: FileManagerUI) {
+    // Attach listeners to non-user events which will only update the in-memory
+    // ActionsModel.
+    if (isNewDirectoryTreeEnabled()) {
+      this.ui_.directoryTree!.addEventListener(
+          XfTree.events.TREE_SELECTION_CHANGED,
+          this.onNavigationListSelectionChanged_.bind(this), true);
+    } else {
+      this.ui_.directoryTree!.addEventListener(
+          'change', this.onNavigationListSelectionChanged_.bind(this), true);
+    }
+    this.selectionHandler_.addEventListener(
+        FileSelectionHandler.EventType.CHANGE_THROTTLED,
+        this.onSelectionChanged_.bind(this));
+
+    // Attach listeners to events based on user action to show the menu, which
+    // updates the DOM.
+    contextMenuHandler.addEventListener(
+        'show', this.onContextMenuShow_.bind(this));
+    this.ui_.selectionMenuButton.addEventListener(
+        'menushow', this.onMenuShow_.bind(this));
+    this.ui_.gearButton.addEventListener(
+        'menushow', this.onMenuShow_.bind(this));
+
+    this.metadataModel_.addEventListener(
+        'update', this.onMetadataUpdated_.bind(this));
+  }
+
+  private getEntriesFor_(element: Element): Array<Entry|FileEntry> {
+    // Element can be null, eg. when invoking a command via a keyboard shortcut.
+    if (!element) {
+      return [];
+    }
+
+    if (this.ui_.listContainer.element.contains(element) ||
+        this.ui_.toolbar.contains(element) ||
+        this.ui_.fileContextMenu.contains(element) ||
+        document.body === element) {
+      return this.selectionHandler_.selection.entries;
+    }
+
+    const contextMenuForRootItems = isNewDirectoryTreeEnabled() ?
+        this.ui_.directoryTreeContainer!.contextMenuForRootItems :
+        (this.ui_.directoryTree as DirectoryTree).contextMenuForRootItems;
+    const contextMenuForSubitems = isNewDirectoryTreeEnabled() ?
+        this.ui_.directoryTreeContainer!.contextMenuForSubitems :
+        (this.ui_.directoryTree as DirectoryTree).contextMenuForSubitems;
+    if (this.ui_.directoryTree!.contains(element) ||
+        contextMenuForRootItems!.contains(element) ||
+        contextMenuForSubitems!.contains(element)) {
+      const entry: FileEntry|null =
+          'entry' in element ? element.entry as FileEntry : null;
+      if (entry) {
+        return [entry];
+      }
+      // DirectoryTree has the focused item.
+      const focusedItem = getFocusedTreeItem(element);
+      if (focusedItem && 'entry' in focusedItem) {
+        const focusedEntry = focusedItem.entry as unknown as FileEntry;
+        return [focusedEntry];
+      }
+    }
+
+    return [];
+  }
+
+  private getEntriesKey_(entries: Array<Entry|FileEntry>): string {
+    return entries.map(entry => entry.toURL()).join(';');
+  }
+
+  /**
+   * Clears data associated with the given `key`.
+   */
+  private clearLocalCache_(key: string) {
+    this.readyModels_.delete(key);
+    this.initializingModels_.delete(key);
+  }
+
+  private updateView_(element: Element) {
+    const entries = this.getEntriesFor_(element);
+
+    // Try to update synchronously.
+    const actionsModel = this.getInitializedActionsForEntries(entries);
+    if (actionsModel) {
+      this.ui_.actionsSubmenu.setActionsModel(actionsModel, element);
+      return;
+    }
+
+    // Asynchronously update the UI, after fetching actions from the backend.
+    const sequence = ++this.updateUiSequence_;
+    this.getActionsForEntries(entries).then((actionsModel) => {
+      // Only update if there wasn't another UI update started while the promise
+      // was resolving, which could be for different entries and avoids multiple
+      // updates for the same entries.
+      if (sequence === this.updateUiSequence_) {
+        this.ui_.actionsSubmenu.setActionsModel(actionsModel!, element);
+      }
+    });
+  }
+
+  private onContextMenuShow_(event: Event) {
+    this.updateView_((event as any).element);
+  }
+
+  private onMenuShow_(event: Event) {
+    this.updateView_(event.target as Element);
+  }
+
+  private onSelectionChanged_() {
+    const entries = this.selectionHandler_.selection.entries;
+
+    if (!entries.length) {
+      return;
+    }
+
+    // To avoid the menu flickering, make this call to start the caching
+    // process. We do not return the result on purpose.
+    this.getActionsForEntries(entries);
+  }
+
+  private onNavigationListSelectionChanged_() {
+    const focusedItem = getFocusedTreeItem(this.ui_.directoryTree);
+    const entry =
+        focusedItem && 'entry' in focusedItem ? focusedItem.entry : null;
+
+    if (!entry) {
+      return;
+    }
+
+    // Force to recalculate for the new current directory.
+    const fileEntry = entry as unknown as FileEntry;
+    const key = this.getEntriesKey_([fileEntry]);
+    this.clearLocalCache_(key);
+
+    // To avoid the menu flickering, make this call to start the caching
+    // process. We do not return the result on purpose.
+    this.getActionsForEntries([fileEntry]);
+  }
+
+  private onMetadataUpdated_(event: null|Event) {
+    if (!event) {
+      return;
+    }
+    const evt = (event as unknown) as MetadataSetEvent;
+    if (!evt.names.has('pinned')) {
+      return;
+    }
+
+    const entriesMap = evt.entriesMap;
+    for (const key of this.readyModels_.keys()) {
+      if (key.split(';').some(url => entriesMap.has(url))) {
+        this.readyModels_.delete(key);
+      }
+    }
+    for (const key of this.initializingModels_.keys()) {
+      if (key.split(';').some(url => entriesMap.has(url))) {
+        this.initializingModels_.delete(key);
+      }
+    }
+  }
+
+  getInitializedActionsForEntries(entries: Array<Entry|FileEntry>): null
+      |ActionsModel {
+    const key = this.getEntriesKey_(entries);
+    return this.readyModels_.get(key) || null;
+  }
+
+  getActionsForEntries(entries: Array<Entry|FileEntry>):
+      Promise<ActionsModel|void> {
+    const key = this.getEntriesKey_(entries);
+    if (!key) {
+      return Promise.resolve();
+    }
+
+    // If it's still initializing, return the cached promise.
+    const promise = this.initializingModels_.get(key);
+    if (promise) {
+      return promise;
+    }
+
+    // If it's already initialized, resolve with the model.
+    const readyModel = this.readyModels_.get(key);
+    if (readyModel) {
+      return Promise.resolve(readyModel);
+    }
+
+    const freshModel = new ActionsModel(
+        this.volumeManager_, this.metadataModel_, this.shortcutsModel_,
+        this.ui_, entries);
+
+    freshModel.addEventListener('invalidated', () => {
+      this.clearLocalCache_(key);
+      this.selectionHandler_.onFileSelectionChanged();
+    }, {once: true});
+
+    // Once it's initialized, move to readyModels_ so we don't have to construct
+    // and initialized again.
+    freshModel.initialize().then(() => {
+      this.initializingModels_.delete(key);
+      this.readyModels_.set(key, freshModel!);
+    });
+
+    // Cache in the waiting initialization map.
+    this.initializingModels_.set(key, Promise.resolve(freshModel));
+    return Promise.resolve(freshModel);
+  }
+
+  executeAction(action: Action) {
+    const entries = action.getEntries();
+    const key = this.getEntriesKey_(entries);
+    // Invalidate the model early so new UI has to refresh it.
+    this.readyModels_.delete(key);
+    action.execute();
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model.js b/ui/file_manager/file_manager/foreground/js/actions_model.js
deleted file mode 100644
index 6b3603f9..0000000
--- a/ui/file_manager/file_manager/foreground/js/actions_model.js
+++ /dev/null
@@ -1,1061 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assert} from 'chrome://resources/ash/common/assert.js';
-import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
-import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
-
-import {isSameVolume, unwrapEntry} from '../../common/js/entry_utils.js';
-import {recordBoolean} from '../../common/js/metrics.js';
-import {strf} from '../../common/js/translations.js';
-import {visitURL} from '../../common/js/util.js';
-import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
-
-import {constants} from './constants.js';
-import {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
-import {MetadataModel} from './metadata/metadata_model.js';
-import {ActionModelUI} from './ui/action_model_ui.js';
-
-/**
- * A single action, that can be taken on a set of entries.
- * @interface
- */
-export class Action {
-  /**
-   * Executes this action on the set of entries.
-   */
-  execute() {}
-
-  /**
-   * Checks whether this action can execute on the set of entries.
-   *
-   * @return {boolean} True if the function can execute, false if not.
-   */
-  canExecute() {
-    return false;
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /**
-   * Entries that this Action will execute upon.
-   * @return {!Array<!Entry|!FileEntry>}
-   */
-  getEntries() {
-    return [];
-  }
-}
-
-/** @implements {Action} */
-class DriveShareAction {
-  /**
-   * @param {!Entry} entry
-   * @param {!MetadataModel} metadataModel
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   */
-  constructor(entry, metadataModel, volumeManager, ui) {
-    /**
-     * @private @type {!Entry}
-     * @const
-     */
-    this.entry_ = entry;
-
-    /**
-     * @private @type {!MetadataModel}
-     * @const
-     */
-    this.metadataModel_ = metadataModel;
-
-    /**
-     * @private @type {!import('../../externs/volume_manager.js').VolumeManager}
-     * @const
-     */
-    this.volumeManager_ = volumeManager;
-
-    /**
-     * @private @type {!ActionModelUI}
-     * @const
-     */
-    this.ui_ = ui;
-  }
-
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {!MetadataModel} metadataModel
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @return {DriveShareAction}
-   */
-  static create(entries, metadataModel, volumeManager, ui) {
-    if (entries.length !== 1) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveShareAction'.
-      return null;
-    }
-    // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry | undefined'
-    // is not assignable to parameter of type 'FileSystemEntry'.
-    return new DriveShareAction(entries[0], metadataModel, volumeManager, ui);
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveShareAction' does not
-  // extend another class.
-  execute() {
-    // Open the Sharing dialog in a new window.
-    chrome.fileManagerPrivate.getEntryProperties(
-        // @ts-ignore: error TS2322: Type 'FileSystemEntry | FilesAppEntry' is
-        // not assignable to type 'FileSystemEntry'.
-        [unwrapEntry(this.entry_)], ['shareUrl'], results => {
-          if (chrome.runtime.lastError) {
-            console.error(chrome.runtime.lastError.message);
-            return;
-          }
-          if (results.length != 1) {
-            console.warn(
-                'getEntryProperties for shareUrl should return 1 entry ' +
-                '(returned ' + results.length + ')');
-            return;
-          }
-          // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-          if (results[0].shareUrl === undefined) {
-            console.warn('getEntryProperties shareUrl is undefined');
-            return;
-          }
-          // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-          visitURL(assert(results[0].shareUrl));
-        });
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveShareAction' does not
-  // extend another class.
-  canExecute() {
-    const metadata = this.metadataModel_.getCache([this.entry_], ['canShare']);
-    assert(metadata.length === 1);
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    const canShareItem = metadata[0].canShare !== false;
-    return this.volumeManager_.getDriveConnectionState().type !==
-        chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE &&
-        canShareItem;
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveShareAction' does not
-  // extend another class.
-  getEntries() {
-    return [this.entry_];
-  }
-}
-
-
-/** @implements {Action} */
-class DriveToggleOfflineAction {
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {!MetadataModel} metadataModel
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @param {boolean} value
-   * @param {function():void} onExecute
-   */
-  constructor(entries, metadataModel, ui, volumeManager, value, onExecute) {
-    /**
-     * @private @type {!Array<!Entry>}
-     * @const
-     */
-    this.entries_ = entries;
-
-    /**
-     * @private @type {!MetadataModel}
-     * @const
-     */
-    this.metadataModel_ = metadataModel;
-
-    /**
-     * @private @type {!import('../../externs/volume_manager.js').VolumeManager}
-     * @const
-     */
-    this.volumeManager_ = volumeManager;
-
-    /**
-     * @private @type {!ActionModelUI}
-     * @const
-     */
-    this.ui_ = ui;
-
-    /**
-     * @private @type {boolean}
-     * @const
-     */
-    this.value_ = value;
-
-    /**
-     * @private @type {function():void}
-     * @const
-     */
-    this.onExecute_ = onExecute;
-  }
-
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {!MetadataModel} metadataModel
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @param {boolean} value
-   * @param {function():void} onExecute
-   * @return {DriveToggleOfflineAction}
-   */
-  static create(entries, metadataModel, ui, volumeManager, value, onExecute) {
-    const actionableEntries = entries.filter(
-        entry =>
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        metadataModel.getCache([entry], ['pinned'])[0].pinned !== value);
-
-    if (actionableEntries.length === 0) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveToggleOfflineAction'.
-      return null;
-    }
-
-    return new DriveToggleOfflineAction(
-        actionableEntries, metadataModel, ui, volumeManager, value, onExecute);
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveToggleOfflineAction'
-  // does not extend another class.
-  execute() {
-    const entries = this.entries_;
-    if (entries.length == 0) {
-      return;
-    }
-
-    // @ts-ignore: error TS7034: Variable 'currentEntry' implicitly has type
-    // 'any' in some locations where its type cannot be determined.
-    let currentEntry;
-    let error = false;
-
-    const steps = {
-      // Pick an entry and pin it.
-      start: () => {
-        // Check if all the entries are pinned or not.
-        if (entries.length === 0) {
-          return;
-        }
-        currentEntry = entries.shift();
-        // Skip files we cannot pin.
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        if (this.metadataModel_
-                // @ts-ignore: error TS2322: Type 'FileSystemEntry | undefined'
-                // is not assignable to type 'FileSystemEntry'.
-                .getCache([currentEntry], ['canPin'])[0]
-                .canPin) {
-          chrome.fileManagerPrivate.pinDriveFile(
-              // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry |
-              // undefined' is not assignable to parameter of type
-              // 'FileSystemEntry'.
-              currentEntry, this.value_, steps.entryPinned);
-        } else {
-          steps.start();
-        }
-      },
-
-      // Check the result of pinning.
-      entryPinned: () => {
-        error = !!chrome.runtime.lastError;
-        recordBoolean('DrivePinSuccess', !error);
-        // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has an
-        // 'any' type.
-        if (this.metadataModel_.getCache([currentEntry], ['hosted'])[0]
-                .hosted) {
-          recordBoolean('DriveHostedFilePinSuccess', !error);
-        }
-        if (error && this.value_) {
-          // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has an
-          // 'any' type.
-          this.metadataModel_.get([currentEntry], ['size']).then(results => {
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-            steps.showError(results[0].size);
-          });
-          return;
-        }
-        // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has an
-        // 'any' type.
-        this.metadataModel_.notifyEntriesChanged([currentEntry]);
-        // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has an
-        // 'any' type.
-        this.metadataModel_.get([currentEntry], ['pinned'])
-            .then(steps.updateUI);
-      },
-
-      // Update the user interface according to the cache state.
-      updateUI: () => {
-        // After execution of last entry call "onExecute_" to invalidate the
-        // model.
-        if (entries.length === 0) {
-          this.onExecute_();
-        }
-        this.ui_.listContainer.currentView.updateListItemsMetadata(
-            // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has
-            // an 'any' type.
-            'external', [currentEntry]);
-        if (!error) {
-          steps.start();
-        }
-      },
-
-      // Show an error.
-      // TODO(crbug.com/1138744): Migrate this error message to a visual signal.
-      // @ts-ignore: error TS7006: Parameter 'size' implicitly has an 'any'
-      // type.
-      showError: size => {
-        this.ui_.alertDialog.show(
-            // @ts-ignore: error TS7005: Variable 'currentEntry' implicitly has
-            // an 'any' type.
-            strf('OFFLINE_FAILURE_MESSAGE', unescape(currentEntry.name)), null,
-            // @ts-ignore: error TS2554: Expected 1-3 arguments, but got 4.
-            null, null);
-      },
-    };
-    steps.start();
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveToggleOfflineAction'
-  // does not extend another class.
-  canExecute() {
-    return this.metadataModel_.getCache(this.entries_, ['canPin'])
-        .some(metadata => metadata.canPin);
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveToggleOfflineAction'
-  // does not extend another class.
-  getEntries() {
-    return this.entries_;
-  }
-}
-
-
-/** @implements {Action} */
-class DriveCreateFolderShortcutAction {
-  /**
-   * @param {!Entry} entry
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {function():void} onExecute
-   */
-  constructor(entry, shortcutsModel, onExecute) {
-    /**
-     * @private @type {!Entry}
-     * @const
-     */
-    this.entry_ = entry;
-
-    /**
-     * @private @type {!FolderShortcutsDataModel}
-     * @const
-     */
-    this.shortcutsModel_ = shortcutsModel;
-
-    /**
-     * @private @type {function():void}
-     * @const
-     */
-    this.onExecute_ = onExecute;
-  }
-
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {function():void} onExecute
-   * @return {DriveCreateFolderShortcutAction}
-   */
-  static create(entries, volumeManager, shortcutsModel, onExecute) {
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    if (entries.length !== 1 || entries[0].isFile) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveCreateFolderShortcutAction'.
-      return null;
-    }
-    // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry | undefined'
-    // is not assignable to parameter of type 'FileSystemEntry | FilesAppEntry'.
-    const locationInfo = volumeManager.getLocationInfo(entries[0]);
-    if (!locationInfo || locationInfo.isSpecialSearchRoot ||
-        locationInfo.isRootEntry) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveCreateFolderShortcutAction'.
-      return null;
-    }
-    return new DriveCreateFolderShortcutAction(
-        // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry |
-        // undefined' is not assignable to parameter of type 'FileSystemEntry'.
-        entries[0], shortcutsModel, onExecute);
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveCreateFolderShortcutAction' does not extend another class.
-  execute() {
-    this.shortcutsModel_.add(this.entry_);
-    this.onExecute_();
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveCreateFolderShortcutAction' does not extend another class.
-  canExecute() {
-    return !this.shortcutsModel_.exists(this.entry_);
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveCreateFolderShortcutAction' does not extend another class.
-  getEntries() {
-    return [this.entry_];
-  }
-}
-
-
-/** @implements {Action} */
-class DriveRemoveFolderShortcutAction {
-  /**
-   * @param {!Entry} entry
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {function():void} onExecute
-   */
-  constructor(entry, shortcutsModel, onExecute) {
-    /**
-     * @private @type {!Entry}
-     * @const
-     */
-    this.entry_ = entry;
-
-    /**
-     * @private @type {!FolderShortcutsDataModel}
-     * @const
-     */
-    this.shortcutsModel_ = shortcutsModel;
-
-    /**
-     * @private @type {function():void}
-     * @const
-     */
-    this.onExecute_ = onExecute;
-  }
-
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {function():void} onExecute
-   * @return {DriveRemoveFolderShortcutAction}
-   */
-  static create(entries, shortcutsModel, onExecute) {
-    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-    if (entries.length !== 1 || entries[0].isFile ||
-        // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry |
-        // undefined' is not assignable to parameter of type 'FileSystemEntry'.
-        !shortcutsModel.exists(entries[0])) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveRemoveFolderShortcutAction'.
-      return null;
-    }
-    return new DriveRemoveFolderShortcutAction(
-        // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry |
-        // undefined' is not assignable to parameter of type 'FileSystemEntry'.
-        entries[0], shortcutsModel, onExecute);
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveRemoveFolderShortcutAction' does not extend another class.
-  execute() {
-    this.shortcutsModel_.remove(this.entry_);
-    this.onExecute_();
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveRemoveFolderShortcutAction' does not extend another class.
-  canExecute() {
-    return this.shortcutsModel_.exists(this.entry_);
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class
-  // 'DriveRemoveFolderShortcutAction' does not extend another class.
-  getEntries() {
-    return [this.entry_];
-  }
-}
-
-
-/**
- * Opens the entry in Drive Web for the user to manage permissions etc.
- *
- * @implements {Action}
- */
-class DriveManageAction {
-  /**
-   * @param {!Entry} entry The entry to open the 'Manage' page for.
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   */
-  constructor(entry, volumeManager, ui) {
-    /**
-     * The entry to open the 'Manage' page for.
-     *
-     * @private @type {!Entry}
-     * @const
-     */
-    this.entry_ = entry;
-
-    /**
-     * @private @type {!import('../../externs/volume_manager.js').VolumeManager}
-     * @const
-     */
-    this.volumeManager_ = volumeManager;
-
-    /**
-     * @private @type {!ActionModelUI}
-     * @const
-     */
-    this.ui_ = ui;
-  }
-
-  /**
-   * Creates a new DriveManageAction object.
-   * |entries| must contain only a single entry.
-   *
-   * @param {!Array<!Entry>} entries
-   * @param {!ActionModelUI} ui
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @return {DriveManageAction}
-   */
-  static create(entries, volumeManager, ui) {
-    if (entries.length !== 1) {
-      // @ts-ignore: error TS2322: Type 'null' is not assignable to type
-      // 'DriveManageAction'.
-      return null;
-    }
-
-    // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry | undefined'
-    // is not assignable to parameter of type 'FileSystemEntry'.
-    return new DriveManageAction(entries[0], volumeManager, ui);
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveManageAction' does not
-  // extend another class.
-  execute() {
-    chrome.fileManagerPrivate.getEntryProperties(
-        // @ts-ignore: error TS2322: Type 'FileSystemEntry | FilesAppEntry' is
-        // not assignable to type 'FileSystemEntry'.
-        [unwrapEntry(this.entry_)], ['alternateUrl'], results => {
-          if (chrome.runtime.lastError) {
-            console.error(chrome.runtime.lastError.message);
-            return;
-          }
-          if (results.length != 1) {
-            console.warn(
-                'getEntryProperties for alternateUrl should return 1 entry ' +
-                '(returned ' + results.length + ')');
-            return;
-          }
-          // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-          if (results[0].alternateUrl === undefined) {
-            console.warn('getEntryProperties alternateUrl is undefined');
-            return;
-          }
-          // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-          visitURL(assert(results[0].alternateUrl));
-        });
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveManageAction' does not
-  // extend another class.
-  canExecute() {
-    return this.volumeManager_.getDriveConnectionState().type !==
-        chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE;
-  }
-
-  /**
-   * @return {?string}
-   */
-  getTitle() {
-    return null;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'DriveManageAction' does not
-  // extend another class.
-  getEntries() {
-    return [this.entry_];
-  }
-}
-
-
-/**
- * A custom action set by the FSP API.
- *
- * @implements {Action}
- */
-class CustomAction {
-  /**
-   * @param {!Array<!Entry>} entries
-   * @param {string} id
-   * @param {?string} title
-   * @param {function():void} onExecute
-   */
-  constructor(entries, id, title, onExecute) {
-    /**
-     * @private @type {!Array<!Entry>}
-     * @const
-     */
-    this.entries_ = entries;
-
-    /**
-     * @private @type {string}
-     * @const
-     */
-    this.id_ = id;
-
-    /**
-     * @private @type {?string}
-     * @const
-     */
-    this.title_ = title;
-
-    /**
-     * @private @type {function():void}
-     * @const
-     */
-    this.onExecute_ = onExecute;
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'CustomAction' does not extend
-  // another class.
-  execute() {
-    chrome.fileManagerPrivate.executeCustomAction(
-        // @ts-ignore: error TS2345: Argument of type '(FileSystemEntry |
-        // FilesAppEntry)[]' is not assignable to parameter of type
-        // 'FileSystemEntry[]'.
-        this.entries_.map(e => unwrapEntry(e)), this.id_, () => {
-          if (chrome.runtime.lastError) {
-            console.error(
-                'Failed to execute a custom action because of: ' +
-                chrome.runtime.lastError.message);
-          }
-          this.onExecute_();
-        });
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'CustomAction' does not extend
-  // another class.
-  canExecute() {
-    return true;  // Custom actions are always executable.
-  }
-
-  /**
-   * @override
-   */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'CustomAction' does not extend
-  // another class.
-  getTitle() {
-    return this.title_;
-  }
-
-  /** @override */
-  // @ts-ignore: error TS4121: This member cannot have a JSDoc comment with an
-  // '@override' tag because its containing class 'CustomAction' does not extend
-  // another class.
-  getEntries() {
-    return this.entries_;
-  }
-}
-
-/**
- * Represents a set of actions for a set of entries. Includes actions set
- * locally in JS, as well as those retrieved from the FSP API.
- */
-export class ActionsModel extends EventTarget {
-  /**
-   * @param {!import('../../externs/volume_manager.js').VolumeManager}
-   *     volumeManager
-   * @param {!MetadataModel} metadataModel
-   * @param {!FolderShortcutsDataModel} shortcutsModel
-   * @param {!ActionModelUI} ui
-   * @param {!Array<!Entry>} entries
-   */
-  constructor(volumeManager, metadataModel, shortcutsModel, ui, entries) {
-    super();
-
-    /**
-     * @private @type {!import('../../externs/volume_manager.js').VolumeManager}
-     * @const
-     */
-    this.volumeManager_ = volumeManager;
-
-    /**
-     * @private @type {!MetadataModel}
-     * @const
-     */
-    this.metadataModel_ = metadataModel;
-
-    /**
-     * @private @type {!FolderShortcutsDataModel}
-     * @const
-     */
-    this.shortcutsModel_ = shortcutsModel;
-
-    /**
-     * @private @type {!ActionModelUI}
-     * @const
-     */
-    this.ui_ = ui;
-
-    /**
-     * @private @type {!Array<!Entry>}
-     * @const
-     */
-    this.entries_ = entries;
-
-    /**
-     * @private @type {!Record<string, !Action>}
-     */
-    this.actions_ = {};
-
-    /**
-     * @private @type {?function():void}
-     */
-    this.initializePromiseReject_ = null;
-
-    /**
-     * @private @type {?Promise<void>}
-     */
-    this.initializePromise_ = null;
-
-    /**
-     * @private @type {boolean}
-     */
-    this.destroyed_ = false;
-  }
-
-  /**
-   * Initializes the ActionsModel, including populating the list of available
-   * actions for the given entries.
-   * @return {!Promise<void>}
-   */
-  initialize() {
-    if (this.initializePromise_) {
-      return this.initializePromise_;
-    }
-
-    this.initializePromise_ =
-        new Promise((fulfill, reject) => {
-          if (this.destroyed_) {
-            reject();
-            return;
-          }
-          this.initializePromiseReject_ = reject;
-
-          const volumeInfo = this.entries_.length >= 1 &&
-              // @ts-ignore: error TS2345: Argument of type 'FileSystemEntry |
-              // undefined' is not assignable to parameter of type
-              // 'FileSystemEntry | FilesAppEntry'.
-              this.volumeManager_.getVolumeInfo(this.entries_[0]);
-          // All entries need to be on the same volume to execute ActionsModel
-          // commands.
-          if (!volumeInfo ||
-              !isSameVolume(this.entries_, this.volumeManager_)) {
-            fulfill({});
-            return;
-          }
-
-          const actions = {};
-          switch (volumeInfo.volumeType) {
-            // For Drive, actions are constructed directly in the Files app
-            // code.
-            case VolumeManagerCommon.VolumeType.DRIVE:
-              const shareAction = DriveShareAction.create(
-                  this.entries_, this.metadataModel_, this.volumeManager_,
-                  this.ui_);
-              if (shareAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.CommonActionId.SHARE] = shareAction;
-              }
-
-              const saveForOfflineAction = DriveToggleOfflineAction.create(
-                  this.entries_, this.metadataModel_, this.ui_,
-                  this.volumeManager_, true, this.invalidate_.bind(this));
-              if (saveForOfflineAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE] =
-                    saveForOfflineAction;
-              }
-
-              const offlineNotNecessaryAction = DriveToggleOfflineAction.create(
-                  this.entries_, this.metadataModel_, this.ui_,
-                  this.volumeManager_, false, this.invalidate_.bind(this));
-              if (offlineNotNecessaryAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY] =
-                    offlineNotNecessaryAction;
-              }
-
-              const createFolderShortcutAction =
-                  DriveCreateFolderShortcutAction.create(
-                      this.entries_, this.volumeManager_, this.shortcutsModel_,
-                      this.invalidate_.bind(this));
-              if (createFolderShortcutAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT] =
-                    createFolderShortcutAction;
-              }
-
-              const removeFolderShortcutAction =
-                  DriveRemoveFolderShortcutAction.create(
-                      this.entries_, this.shortcutsModel_,
-                      this.invalidate_.bind(this));
-              if (removeFolderShortcutAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.InternalActionId.REMOVE_FOLDER_SHORTCUT] =
-                    removeFolderShortcutAction;
-              }
-
-              const manageInDriveAction = DriveManageAction.create(
-                  this.entries_, this.volumeManager_, this.ui_);
-              if (manageInDriveAction) {
-                // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                // type because expression of type 'string' can't be used to
-                // index type '{}'.
-                actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE] =
-                    manageInDriveAction;
-              }
-
-              fulfill(actions);
-              break;
-
-            // For FSP, fetch custom actions via an API.
-            case VolumeManagerCommon.VolumeType.PROVIDED:
-              chrome.fileManagerPrivate.getCustomActions(
-                  // @ts-ignore: error TS2345: Argument of type
-                  // '(FileSystemEntry | FilesAppEntry)[]' is not assignable to
-                  // parameter of type 'FileSystemEntry[]'.
-                  this.entries_.map(e => unwrapEntry(e)), customActions => {
-                    if (chrome.runtime.lastError) {
-                      console.error(
-                          'Failed to fetch custom actions because of: ' +
-                          chrome.runtime.lastError.message);
-                    } else {
-                      customActions.forEach(action => {
-                        // Skip fake actions that should not be displayed to the
-                        // user, for example actions that just expose OneDrive
-                        // URLs.
-                        // TODO(b/237216270): Restrict to the ODFS extension ID.
-                        if (action.id ===
-                            constants.FSP_ACTION_HIDDEN_ONEDRIVE_URL) {
-                          return;
-                        }
-                        if (action.id ===
-                            constants.FSP_ACTION_HIDDEN_ONEDRIVE_USER_EMAIL) {
-                          return;
-                        }
-                        if (action.id ===
-                            constants
-                                .FSP_ACTION_HIDDEN_ONEDRIVE_REAUTHENTICATION_REQUIRED) {
-                          return;
-                        }
-                        // @ts-ignore: error TS7053: Element implicitly has an
-                        // 'any' type because expression of type 'string' can't
-                        // be used to index type '{}'.
-                        actions[action.id] = new CustomAction(
-                            this.entries_, action.id, action.title || null,
-                            this.invalidate_.bind(this));
-                      });
-                    }
-                    fulfill(actions);
-                  });
-              break;
-
-            default:
-              fulfill(actions);
-          }
-        }).then(actions => {
-          this.actions_ = actions;
-        });
-
-    return this.initializePromise_;
-  }
-
-  /**
-   * @return {!Record<string, !Action>}
-   */
-  getActions() {
-    return this.actions_;
-  }
-
-  /**
-   * @param {string} id
-   * @return {Action}
-   */
-  getAction(id) {
-    // @ts-ignore: error TS7053: Element implicitly has an 'any' type because
-    // expression of type 'string' can't be used to index type '{}'.
-    return this.actions_[id] || null;
-  }
-
-  /**
-   * Destroys the model and cancels initialization if in progress.
-   */
-  destroy() {
-    this.destroyed_ = true;
-    if (this.initializePromiseReject_ !== null) {
-      const reject = this.initializePromiseReject_;
-      this.initializePromiseReject_ = null;
-      reject();
-    }
-  }
-
-  /**
-   * Invalidates the current actions model by emitting an invalidation event.
-   * The model has to be initialized again, as the list of actions might have
-   * changed.
-   *
-   * @private
-   */
-  invalidate_() {
-    if (this.initializePromiseReject_ !== null) {
-      const reject = this.initializePromiseReject_;
-      this.initializePromiseReject_ = null;
-      this.initializePromise_ = null;
-      reject();
-    }
-    dispatchSimpleEvent(this, 'invalidated', true);
-  }
-
-  /**
-   * @return {!Array<!Entry>}
-   * @public
-   */
-  getEntries() {
-    return this.entries_;
-  }
-}
-
-/**
- * List of common actions, used both internally and externally (custom actions).
- * Keep in sync with file_system_provider.idl.
- * @enum {string}
- */
-ActionsModel.CommonActionId = {
-  SHARE: 'SHARE',
-  SAVE_FOR_OFFLINE: 'SAVE_FOR_OFFLINE',
-  OFFLINE_NOT_NECESSARY: 'OFFLINE_NOT_NECESSARY',
-};
-
-/**
- * @enum {string}
- */
-ActionsModel.InternalActionId = {
-  CREATE_FOLDER_SHORTCUT: 'pin-folder',
-  REMOVE_FOLDER_SHORTCUT: 'unpin-folder',
-  MANAGE_IN_DRIVE: 'manage-in-drive',
-};
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model.ts b/ui/file_manager/file_manager/foreground/js/actions_model.ts
new file mode 100644
index 0000000..aeef8fc9
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/actions_model.ts
@@ -0,0 +1,579 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
+import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
+import {assert} from 'chrome://resources/js/assert.js';
+
+import {isDirectoryEntry, isSameVolume, unwrapEntry} from '../../common/js/entry_utils.js';
+import {recordBoolean} from '../../common/js/metrics.js';
+import {strf} from '../../common/js/translations.js';
+import {visitURL} from '../../common/js/util.js';
+import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
+import type {VolumeManager} from '../../externs/volume_manager.js';
+
+import {constants} from './constants.js';
+import type {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
+import type {MetadataModel} from './metadata/metadata_model.js';
+import type {ActionModelUI} from './ui/action_model_ui.js';
+
+type ActionsMap =
+    Partial<Record<CommonActionId|InternalActionId|string, Action>>;
+
+/**
+ * A single action, that can be taken on a set of entries.
+ */
+export abstract class Action {
+  /**
+   * Executes this action on the set of entries.
+   */
+  abstract execute(): void;
+
+  /**
+   * Checks whether this action can execute on the set of entries.
+   *
+   * @return True if the function can execute, false if not.
+   */
+  abstract canExecute(): boolean;
+
+  abstract getTitle(): string|null;
+
+  /**
+   * Entries that this Action will execute upon.
+   */
+  abstract getEntries(): Array<Entry|FileEntry>;
+}
+
+class DriveShareAction implements Action {
+  constructor(
+      private entry_: Entry, private metadataModel_: MetadataModel,
+      private volumeManager_: VolumeManager) {}
+
+  static create(
+      entries: Entry[], metadataModel: MetadataModel,
+      volumeManager: VolumeManager) {
+    if (entries.length !== 1) {
+      return null;
+    }
+    return new DriveShareAction(entries[0]!, metadataModel, volumeManager);
+  }
+
+  execute() {
+    // Open the Sharing dialog in a new window.
+    chrome.fileManagerPrivate.getEntryProperties(
+        [unwrapEntry(this.entry_) as Entry], ['shareUrl'],
+        (results: chrome.fileManagerPrivate.EntryProperties[]) => {
+          if (chrome.runtime.lastError) {
+            console.error(chrome.runtime.lastError.message);
+            return;
+          }
+          if (results.length !== 1) {
+            console.warn(
+                'getEntryProperties for shareUrl should return 1 entry ' +
+                '(returned ' + results.length + ')');
+            return;
+          }
+          if (results[0]!.shareUrl === undefined) {
+            console.warn('getEntryProperties shareUrl is undefined');
+            return;
+          }
+          visitURL(results[0]!.shareUrl);
+        });
+  }
+
+  canExecute() {
+    const metadata = this.metadataModel_.getCache([this.entry_], ['canShare']);
+    assert(metadata.length === 1);
+    const canShareItem = metadata[0]!.canShare !== false;
+    return this.volumeManager_.getDriveConnectionState().type !==
+        chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE &&
+        canShareItem;
+  }
+
+  getTitle() {
+    return null;
+  }
+
+  getEntries() {
+    return [this.entry_];
+  }
+}
+
+
+class DriveToggleOfflineAction implements Action {
+  constructor(
+      private entries_: Entry[], private metadataModel_: MetadataModel,
+      private ui_: ActionModelUI, private value_: boolean,
+      private onExecute_: VoidCallback) {}
+
+  static create(
+      entries: Entry[], metadataModel: MetadataModel, ui: ActionModelUI,
+      value: boolean, onExecute: VoidCallback) {
+    const actionableEntries = entries.filter(
+        entry =>
+            metadataModel.getCache([entry], ['pinned'])[0]?.pinned !== value);
+
+    if (actionableEntries.length === 0) {
+      return null;
+    }
+
+    return new DriveToggleOfflineAction(
+        actionableEntries, metadataModel, ui, value, onExecute);
+  }
+
+  execute() {
+    const entries = this.entries_;
+    if (entries.length == 0) {
+      return;
+    }
+
+    let currentEntry: Entry;
+    let error = false;
+
+    const steps = {
+      // Pick an entry and pin it.
+      start: () => {
+        // Check if all the entries are pinned or not.
+        if (entries.length === 0) {
+          return;
+        }
+        currentEntry = entries.shift()!;
+        // Skip files we cannot pin.
+        if (this.metadataModel_.getCache([currentEntry], ['canPin'])[0]
+                ?.canPin) {
+          chrome.fileManagerPrivate.pinDriveFile(
+              currentEntry, this.value_, steps.entryPinned);
+        } else {
+          steps.start();
+        }
+      },
+
+      // Check the result of pinning.
+      entryPinned: () => {
+        error = !!chrome.runtime.lastError;
+        recordBoolean('DrivePinSuccess', !error);
+        if (this.metadataModel_.getCache([currentEntry], ['hosted'])[0]
+                ?.hosted) {
+          recordBoolean('DriveHostedFilePinSuccess', !error);
+        }
+        if (error && this.value_) {
+          this.metadataModel_.get([currentEntry], ['size']).then(() => {
+            steps.showError();
+          });
+          return;
+        }
+        this.metadataModel_.notifyEntriesChanged([currentEntry]);
+        this.metadataModel_.get([currentEntry], ['pinned'])
+            .then(steps.updateUI);
+      },
+
+      // Update the user interface according to the cache state.
+      updateUI: () => {
+        // After execution of last entry call "onExecute_" to invalidate the
+        // model.
+        if (entries.length === 0) {
+          this.onExecute_();
+        }
+        this.ui_.listContainer.currentView.updateListItemsMetadata(
+            'external', [currentEntry]);
+        if (!error) {
+          steps.start();
+        }
+      },
+
+      // Show an error.
+      // TODO(crbug.com/1138744): Migrate this error message to a visual signal.
+      showError: () => {
+        this.ui_.alertDialog.show(
+            strf('OFFLINE_FAILURE_MESSAGE', unescape(currentEntry.name)),
+            undefined, undefined);
+      },
+    };
+    steps.start();
+  }
+
+  canExecute() {
+    return this.metadataModel_.getCache(this.entries_, ['canPin'])
+        .some(metadata => metadata.canPin);
+  }
+
+  getTitle() {
+    return null;
+  }
+
+  getEntries() {
+    return this.entries_;
+  }
+}
+
+
+class DriveCreateFolderShortcutAction implements Action {
+  constructor(
+      private entry_: Entry, private shortcutsModel_: FolderShortcutsDataModel,
+      private onExecute_: VoidCallback) {}
+
+  static create(
+      entries: Entry[], volumeManager: VolumeManager,
+      shortcutsModel: FolderShortcutsDataModel, onExecute: VoidCallback) {
+    if (entries.length !== 1 || !isDirectoryEntry(entries[0]!)) {
+      return null;
+    }
+    const locationInfo = volumeManager.getLocationInfo(entries[0]);
+    if (!locationInfo || locationInfo.isSpecialSearchRoot ||
+        locationInfo.isRootEntry) {
+      return null;
+    }
+    return new DriveCreateFolderShortcutAction(
+        entries[0], shortcutsModel, onExecute);
+  }
+
+  execute() {
+    this.shortcutsModel_.add(this.entry_);
+    this.onExecute_();
+  }
+
+  canExecute() {
+    return !this.shortcutsModel_.exists(this.entry_);
+  }
+
+  getTitle() {
+    return null;
+  }
+
+  getEntries() {
+    return [this.entry_];
+  }
+}
+
+
+class DriveRemoveFolderShortcutAction implements Action {
+  constructor(
+      private entry_: Entry, private shortcutsModel_: FolderShortcutsDataModel,
+      private onExecute_: VoidCallback) {}
+
+  static create(
+      entries: Entry[], shortcutsModel: FolderShortcutsDataModel,
+      onExecute: VoidCallback) {
+    if (entries.length !== 1 || !isDirectoryEntry(entries[0]!) ||
+        !shortcutsModel.exists(entries[0])) {
+      return null;
+    }
+    return new DriveRemoveFolderShortcutAction(
+        entries[0], shortcutsModel, onExecute);
+  }
+
+  execute() {
+    this.shortcutsModel_.remove(this.entry_);
+    this.onExecute_();
+  }
+
+  canExecute() {
+    return this.shortcutsModel_.exists(this.entry_);
+  }
+
+  getTitle() {
+    return null;
+  }
+
+  getEntries() {
+    return [this.entry_];
+  }
+}
+
+
+/**
+ * Opens the entry in Drive Web for the user to manage permissions etc.
+ */
+class DriveManageAction implements Action {
+  /**
+   * @param entry The entry to open the 'Manage' page for.
+   */
+  constructor(private entry_: Entry, private volumeManager_: VolumeManager) {}
+
+  /**
+   * Creates a new DriveManageAction object.
+   * |entries| must contain only a single entry.
+   */
+  static create(entries: Entry[], volumeManager: VolumeManager) {
+    if (entries.length !== 1) {
+      return null;
+    }
+
+    return new DriveManageAction(entries[0]!, volumeManager);
+  }
+
+  execute() {
+    chrome.fileManagerPrivate.getEntryProperties(
+        [unwrapEntry(this.entry_) as Entry], ['alternateUrl'],
+        (results: chrome.fileManagerPrivate.EntryProperties[]) => {
+          if (chrome.runtime.lastError) {
+            console.error(chrome.runtime.lastError.message);
+            return;
+          }
+          if (results.length !== 1) {
+            console.warn(
+                'getEntryProperties for alternateUrl should return 1 entry ' +
+                '(returned ' + results.length + ')');
+            return;
+          }
+          if (results[0]!.alternateUrl === undefined) {
+            console.warn('getEntryProperties alternateUrl is undefined');
+            return;
+          }
+          visitURL(results[0]!.alternateUrl);
+        });
+  }
+
+  canExecute() {
+    return this.volumeManager_.getDriveConnectionState().type !==
+        chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE;
+  }
+
+  getTitle() {
+    return null;
+  }
+
+  getEntries() {
+    return [this.entry_];
+  }
+}
+
+
+/**
+ * A custom action set by the FSP API.
+ */
+class CustomAction implements Action {
+  constructor(
+      private entries_: Entry[], private id_: string,
+      private title_: string|null, private onExecute_: VoidCallback) {}
+
+  execute() {
+    chrome.fileManagerPrivate.executeCustomAction(
+        this.entries_.map(e => unwrapEntry(e)) as Entry[], this.id_, () => {
+          if (chrome.runtime.lastError) {
+            console.error(
+                'Failed to execute a custom action because of: ' +
+                chrome.runtime.lastError.message);
+          }
+          this.onExecute_();
+        });
+  }
+
+  canExecute() {
+    return true;  // Custom actions are always executable.
+  }
+
+  getTitle() {
+    return this.title_;
+  }
+
+  getEntries() {
+    return this.entries_;
+  }
+}
+
+/**
+ * Represents a set of actions for a set of entries. Includes actions set
+ * locally in JS, as well as those retrieved from the FSP API.
+ */
+export class ActionsModel extends EventTarget {
+  private actions_: ActionsMap = {};
+
+  private initializePromiseReject_: VoidCallback|null = null;
+
+  private initializePromise_: Promise<void>|null = null;
+
+  private destroyed_ = false;
+
+  constructor(
+      private volumeManager_: VolumeManager,
+      private metadataModel_: MetadataModel,
+      private shortcutsModel_: FolderShortcutsDataModel,
+      private ui_: ActionModelUI, private entries_: Entry[]) {
+    super();
+  }
+
+  /**
+   * Initializes the ActionsModel, including populating the list of available
+   * actions for the given entries.
+   */
+  initialize() {
+    if (this.initializePromise_) {
+      return this.initializePromise_;
+    }
+
+    this.initializePromise_ =
+        new Promise((fulfill: (value: ActionsMap) => void, reject) => {
+          if (this.destroyed_) {
+            reject();
+            return;
+          }
+          this.initializePromiseReject_ = reject;
+
+          const volumeInfo = this.entries_.length >= 1 &&
+              this.volumeManager_.getVolumeInfo(this.entries_[0]!);
+          // All entries need to be on the same volume to execute ActionsModel
+          // commands.
+          if (!volumeInfo ||
+              !isSameVolume(this.entries_, this.volumeManager_)) {
+            fulfill({});
+            return;
+          }
+
+          const actions: ActionsMap = {};
+          switch (volumeInfo.volumeType) {
+            // For Drive, actions are constructed directly in the Files app
+            // code.
+            case VolumeManagerCommon.VolumeType.DRIVE:
+              const shareAction = DriveShareAction.create(
+                  this.entries_, this.metadataModel_, this.volumeManager_);
+              if (shareAction) {
+                actions[CommonActionId.SHARE] = shareAction;
+              }
+
+              const saveForOfflineAction = DriveToggleOfflineAction.create(
+                  this.entries_, this.metadataModel_, this.ui_, true,
+                  this.invalidate_.bind(this));
+              if (saveForOfflineAction) {
+                actions[CommonActionId.SAVE_FOR_OFFLINE] = saveForOfflineAction;
+              }
+
+              const offlineNotNecessaryAction = DriveToggleOfflineAction.create(
+                  this.entries_, this.metadataModel_, this.ui_, false,
+                  this.invalidate_.bind(this));
+              if (offlineNotNecessaryAction) {
+                actions[CommonActionId.OFFLINE_NOT_NECESSARY] =
+                    offlineNotNecessaryAction;
+              }
+
+              const createFolderShortcutAction =
+                  DriveCreateFolderShortcutAction.create(
+                      this.entries_, this.volumeManager_, this.shortcutsModel_,
+                      this.invalidate_.bind(this));
+              if (createFolderShortcutAction) {
+                actions[InternalActionId.CREATE_FOLDER_SHORTCUT] =
+                    createFolderShortcutAction;
+              }
+
+              const removeFolderShortcutAction =
+                  DriveRemoveFolderShortcutAction.create(
+                      this.entries_, this.shortcutsModel_,
+                      this.invalidate_.bind(this));
+              if (removeFolderShortcutAction) {
+                actions[InternalActionId.REMOVE_FOLDER_SHORTCUT] =
+                    removeFolderShortcutAction;
+              }
+
+              const manageInDriveAction =
+                  DriveManageAction.create(this.entries_, this.volumeManager_);
+              if (manageInDriveAction) {
+                actions[InternalActionId.MANAGE_IN_DRIVE] = manageInDriveAction;
+              }
+
+              fulfill(actions);
+              break;
+
+            // For FSP, fetch custom actions via an API.
+            case VolumeManagerCommon.VolumeType.PROVIDED:
+              chrome.fileManagerPrivate.getCustomActions(
+                  this.entries_.map(e => unwrapEntry(e)) as Entry[],
+                  (customActions: chrome.fileManagerPrivate
+                       .FileSystemProviderAction[]) => {
+                    if (chrome.runtime.lastError) {
+                      console.error(
+                          'Failed to fetch custom actions because of: ' +
+                          chrome.runtime.lastError.message);
+                    } else {
+                      customActions.forEach(action => {
+                        // Skip fake actions that should not be displayed to the
+                        // user, for example actions that just expose OneDrive
+                        // URLs.
+                        // TODO(b/237216270): Restrict to the ODFS extension ID.
+                        if (action.id ===
+                            constants.FSP_ACTION_HIDDEN_ONEDRIVE_URL) {
+                          return;
+                        }
+                        if (action.id ===
+                            constants.FSP_ACTION_HIDDEN_ONEDRIVE_USER_EMAIL) {
+                          return;
+                        }
+                        if (action.id ===
+                            constants
+                                .FSP_ACTION_HIDDEN_ONEDRIVE_REAUTHENTICATION_REQUIRED) {
+                          return;
+                        }
+                        actions[action.id] = new CustomAction(
+                            this.entries_, action.id, action.title || null,
+                            this.invalidate_.bind(this));
+                      });
+                    }
+                    fulfill(actions);
+                  });
+              break;
+
+            default:
+              fulfill(actions);
+          }
+        }).then(actions => {
+          this.actions_ = actions;
+        });
+
+    return this.initializePromise_;
+  }
+
+  getActions() {
+    return this.actions_;
+  }
+
+  getAction(id: string) {
+    return this.actions_[id] || null;
+  }
+
+  /**
+   * Destroys the model and cancels initialization if in progress.
+   */
+  destroy() {
+    this.destroyed_ = true;
+    if (this.initializePromiseReject_ !== null) {
+      const reject = this.initializePromiseReject_;
+      this.initializePromiseReject_ = null;
+      reject();
+    }
+  }
+
+  /**
+   * Invalidates the current actions model by emitting an invalidation event.
+   * The model has to be initialized again, as the list of actions might have
+   * changed.
+   */
+  private invalidate_() {
+    if (this.initializePromiseReject_ !== null) {
+      const reject = this.initializePromiseReject_;
+      this.initializePromiseReject_ = null;
+      this.initializePromise_ = null;
+      reject();
+    }
+    dispatchSimpleEvent(this, 'invalidated', true);
+  }
+
+  getEntries() {
+    return this.entries_;
+  }
+}
+
+/**
+ * List of common actions, used both internally and externally (custom actions).
+ * Keep in sync with file_system_provider.idl.
+ */
+export enum CommonActionId {
+  SHARE = 'SHARE',
+  SAVE_FOR_OFFLINE = 'SAVE_FOR_OFFLINE',
+  OFFLINE_NOT_NECESSARY = 'OFFLINE_NOT_NECESSARY',
+}
+
+export enum InternalActionId {
+  CREATE_FOLDER_SHORTCUT = 'pin-folder',
+  REMOVE_FOLDER_SHORTCUT = 'unpin-folder',
+  MANAGE_IN_DRIVE = 'manage-in-drive',
+}
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
deleted file mode 100644
index 209b87c..0000000
--- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
+++ /dev/null
@@ -1,1006 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assert} from 'chrome://resources/ash/common/assert.js';
-import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
-
-import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
-import {installMockChrome, MockCommandLinePrivate, MockMetrics} from '../../common/js/mock_chrome.js';
-import {MockDirectoryEntry, MockFileEntry} from '../../common/js/mock_entry.js';
-import {reportPromise} from '../../common/js/test_error_reporting.js';
-import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
-
-import {ActionsModel} from './actions_model.js';
-import {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
-import {MockMetadataModel} from './metadata/mock_metadata.js';
-import {ActionModelUI} from './ui/action_model_ui.js';
-import {FilesAlertDialog} from './ui/files_alert_dialog.js';
-import {ListContainer} from './ui/list_container.js';
-
-/**
- * @type {!MockVolumeManager}
- */
-let volumeManager;
-
-/**
- * @type {!FileSystem}
- */
-let driveFileSystem;
-
-/**
- * @type {!FileSystem}
- */
-let providedFileSystem;
-
-/** @type {!MockMetrics} */
-let mockMetrics;
-
-/**
- * @param {string} metricName
- * @returns {number} total number of calls for that metric.
- */
-function countMetricCalls(metricName) {
-  const calls = mockMetrics.metricCalls;
-  return (calls[metricName] || []).length;
-}
-
-/**
- * @returns {!FolderShortcutsDataModel}
- */
-function createFakeFolderShortcutsDataModel() {
-  class FakeFolderShortcutsModel extends EventTarget {
-    constructor() {
-      super();
-      this.has = false;
-    }
-
-    exists() {
-      return this.has;
-    }
-
-    // @ts-ignore: error TS7006: Parameter 'entry' implicitly has an 'any' type.
-    add(entry) {
-      this.has = true;
-      return 0;
-    }
-
-    // @ts-ignore: error TS7006: Parameter 'entry' implicitly has an 'any' type.
-    remove(entry) {
-      this.has = false;
-      return 0;
-    }
-  }
-
-  const model = /** @type {!Object} */ (new FakeFolderShortcutsModel());
-  return /** @type {!FolderShortcutsDataModel} */ (model);
-}
-
-/**
- * @type {!FolderShortcutsDataModel}
- */
-let shortcutsModel;
-
-/** @implements ActionModelUI */
-class MockUI {
-  constructor() {
-    // @ts-ignore: error TS2352: Conversion of type '{ currentView: {
-    // updateListItemsMetadata: () => void; }; }' to type 'ListContainer' may be
-    // a mistake because neither type sufficiently overlaps with the other. If
-    // this was intentional, convert the expression to 'unknown' first.
-    this.listContainer = /** @type {!ListContainer} */ ({
-      currentView: {
-        updateListItemsMetadata: function() {},
-      },
-    });
-
-    // @ts-ignore: error TS2352: Conversion of type '{ showHtml: () => void; }'
-    // to type 'FilesAlertDialog' may be a mistake because neither type
-    // sufficiently overlaps with the other. If this was intentional, convert
-    // the expression to 'unknown' first.
-    this.alertDialog = /** @type {!FilesAlertDialog} */ ({
-      showHtml: function() {},
-    });
-  }
-}
-
-/**
- * @type {!MockUI}
- */
-let ui;
-
-export function setUp() {
-  mockMetrics = new MockMetrics();
-  // Mock Chrome APIs.
-  const mockChrome = {
-    metricsPrivate: mockMetrics,
-    runtime: {
-      lastError: null,
-    },
-  };
-  installMockChrome(mockChrome);
-  new MockCommandLinePrivate();
-
-  // Setup Drive file system.
-  volumeManager = new MockVolumeManager();
-  let type = VolumeManagerCommon.VolumeType.DRIVE;
-  driveFileSystem =
-      // @ts-ignore: error TS2531: Object is possibly 'null'.
-      assert(volumeManager.getCurrentProfileVolumeInfo(type).fileSystem);
-
-  // Setup Provided file system.
-  type = VolumeManagerCommon.VolumeType.PROVIDED;
-  volumeManager.createVolumeInfo(type, 'provided', 'Provided');
-  providedFileSystem =
-      // @ts-ignore: error TS2531: Object is possibly 'null'.
-      assert(volumeManager.getCurrentProfileVolumeInfo(type).fileSystem);
-
-  // Create mock action model components.
-  shortcutsModel = createFakeFolderShortcutsDataModel();
-  ui = new MockUI();
-}
-
-/**
- * Tests that the correct actions are available for a Google Drive directory.
- * @param {()=>void} callback
- */
-export function testDriveDirectoryEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test'] =
-      MockDirectoryEntry.create(driveFileSystem, '/test');
-
-  const metadataModel = new MockMetadataModel({
-    canShare: true,
-  });
-
-  let model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [driveFileSystem.entries['/test']]);
-
-  let invalidated = 0;
-  model.addEventListener('invalidated', () => {
-    invalidated++;
-  });
-
-  return reportPromise(
-      model.initialize()
-          .then(() => {
-            const actions = model.getActions();
-            assertEquals(5, Object.keys(actions).length);
-
-            // 'Share' should be disabled in offline mode.
-            const shareAction = actions[ActionsModel.CommonActionId.SHARE];
-            assertTrue(!!shareAction);
-            volumeManager.driveConnectionState = {
-              type: chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE,
-            };
-            // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-            assertFalse(shareAction.canExecute());
-
-            // 'Manage in Drive' should be disabled in offline mode.
-            const manageInDriveAction =
-                actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-            assertTrue(!!manageInDriveAction);
-            // @ts-ignore: error TS18048: 'manageInDriveAction' is possibly
-            // 'undefined'.
-            assertFalse(manageInDriveAction.canExecute());
-
-            // 'Create Shortcut' should be enabled, until it's executed, then
-            // disabled.
-            const createFolderShortcutAction =
-                actions[ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT];
-            assertTrue(!!createFolderShortcutAction);
-            // @ts-ignore: error TS18048: 'createFolderShortcutAction' is
-            // possibly 'undefined'.
-            assertTrue(createFolderShortcutAction.canExecute());
-            // @ts-ignore: error TS18048: 'createFolderShortcutAction' is
-            // possibly 'undefined'.
-            createFolderShortcutAction.execute();
-            // @ts-ignore: error TS18048: 'createFolderShortcutAction' is
-            // possibly 'undefined'.
-            assertFalse(createFolderShortcutAction.canExecute());
-            assertEquals(1, invalidated);
-
-            // The model is invalidated, as list of actions have changed.
-            // Recreated the model and check that the actions are updated.
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                // @ts-ignore: error TS2339: Property 'entries' does not exist
-                // on type 'FileSystem'.
-                [driveFileSystem.entries['/test']]);
-            model.addEventListener('invalidated', () => {
-              invalidated++;
-            });
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-            assertEquals(6, Object.keys(actions).length);
-            assertTrue(!!actions[ActionsModel.CommonActionId.SHARE]);
-            assertTrue(
-                !!actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE]);
-            assertTrue(!!actions[ActionsModel.InternalActionId
-                                     .REMOVE_FOLDER_SHORTCUT]);
-
-            // 'Create shortcut' should be disabled.
-            const createFolderShortcutAction =
-                actions[ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT];
-            assertTrue(!!createFolderShortcutAction);
-            // @ts-ignore: error TS18048: 'createFolderShortcutAction' is
-            // possibly 'undefined'.
-            assertFalse(createFolderShortcutAction.canExecute());
-            assertEquals(1, invalidated);
-          }),
-      callback);
-}
-
-/**
- * Tests that the correct actions are available for a Google Drive file.
- * @param {()=>void} callback
- */
-export function testDriveFileEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test.txt'] =
-      MockFileEntry.create(driveFileSystem, '/test.txt');
-
-  const metadataModel = new MockMetadataModel({
-    hosted: false,
-    pinned: false,
-    canPin: true,
-  });
-
-  let model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [driveFileSystem.entries['/test.txt']]);
-  let invalidated = 0;
-
-  return reportPromise(
-      model.initialize()
-          .then(() => {
-            const actions = model.getActions();
-            assertEquals(3, Object.keys(actions).length);
-            assertTrue(!!actions[ActionsModel.CommonActionId.SHARE]);
-
-            // 'Save for Offline' should be enabled.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertTrue(saveForOfflineAction.canExecute());
-
-            // 'Manage in Drive' should be enabled.
-            const manageInDriveAction =
-                actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-            assertTrue(!!manageInDriveAction);
-            // @ts-ignore: error TS18048: 'manageInDriveAction' is possibly
-            // 'undefined'.
-            assertTrue(manageInDriveAction.canExecute());
-
-            chrome.fileManagerPrivate.pinDriveFile = (entry, pin, callback) => {
-              // @ts-ignore: error TS2339: Property 'pinned' does not exist on
-              // type 'Object'.
-              metadataModel.properties.pinned = true;
-              // @ts-ignore: error TS2339: Property 'entries' does not exist on
-              // type 'FileSystem'.
-              assertEquals(driveFileSystem.entries['/test.txt'], entry);
-              assertTrue(pin);
-              callback();
-            };
-
-            // For pinning, invalidating is done asynchronously, so we need to
-            // wait for it with a promise.
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                invalidated++;
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-              // 'undefined'.
-              saveForOfflineAction.execute();
-            });
-          })
-          .then(() => {
-            // @ts-ignore: error TS2339: Property 'pinned' does not exist on
-            // type 'Object'.
-            assertTrue(metadataModel.properties.pinned);
-            assertEquals(1, invalidated);
-
-            assertEquals(1, countMetricCalls('FileBrowser.DrivePinSuccess'));
-            assertEquals(
-                0, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
-
-            // The model is invalidated, as list of actions have changed.
-            // Recreated the model and check that the actions are updated.
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                // @ts-ignore: error TS2339: Property 'entries' does not exist
-                // on type 'FileSystem'.
-                [driveFileSystem.entries['/test.txt']]);
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-            assertEquals(3, Object.keys(actions).length);
-            assertTrue(!!actions[ActionsModel.CommonActionId.SHARE]);
-
-            // 'Offline not Necessary' should be enabled.
-            const offlineNotNecessaryAction =
-                actions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY];
-            assertTrue(!!offlineNotNecessaryAction);
-            // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-            // possibly 'undefined'.
-            assertTrue(offlineNotNecessaryAction.canExecute());
-
-            // 'Manage in Drive' should be enabled.
-            const manageInDriveAction =
-                actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-            assertTrue(!!manageInDriveAction);
-            // @ts-ignore: error TS18048: 'manageInDriveAction' is possibly
-            // 'undefined'.
-            assertTrue(manageInDriveAction.canExecute());
-
-            chrome.fileManagerPrivate.pinDriveFile = (entry, pin, callback) => {
-              // @ts-ignore: error TS2339: Property 'pinned' does not exist on
-              // type 'Object'.
-              metadataModel.properties.pinned = false;
-              // @ts-ignore: error TS2339: Property 'entries' does not exist on
-              // type 'FileSystem'.
-              assertEquals(driveFileSystem.entries['/test.txt'], entry);
-              assertFalse(pin);
-              callback();
-            };
-
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                invalidated++;
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-              // possibly 'undefined'.
-              offlineNotNecessaryAction.execute();
-            });
-          })
-          .then(() => {
-            // @ts-ignore: error TS2339: Property 'pinned' does not exist on
-            // type 'Object'.
-            assertFalse(metadataModel.properties.pinned);
-            assertEquals(2, invalidated);
-          }),
-      callback);
-}
-
-/**
- * Tests that the correct actions are available for a Google Drive hosted file.
- * @param {()=>void} callback
- */
-export function testDriveHostedFileEntry(callback) {
-  const testDocument = MockFileEntry.create(driveFileSystem, '/test.gdoc');
-  const testFile = MockFileEntry.create(driveFileSystem, '/test.txt');
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test.gdoc'] = testDocument;
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test.txt'] = testFile;
-
-  const metadataModel = new MockMetadataModel({});
-  metadataModel.set(testDocument, {hosted: true, pinned: false, canPin: true});
-  metadataModel.set(testFile, {hosted: false, pinned: false, canPin: true});
-  volumeManager.driveConnectionState = {
-    type: chrome.fileManagerPrivate.DriveConnectionStateType.ONLINE,
-    // @ts-ignore: error TS2322: Type '{ type: string; hasCellularNetworkAccess:
-    // boolean; canPinHostedFiles: boolean; }' is not assignable to type
-    // 'DriveConnectionState'.
-    hasCellularNetworkAccess: false,
-    canPinHostedFiles: true,
-  };
-  chrome.fileManagerPrivate.pinDriveFile = (entry, pin, callback) => {
-    const metadata = metadataModel.getCache([entry])[0];
-    metadata.pinned = pin;
-    metadataModel.set(entry, metadata);
-    callback();
-  };
-
-  let model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui, [testDocument]);
-
-  return reportPromise(
-      model.initialize()
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Save for Offline' should be enabled.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertTrue(saveForOfflineAction.canExecute());
-
-            // Check the actions for multiple selection.
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                [testDocument, testFile]);
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Offline not Necessary' should not be enabled.
-            assertFalse(actions.hasOwnProperty(
-                ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY));
-
-            // 'Save for Offline' should be enabled.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertTrue(saveForOfflineAction.canExecute());
-
-            // For pinning, invalidating is done asynchronously, so we need to
-            // wait for it with a promise.
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-              // 'undefined'.
-              saveForOfflineAction.execute();
-            });
-          })
-          .then(() => {
-            assertTrue(!!metadataModel.getCache([testDocument])[0].pinned);
-            assertTrue(!!metadataModel.getCache([testFile])[0].pinned);
-
-            assertEquals(2, countMetricCalls('FileBrowser.DrivePinSuccess'));
-            assertEquals(
-                1, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
-
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                [testDocument, testFile]);
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Offline not Necessary' should be enabled.
-            const offlineNotNecessaryAction =
-                actions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY];
-            assertTrue(!!offlineNotNecessaryAction);
-            // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-            // possibly 'undefined'.
-            assertTrue(offlineNotNecessaryAction.canExecute());
-
-            // 'Save for Offline' should not be enabled.
-            assertFalse(actions.hasOwnProperty(
-                ActionsModel.CommonActionId.SAVE_FOR_OFFLINE));
-
-            // For pinning, invalidating is done asynchronously, so we need to
-            // wait for it with a promise.
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-              // possibly 'undefined'.
-              offlineNotNecessaryAction.execute();
-            });
-          })
-          .then(() => {
-            assertFalse(!!metadataModel.getCache([testDocument])[0].pinned);
-            assertFalse(!!metadataModel.getCache([testFile])[0].pinned);
-          }),
-      callback);
-}
-
-/**
- * Tests that the correct actions are available for a Drive file that cannot be
- * pinned.
- * @param {()=>void} callback
- */
-export function testUnpinnableDriveHostedFileEntry(callback) {
-  const testDocument = MockFileEntry.create(driveFileSystem, '/test.gdoc');
-  const testFile = MockFileEntry.create(driveFileSystem, '/test.txt');
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test.gdoc'] = testDocument;
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/test.txt'] = testFile;
-
-  const metadataModel = new MockMetadataModel({});
-  metadataModel.set(testDocument, {hosted: true, pinned: false, canPin: false});
-  metadataModel.set(testFile, {hosted: false, pinned: false, canPin: true});
-  volumeManager.driveConnectionState = {
-    type: chrome.fileManagerPrivate.DriveConnectionStateType.ONLINE,
-    // @ts-ignore: error TS2322: Type '{ type: string; hasCellularNetworkAccess:
-    // boolean; canPinHostedFiles: boolean; }' is not assignable to type
-    // 'DriveConnectionState'.
-    hasCellularNetworkAccess: false,
-    canPinHostedFiles: false,
-  };
-  chrome.fileManagerPrivate.pinDriveFile = (entry, pin, callback) => {
-    const metadata = metadataModel.getCache([entry])[0];
-    metadata.pinned = pin;
-    metadataModel.set(entry, metadata);
-    callback();
-  };
-
-  let model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui, [testDocument]);
-
-  return reportPromise(
-      model.initialize()
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Save for Offline' should be enabled, but not executable.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertFalse(saveForOfflineAction.canExecute());
-
-            // Check the actions for multiple selection.
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                [testDocument, testFile]);
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Offline not Necessary' should not be enabled.
-            assertFalse(actions.hasOwnProperty(
-                ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY));
-
-            // 'Save for Offline' should be enabled even though we can't pin
-            // hosted files as we've also selected a non-hosted file.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertTrue(saveForOfflineAction.canExecute());
-
-            // For pinning, invalidating is done asynchronously, so we need to
-            // wait for it with a promise.
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-              // 'undefined'.
-              saveForOfflineAction.execute();
-            });
-          })
-          .then(() => {
-            assertFalse(!!metadataModel.getCache([testDocument])[0].pinned);
-            assertTrue(!!metadataModel.getCache([testFile])[0].pinned);
-
-            assertEquals(1, countMetricCalls('FileBrowser.DrivePinSuccess'));
-            assertEquals(
-                0, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
-
-            model = new ActionsModel(
-                // @ts-ignore: error TS2345: Argument of type
-                // 'MockMetadataModel' is not assignable to parameter of type
-                // 'MetadataModel'.
-                volumeManager, metadataModel, shortcutsModel, ui,
-                [testDocument, testFile]);
-            return model.initialize();
-          })
-          .then(() => {
-            const actions = model.getActions();
-
-            // 'Offline not Necessary' should be enabled.
-            const offlineNotNecessaryAction =
-                actions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY];
-            assertTrue(!!offlineNotNecessaryAction);
-            // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-            // possibly 'undefined'.
-            assertTrue(offlineNotNecessaryAction.canExecute());
-
-            // 'Save for Offline' should be enabled, but not executable.
-            const saveForOfflineAction =
-                actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-            assertTrue(!!saveForOfflineAction);
-            // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-            // 'undefined'.
-            assertFalse(saveForOfflineAction.canExecute());
-
-            // For pinning, invalidating is done asynchronously, so we need to
-            // wait for it with a promise.
-            // @ts-ignore: error TS6133: 'reject' is declared but its value is
-            // never read.
-            return new Promise((fulfill, reject) => {
-              model.addEventListener('invalidated', () => {
-                // @ts-ignore: error TS2810: Expected 1 argument, but got 0.
-                // 'new Promise()' needs a JSDoc hint to produce a 'resolve'
-                // that can be called without arguments.
-                fulfill();
-              });
-              // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is
-              // possibly 'undefined'.
-              offlineNotNecessaryAction.execute();
-            });
-          })
-          .then(() => {
-            assertFalse(!!metadataModel.getCache([testDocument])[0].pinned);
-            assertFalse(!!metadataModel.getCache([testFile])[0].pinned);
-          }),
-      callback);
-}
-
-/**
- * Tests that a Team Drive Root entry has the correct actions available.
- * @param {()=>void} callback
- */
-export function testTeamDriveRootEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/team_drives/ABC Team'] =
-      MockDirectoryEntry.create(driveFileSystem, '/team_drives/ABC Team');
-
-  const metadataModel = new MockMetadataModel({
-    canShare: true,
-  });
-
-  const model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [driveFileSystem.entries['/team_drives/ABC Team']]);
-
-  return reportPromise(
-      model.initialize().then(() => {
-        const actions = model.getActions();
-        console.log(Object.keys(actions));
-        assertEquals(4, Object.keys(actions).length);
-
-        // "share" action is enabled for Team Drive Root entries.
-        const shareAction = actions[ActionsModel.CommonActionId.SHARE];
-        assertTrue(!!shareAction);
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        assertTrue(shareAction.canExecute());
-
-        // "manage in drive" action is disabled for Team Drive Root entries.
-        const manageAction =
-            actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-        assertTrue(!!manageAction);
-        // @ts-ignore: error TS18048: 'manageAction' is possibly 'undefined'.
-        assertTrue(manageAction.canExecute());
-      }),
-      callback);
-}
-
-/**
- * Tests that a Team Drive directory entry has the correct actions available.
- * @param {()=>void} callback
- */
-export function testTeamDriveDirectoryEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/team_drives/ABC Team/Folder 1'] =
-      MockDirectoryEntry.create(
-          driveFileSystem, '/team_drives/ABC Team/Folder 1');
-
-  const metadataModel = new MockMetadataModel({
-    canShare: true,
-    canPin: true,
-  });
-
-  const model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [driveFileSystem.entries['/team_drives/ABC Team/Folder 1']]);
-
-  return reportPromise(
-      model.initialize().then(() => {
-        const actions = model.getActions();
-        assertEquals(5, Object.keys(actions).length);
-
-        // "Share" is enabled for Team Drive directories.
-        const shareAction = actions[ActionsModel.CommonActionId.SHARE];
-        assertTrue(!!shareAction);
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        assertTrue(shareAction.canExecute());
-
-        // "Available Offline" toggle is enabled for Team Drive directories.
-        const saveForOfflineAction =
-            actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-        assertTrue(!!saveForOfflineAction);
-        // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-        // 'undefined'.
-        assertTrue(saveForOfflineAction.canExecute());
-
-        // "Available Offline" toggle is enabled for Team Drive directories.
-        const offlineNotNecessaryAction =
-            actions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY];
-        assertTrue(!!offlineNotNecessaryAction);
-        // @ts-ignore: error TS18048: 'offlineNotNecessaryAction' is possibly
-        // 'undefined'.
-        assertTrue(offlineNotNecessaryAction.canExecute());
-
-        // "Manage in drive" is enabled for Team Drive directories.
-        const manageAction =
-            actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-        assertTrue(!!manageAction);
-        // @ts-ignore: error TS18048: 'manageAction' is possibly 'undefined'.
-        assertTrue(manageAction.canExecute());
-
-        // 'Create shortcut' should be enabled.
-        const createFolderShortcutAction =
-            actions[ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT];
-        assertTrue(!!createFolderShortcutAction);
-        // @ts-ignore: error TS18048: 'createFolderShortcutAction' is possibly
-        // 'undefined'.
-        assertTrue(createFolderShortcutAction.canExecute());
-      }),
-      callback);
-}
-
-/**
- * Tests that a Team Drive file entry has the correct actions available.
- * @param {()=>void} callback
- */
-export function testTeamDriveFileEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  driveFileSystem.entries['/team_drives/ABC Team/Folder 1/test.txt'] =
-      MockFileEntry.create(
-          driveFileSystem, '/team_drives/ABC Team/Folder 1/test.txt');
-
-  const metadataModel = new MockMetadataModel({
-    hosted: false,
-    pinned: false,
-    canPin: true,
-  });
-
-  const model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [driveFileSystem.entries['/team_drives/ABC Team/Folder 1/test.txt']]);
-
-  return reportPromise(
-      model.initialize().then(() => {
-        const actions = model.getActions();
-        assertEquals(3, Object.keys(actions).length);
-
-        // "save for offline" action is enabled for Team Drive file entries.
-        const saveForOfflineAction =
-            actions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
-        assertTrue(!!saveForOfflineAction);
-        // @ts-ignore: error TS18048: 'saveForOfflineAction' is possibly
-        // 'undefined'.
-        assertTrue(saveForOfflineAction.canExecute());
-
-        // "share" action is enabled for Team Drive file entries.
-        const shareAction = actions[ActionsModel.CommonActionId.SHARE];
-        assertTrue(!!shareAction);
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        assertTrue(shareAction.canExecute());
-
-        // "manage in drive" action is enabled for Team Drive file entries.
-        const manageAction =
-            actions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
-        assertTrue(!!manageAction);
-        // @ts-ignore: error TS18048: 'manageAction' is possibly 'undefined'.
-        assertTrue(manageAction.canExecute());
-      }),
-      callback);
-}
-
-/**
- * Tests that if actions are provided with getCustomActions(), they appear
- * correctly for the file.
- * @param {()=>void} callback
- */
-export function testProvidedEntry(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  providedFileSystem.entries['/test'] =
-      MockDirectoryEntry.create(providedFileSystem, '/test');
-
-  chrome.fileManagerPrivate.getCustomActions = (entries, callback) => {
-    assertEquals(1, entries.length);
-    // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-    // 'FileSystem'.
-    assertEquals(providedFileSystem.entries['/test'], entries[0]);
-    callback([
-      {
-        id: ActionsModel.CommonActionId.SHARE,
-        title: 'Share it!',
-      },
-      {
-        id: 'some-custom-id',
-        title: 'Turn into chocolate!',
-      },
-    ]);
-  };
-
-  // @ts-ignore: error TS2345: Argument of type 'null' is not assignable to
-  // parameter of type 'Object'.
-  const metadataModel = new MockMetadataModel(null);
-
-  const model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [providedFileSystem.entries['/test']]);
-
-  let invalidated = 0;
-  model.addEventListener('invalidated', () => {
-    invalidated++;
-  });
-
-  return reportPromise(
-      model.initialize().then(() => {
-        const actions = model.getActions();
-        assertEquals(2, Object.keys(actions).length);
-
-        const shareAction = actions[ActionsModel.CommonActionId.SHARE];
-        assertTrue(!!shareAction);
-        // Sharing on FSP is possible even if Drive is offline. Custom actions
-        // are always executable, as we don't know the actions implementation.
-        volumeManager.driveConnectionState = {
-          type: chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE,
-          // @ts-ignore: error TS2322: Type '{ type: string;
-          // hasCellularNetworkAccess: boolean; canPinHostedFiles: boolean; }'
-          // is not assignable to type 'DriveConnectionState'.
-          hasCellularNetworkAccess: false,
-          canPinHostedFiles: false,
-        };
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        assertTrue(shareAction.canExecute());
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        assertEquals('Share it!', shareAction.getTitle());
-
-        chrome.fileManagerPrivate.executeCustomAction =
-            (entries, actionId, callback) => {
-              assertEquals(1, entries.length);
-              // @ts-ignore: error TS2339: Property 'entries' does not exist on
-              // type 'FileSystem'.
-              assertEquals(providedFileSystem.entries['/test'], entries[0]);
-              assertEquals(ActionsModel.CommonActionId.SHARE, actionId);
-              callback();
-            };
-        // @ts-ignore: error TS18048: 'shareAction' is possibly 'undefined'.
-        shareAction.execute();
-        assertEquals(1, invalidated);
-
-        assertTrue(!!actions['some-custom-id']);
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        assertTrue(actions['some-custom-id'].canExecute());
-        assertEquals(
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-            'Turn into chocolate!', actions['some-custom-id'].getTitle());
-
-        chrome.fileManagerPrivate.executeCustomAction =
-            (entries, actionId, callback) => {
-              assertEquals(1, entries.length);
-              // @ts-ignore: error TS2339: Property 'entries' does not exist on
-              // type 'FileSystem'.
-              assertEquals(providedFileSystem.entries['/test'], entries[0]);
-              assertEquals('some-custom-id', actionId);
-              callback();
-            };
-
-        // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-        actions['some-custom-id'].execute();
-        assertEquals(2, invalidated);
-      }),
-      callback);
-}
-
-/**
- * Tests that no actions are available when getCustomActions() throws an error.
- * @param {()=>void} callback
- */
-export function testProvidedEntryWithError(callback) {
-  // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-  // 'FileSystem'.
-  providedFileSystem.entries['/test'] =
-      MockDirectoryEntry.create(providedFileSystem, '/test');
-
-  // @ts-ignore: error TS6133: 'entries' is declared but its value is never
-  // read.
-  chrome.fileManagerPrivate.getCustomActions = (entries, callback) => {
-    // @ts-ignore: error TS2339: Property 'runtime' does not exist on type
-    // 'typeof chrome'.
-    chrome.runtime.lastError = {
-      message: 'Failed to fetch custom actions.',
-    };
-    // @ts-ignore: error TS2322: Type 'string' is not assignable to type
-    // 'FileSystemProviderAction'.
-    callback(['error']);
-  };
-
-  // @ts-ignore: error TS2345: Argument of type 'null' is not assignable to
-  // parameter of type 'Object'.
-  const metadataModel = new MockMetadataModel(null);
-
-  const model = new ActionsModel(
-      // @ts-ignore: error TS2345: Argument of type 'MockMetadataModel' is not
-      // assignable to parameter of type 'MetadataModel'.
-      volumeManager, metadataModel, shortcutsModel, ui,
-      // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-      // 'FileSystem'.
-      [providedFileSystem.entries['/test']]);
-
-  return reportPromise(
-      model.initialize().then(() => {
-        const actions = model.getActions();
-        assertEquals(0, Object.keys(actions).length);
-      }),
-      callback);
-}
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.ts b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.ts
new file mode 100644
index 0000000..d514cbd
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.ts
@@ -0,0 +1,704 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
+import {assert} from 'chrome://resources/js/assert.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+
+import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
+import {installMockChrome, MockCommandLinePrivate, MockMetrics} from '../../common/js/mock_chrome.js';
+import {MockDirectoryEntry, MockFileEntry} from '../../common/js/mock_entry.js';
+import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
+import type {VolumeManager} from '../../externs/volume_manager.js';
+
+import {ActionsModel, CommonActionId, InternalActionId} from './actions_model.js';
+import {FolderShortcutsDataModel} from './folder_shortcuts_data_model.js';
+import {MetadataModel} from './metadata/metadata_model.js';
+import {MockMetadataModel} from './metadata/mock_metadata.js';
+import {ActionModelUI} from './ui/action_model_ui.js';
+import {FilesAlertDialog} from './ui/files_alert_dialog.js';
+import {ListContainer} from './ui/list_container.js';
+
+type GetCustomActionsCallback =
+    (actions: chrome.fileManagerPrivate.FileSystemProviderAction[]) => void;
+
+let mockVolumeManager: MockVolumeManager;
+let driveFileSystem: FileSystem&
+    {entries?: Record<string, DirectoryEntry|FileEntry>};
+let providedFileSystem: FileSystem&{entries?: Record<string, DirectoryEntry>};
+let mockMetrics: MockMetrics;
+let shortcutsModel: FolderShortcutsDataModel;
+
+/**
+ * @return total number of calls for that metric.
+ */
+function countMetricCalls(metricName: string): number {
+  const calls = mockMetrics.metricCalls;
+  return (calls[metricName] || []).length;
+}
+
+function createFakeFolderShortcutsDataModel(): FolderShortcutsDataModel {
+  class FakeFolderShortcutsModel extends EventTarget {
+    private has_ = false;
+
+    constructor() {
+      super();
+    }
+
+    exists() {
+      return this.has_;
+    }
+
+    add() {
+      this.has_ = true;
+      return 0;
+    }
+
+    remove() {
+      this.has_ = false;
+      return 0;
+    }
+  }
+
+  const model = new FakeFolderShortcutsModel();
+  return model as unknown as FolderShortcutsDataModel;
+}
+
+class MockUi implements ActionModelUI {
+  listContainer: ListContainer;
+  alertDialog: FilesAlertDialog;
+
+  constructor() {
+    this.listContainer = {
+      currentView: {
+        updateListItemsMetadata: function() {},
+      },
+    } as unknown as ListContainer;
+
+    this.alertDialog = {
+      showHtml: () => {},
+    } as unknown as FilesAlertDialog;
+  }
+}
+
+let ui: MockUi;
+
+function getVolumeManager(): VolumeManager {
+  return mockVolumeManager as unknown as VolumeManager;
+}
+
+function asMetadataModel(metadataModel: MockMetadataModel): MetadataModel {
+  return metadataModel as unknown as MetadataModel;
+}
+
+export function setUp() {
+  mockMetrics = new MockMetrics();
+  // Mock Chrome APIs.
+  const mockChrome = {
+    metricsPrivate: mockMetrics,
+    runtime: {
+      lastError: null,
+    },
+  };
+  installMockChrome(mockChrome);
+  new MockCommandLinePrivate();
+
+  // Setup Drive file system.
+  mockVolumeManager = new MockVolumeManager();
+  let type = VolumeManagerCommon.VolumeType.DRIVE;
+  assert(mockVolumeManager.getCurrentProfileVolumeInfo(type)!.fileSystem);
+  driveFileSystem =
+      mockVolumeManager.getCurrentProfileVolumeInfo(type)!.fileSystem;
+
+  // Setup Provided file system.
+  type = VolumeManagerCommon.VolumeType.PROVIDED;
+  mockVolumeManager.createVolumeInfo(type, 'provided', 'Provided');
+  assert(mockVolumeManager.getCurrentProfileVolumeInfo(type)!.fileSystem);
+  providedFileSystem =
+      mockVolumeManager.getCurrentProfileVolumeInfo(type)!.fileSystem;
+
+  // Create mock action model components.
+  shortcutsModel = createFakeFolderShortcutsDataModel();
+  ui = new MockUi();
+}
+
+/**
+ * Tests that the correct actions are available for a Google Drive directory.
+ */
+export async function testDriveDirectoryEntry() {
+  driveFileSystem.entries!['/test'] =
+      MockDirectoryEntry.create(driveFileSystem, '/test');
+
+  const mockMetadataModel = new MockMetadataModel({
+    canShare: true,
+  });
+
+  let model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/test']]);
+
+  let invalidated = 0;
+  model.addEventListener('invalidated', () => {
+    invalidated++;
+  });
+
+  await model.initialize();
+  let actions = model.getActions();
+  assertEquals(5, Object.keys(actions).length);
+
+  // 'Share' should be disabled in offline mode.
+  const shareAction = actions[CommonActionId.SHARE]!;
+  assertTrue(!!shareAction);
+  mockVolumeManager.driveConnectionState = {
+    type: chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE,
+  };
+  assertFalse(shareAction.canExecute());
+
+  // 'Manage in Drive' should be disabled in offline mode.
+  const manageInDriveAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageInDriveAction);
+  assertFalse(manageInDriveAction.canExecute());
+
+  // 'Create Shortcut' should be enabled, until it's executed, then
+  // disabled.
+  let createFolderShortcutAction =
+      actions[InternalActionId.CREATE_FOLDER_SHORTCUT]!;
+  assertTrue(!!createFolderShortcutAction);
+  assertTrue(createFolderShortcutAction.canExecute());
+  createFolderShortcutAction.execute();
+  assertFalse(createFolderShortcutAction.canExecute());
+  assertEquals(1, invalidated);
+
+  // The model is invalidated, as list of actions have changed.
+  // Recreated the model and check that the actions are updated.
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/test']]);
+  model.addEventListener('invalidated', () => {
+    invalidated++;
+  });
+  await model.initialize();
+  actions = model.getActions();
+  assertEquals(6, Object.keys(actions).length);
+  assertTrue(!!actions[CommonActionId.SHARE]);
+  assertTrue(!!actions[InternalActionId.MANAGE_IN_DRIVE]);
+  assertTrue(!!actions[InternalActionId.REMOVE_FOLDER_SHORTCUT]);
+
+  // 'Create shortcut' should be disabled.
+  createFolderShortcutAction =
+      actions[InternalActionId.CREATE_FOLDER_SHORTCUT]!;
+  assertTrue(!!createFolderShortcutAction);
+  assertFalse(createFolderShortcutAction.canExecute());
+  assertEquals(1, invalidated);
+}
+
+/**
+ * Tests that the correct actions are available for a Google Drive file.
+ */
+export async function testDriveFileEntry() {
+  driveFileSystem.entries!['/test.txt'] =
+      MockFileEntry.create(driveFileSystem, '/test.txt');
+
+  const mockMetadataModel = new MockMetadataModel({
+    hosted: false,
+    pinned: false,
+    canPin: true,
+  });
+
+  let model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/test.txt']]);
+  let invalidated = 0;
+
+  await model.initialize();
+  let actions = model.getActions();
+  assertEquals(3, Object.keys(actions).length);
+  assertTrue(!!actions[CommonActionId.SHARE]);
+
+  // 'Save for Offline' should be enabled.
+  const saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // 'Manage in Drive' should be enabled.
+  let manageInDriveAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageInDriveAction);
+  assertTrue(manageInDriveAction.canExecute());
+
+  chrome.fileManagerPrivate.pinDriveFile =
+      (entry: Entry, pin: boolean, callback: VoidCallback) => {
+        mockMetadataModel.properties['pinned'] = true;
+        assertEquals(driveFileSystem.entries!['/test.txt'], entry);
+        assertTrue(pin);
+        callback();
+      };
+
+  // For pinning, invalidating is done asynchronously, so we need to
+  // wait for it with a promise.
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      invalidated++;
+      resolve();
+    });
+    saveForOfflineAction.execute();
+  });
+  assertTrue(mockMetadataModel.properties['pinned']);
+  assertEquals(1, invalidated);
+
+  assertEquals(1, countMetricCalls('FileBrowser.DrivePinSuccess'));
+  assertEquals(0, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
+
+  // The model is invalidated, as list of actions have changed.
+  // Recreated the model and check that the actions are updated.
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/test.txt']]);
+  await model.initialize();
+  actions = model.getActions();
+  assertEquals(3, Object.keys(actions).length);
+  assertTrue(!!actions[CommonActionId.SHARE]);
+
+  // 'Offline not Necessary' should be enabled.
+  const offlineNotNecessaryAction =
+      actions[CommonActionId.OFFLINE_NOT_NECESSARY]!;
+  assertTrue(!!offlineNotNecessaryAction);
+  assertTrue(offlineNotNecessaryAction.canExecute());
+
+  // 'Manage in Drive' should be enabled.
+  manageInDriveAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageInDriveAction);
+  assertTrue(manageInDriveAction.canExecute());
+
+  chrome.fileManagerPrivate.pinDriveFile =
+      (entry: Entry, pin: boolean, callback: VoidCallback) => {
+        mockMetadataModel.properties['pinned'] = false;
+        assertEquals(driveFileSystem.entries!['/test.txt'], entry);
+        assertFalse(pin);
+        callback();
+      };
+
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      invalidated++;
+      resolve();
+    });
+    offlineNotNecessaryAction.execute();
+  });
+  assertFalse(mockMetadataModel.properties['pinned']);
+  assertEquals(2, invalidated);
+}
+
+/**
+ * Tests that the correct actions are available for a Google Drive hosted file.
+ */
+export async function testDriveHostedFileEntry() {
+  const testDocument = MockFileEntry.create(driveFileSystem, '/test.gdoc');
+  const testFile = MockFileEntry.create(driveFileSystem, '/test.txt');
+  driveFileSystem.entries!['/test.gdoc'] = testDocument;
+  driveFileSystem.entries!['/test.txt'] = testFile;
+
+  const mockMetadataModel = new MockMetadataModel({});
+  mockMetadataModel.set(
+      testDocument, {hosted: true, pinned: false, canPin: true});
+  mockMetadataModel.set(testFile, {hosted: false, pinned: false, canPin: true});
+  mockVolumeManager.driveConnectionState = {
+    type: chrome.fileManagerPrivate.DriveConnectionStateType.ONLINE,
+  };
+  chrome.fileManagerPrivate.pinDriveFile =
+      (entry: Entry, pin: boolean, callback: VoidCallback) => {
+        const metadata = mockMetadataModel.getCache([entry])[0];
+        metadata['pinned'] = pin;
+        mockMetadataModel.set(entry, metadata);
+        callback();
+      };
+
+  let model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument]);
+
+  await model.initialize();
+  let actions = model.getActions();
+
+  // 'Save for Offline' should be enabled.
+  let saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // Check the actions for multiple selection.
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument, testFile]);
+  await model.initialize();
+  actions = model.getActions();
+
+  // 'Offline not Necessary' should not be enabled.
+  assertFalse(actions.hasOwnProperty(CommonActionId.OFFLINE_NOT_NECESSARY));
+
+  // 'Save for Offline' should be enabled.
+  saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // For pinning, invalidating is done asynchronously, so we need to
+  // wait for it with a promise.
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      resolve();
+    });
+    saveForOfflineAction.execute();
+  });
+
+  assertTrue(!!mockMetadataModel.getCache([testDocument])[0]['pinned']);
+  assertTrue(!!mockMetadataModel.getCache([testFile])[0]['pinned']);
+
+  assertEquals(2, countMetricCalls('FileBrowser.DrivePinSuccess'));
+  assertEquals(1, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
+
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument, testFile]);
+  await model.initialize();
+
+  actions = model.getActions();
+
+  // 'Offline not Necessary' should be enabled.
+  const offlineNotNecessaryAction =
+      actions[CommonActionId.OFFLINE_NOT_NECESSARY]!;
+  assertTrue(!!offlineNotNecessaryAction);
+  assertTrue(offlineNotNecessaryAction.canExecute());
+
+  // 'Save for Offline' should not be enabled.
+  assertFalse(actions.hasOwnProperty(CommonActionId.SAVE_FOR_OFFLINE));
+
+  // For pinning, invalidating is done asynchronously, so we need to
+  // wait for it with a promise.
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      resolve();
+    });
+    offlineNotNecessaryAction.execute();
+  });
+
+  assertFalse(!!mockMetadataModel.getCache([testDocument])[0]['pinned']);
+  assertFalse(!!mockMetadataModel.getCache([testFile])[0]['pinned']);
+}
+
+/**
+ * Tests that the correct actions are available for a Drive file that cannot be
+ * pinned.
+ */
+export async function testUnpinnableDriveHostedFileEntry() {
+  const testDocument = MockFileEntry.create(driveFileSystem, '/test.gdoc');
+  const testFile = MockFileEntry.create(driveFileSystem, '/test.txt');
+  driveFileSystem.entries!['/test.gdoc'] = testDocument;
+  driveFileSystem.entries!['/test.txt'] = testFile;
+
+  const mockMetadataModel = new MockMetadataModel({});
+  mockMetadataModel.set(
+      testDocument, {hosted: true, pinned: false, canPin: false});
+  mockMetadataModel.set(testFile, {hosted: false, pinned: false, canPin: true});
+  mockVolumeManager.driveConnectionState = {
+    type: chrome.fileManagerPrivate.DriveConnectionStateType.ONLINE,
+  };
+  chrome.fileManagerPrivate.pinDriveFile =
+      (entry: Entry, pin: boolean, callback: VoidCallback) => {
+        const metadata = mockMetadataModel.getCache([entry])[0];
+        metadata['pinned'] = pin;
+        mockMetadataModel.set(entry, metadata);
+        callback();
+      };
+
+  let model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument]);
+
+  await model.initialize();
+  let actions = model.getActions();
+
+  // 'Save for Offline' should be enabled, but not executable.
+  let saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertFalse(saveForOfflineAction.canExecute());
+
+  // Check the actions for multiple selection.
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument, testFile]);
+  await model.initialize();
+
+  actions = model.getActions();
+
+  // 'Offline not Necessary' should not be enabled.
+  assertFalse(actions.hasOwnProperty(CommonActionId.OFFLINE_NOT_NECESSARY));
+
+  // 'Save for Offline' should be enabled even though we can't pin
+  // hosted files as we've also selected a non-hosted file.
+  saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // For pinning, invalidating is done asynchronously, so we need to
+  // wait for it with a promise.
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      resolve();
+    });
+    saveForOfflineAction.execute();
+  });
+
+  assertFalse(!!mockMetadataModel.getCache([testDocument])[0]['pinned']);
+  assertTrue(!!mockMetadataModel.getCache([testFile])[0]['pinned']);
+
+  assertEquals(1, countMetricCalls('FileBrowser.DrivePinSuccess'));
+  assertEquals(0, countMetricCalls('FileBrowser.DriveHostedFilePinSuccess'));
+
+  model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [testDocument, testFile]);
+  await model.initialize();
+
+  actions = model.getActions();
+
+  // 'Offline not Necessary' should be enabled.
+  const offlineNotNecessaryAction =
+      actions[CommonActionId.OFFLINE_NOT_NECESSARY]!;
+  assertTrue(!!offlineNotNecessaryAction);
+  assertTrue(offlineNotNecessaryAction.canExecute());
+
+  // 'Save for Offline' should be enabled, but not executable.
+  saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertFalse(saveForOfflineAction.canExecute());
+
+  // For pinning, invalidating is done asynchronously, so we need to
+  // wait for it with a promise.
+  await new Promise<void>(resolve => {
+    model.addEventListener('invalidated', () => {
+      resolve();
+    });
+    offlineNotNecessaryAction.execute();
+  });
+
+  assertFalse(!!mockMetadataModel.getCache([testDocument])[0]['pinned']);
+  assertFalse(!!mockMetadataModel.getCache([testFile])[0]['pinned']);
+}
+
+/**
+ * Tests that a Team Drive Root entry has the correct actions available.
+ */
+export async function testTeamDriveRootEntry() {
+  driveFileSystem.entries!['/team_drives/ABC Team'] =
+      MockDirectoryEntry.create(driveFileSystem, '/team_drives/ABC Team');
+
+  const mockMetadataModel = new MockMetadataModel({
+    canShare: true,
+  });
+
+  const model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/team_drives/ABC Team']]);
+
+  await model.initialize();
+  const actions = model.getActions();
+  assertEquals(4, Object.keys(actions).length);
+
+  // "share" action is enabled for Team Drive Root entries.
+  const shareAction = actions[CommonActionId.SHARE]!;
+  assertTrue(!!shareAction);
+  assertTrue(shareAction.canExecute());
+
+  // "manage in drive" action is disabled for Team Drive Root entries.
+  const manageAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageAction);
+  assertTrue(manageAction.canExecute());
+}
+
+/**
+ * Tests that a Team Drive directory entry has the correct actions available.
+ */
+export async function testTeamDriveDirectoryEntry() {
+  driveFileSystem.entries!['/team_drives/ABC Team/Folder 1'] =
+      MockDirectoryEntry.create(
+          driveFileSystem, '/team_drives/ABC Team/Folder 1');
+
+  const mockMetadataModel = new MockMetadataModel({
+    canShare: true,
+    canPin: true,
+  });
+
+  const model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [driveFileSystem.entries!['/team_drives/ABC Team/Folder 1']]);
+
+  await model.initialize();
+  const actions = model.getActions();
+  assertEquals(5, Object.keys(actions).length);
+
+  // "Share" is enabled for Team Drive directories.
+  const shareAction = actions[CommonActionId.SHARE]!;
+  assertTrue(!!shareAction);
+  assertTrue(shareAction.canExecute());
+
+  // "Available Offline" toggle is enabled for Team Drive directories.
+  const saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // "Available Offline" toggle is enabled for Team Drive directories.
+  const offlineNotNecessaryAction =
+      actions[CommonActionId.OFFLINE_NOT_NECESSARY]!;
+  assertTrue(!!offlineNotNecessaryAction);
+  assertTrue(offlineNotNecessaryAction.canExecute());
+
+  // "Manage in drive" is enabled for Team Drive directories.
+  const manageAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageAction);
+  assertTrue(manageAction.canExecute());
+
+  // 'Create shortcut' should be enabled.
+  const createFolderShortcutAction =
+      actions[InternalActionId.CREATE_FOLDER_SHORTCUT]!;
+  assertTrue(!!createFolderShortcutAction);
+  assertTrue(createFolderShortcutAction.canExecute());
+}
+
+/**
+ * Tests that a Team Drive file entry has the correct actions available.
+ */
+export async function testTeamDriveFileEntry() {
+  driveFileSystem.entries!['/team_drives/ABC Team/Folder 1/test.txt'] =
+      MockFileEntry.create(
+          driveFileSystem, '/team_drives/ABC Team/Folder 1/test.txt');
+
+  const mockMetadataModel = new MockMetadataModel({
+    hosted: false,
+    pinned: false,
+    canPin: true,
+  });
+
+  const model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui,
+      [driveFileSystem.entries!['/team_drives/ABC Team/Folder 1/test.txt']]);
+
+  await model.initialize();
+  const actions = model.getActions();
+  assertEquals(3, Object.keys(actions).length);
+
+  // "save for offline" action is enabled for Team Drive file entries.
+  const saveForOfflineAction = actions[CommonActionId.SAVE_FOR_OFFLINE]!;
+  assertTrue(!!saveForOfflineAction);
+  assertTrue(saveForOfflineAction.canExecute());
+
+  // "share" action is enabled for Team Drive file entries.
+  const shareAction = actions[CommonActionId.SHARE]!;
+  assertTrue(!!shareAction);
+  assertTrue(shareAction.canExecute());
+
+  // "manage in drive" action is enabled for Team Drive file entries.
+  const manageAction = actions[InternalActionId.MANAGE_IN_DRIVE]!;
+  assertTrue(!!manageAction);
+  assertTrue(manageAction.canExecute());
+}
+
+/**
+ * Tests that if actions are provided with getCustomActions(), they appear
+ * correctly for the file.
+ */
+export async function testProvidedEntry() {
+  providedFileSystem.entries!['/test'] =
+      MockDirectoryEntry.create(providedFileSystem, '/test');
+
+  chrome.fileManagerPrivate.getCustomActions =
+      (entries: Entry[], callback: GetCustomActionsCallback) => {
+        assertEquals(1, entries.length);
+        assertEquals(providedFileSystem.entries!['/test'], entries[0]);
+        callback([
+          {
+            id: CommonActionId.SHARE,
+            title: 'Share it!',
+          },
+          {
+            id: 'some-custom-id',
+            title: 'Turn into chocolate!',
+          },
+        ]);
+      };
+
+  const mockMetadataModel = new MockMetadataModel({});
+
+  const model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [providedFileSystem.entries!['/test']]);
+
+  let invalidated = 0;
+  model.addEventListener('invalidated', () => {
+    invalidated++;
+  });
+
+  await model.initialize();
+  const actions = model.getActions();
+  assertEquals(2, Object.keys(actions).length);
+
+  const shareAction = actions[CommonActionId.SHARE]!;
+  assertTrue(!!shareAction);
+  // Sharing on FSP is possible even if Drive is offline. Custom actions
+  // are always executable, as we don't know the actions implementation.
+  mockVolumeManager.driveConnectionState = {
+    type: chrome.fileManagerPrivate.DriveConnectionStateType.OFFLINE,
+  };
+  assertTrue(shareAction.canExecute());
+  assertEquals('Share it!', shareAction.getTitle());
+
+  chrome.fileManagerPrivate.executeCustomAction =
+      (entries: Entry[], actionId: string, callback: VoidCallback) => {
+        assertEquals(1, entries.length);
+        assertEquals(providedFileSystem.entries!['/test'], entries[0]);
+        assertEquals(CommonActionId.SHARE, actionId);
+        callback();
+      };
+  shareAction.execute();
+  assertEquals(1, invalidated);
+
+  assertTrue(!!actions['some-custom-id']);
+  assertTrue(actions['some-custom-id']!.canExecute());
+  assertEquals('Turn into chocolate!', actions['some-custom-id']!.getTitle());
+
+  chrome.fileManagerPrivate.executeCustomAction =
+      (entries: Entry[], actionId: string, callback: VoidCallback) => {
+        assertEquals(1, entries.length);
+        assertEquals(providedFileSystem.entries!['/test'], entries[0]);
+        assertEquals('some-custom-id', actionId);
+        callback();
+      };
+
+  actions['some-custom-id']!.execute();
+  assertEquals(2, invalidated);
+}
+
+/**
+ * Tests that no actions are available when getCustomActions() throws an error.
+ */
+export async function testProvidedEntryWithError() {
+  providedFileSystem.entries!['/test'] =
+      MockDirectoryEntry.create(providedFileSystem, '/test');
+
+  chrome.fileManagerPrivate.getCustomActions =
+      (_entries: Entry[], callback: GetCustomActionsCallback) => {
+        chrome.runtime.lastError = {
+          message: 'Failed to fetch custom actions.',
+        };
+        callback([]);
+      };
+
+  const mockMetadataModel = new MockMetadataModel({});
+
+  const model = new ActionsModel(
+      getVolumeManager(), asMetadataModel(mockMetadataModel), shortcutsModel,
+      ui, [providedFileSystem.entries!['/test']]);
+
+  await model.initialize();
+  const actions = model.getActions();
+  assertEquals(0, Object.keys(actions).length);
+}
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index a438c3d..464fffd 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -40,7 +40,7 @@
 import {CommandHandlerDeps} from '../../externs/command_handler_deps.js';
 import {FakeEntry, FilesAppDirEntry} from '../../externs/files_app_entry_interfaces.js';
 import {ForegroundWindow} from '../../externs/foreground_window.js';
-import {DialogType, PropStatus} from '../../externs/ts/state.js';
+import {DialogType, PropStatus, SearchLocation} from '../../externs/ts/state.js';
 import {Store} from '../../externs/ts/store.js';
 import {getMyFiles} from '../../state/ducks/all_entries.js';
 import {updateBulkPinProgress} from '../../state/ducks/bulk_pinning.js';
@@ -1648,11 +1648,13 @@
     const searchQuery = this.launchParams_.searchQuery;
     if (searchQuery) {
       startInterval('Load.ProcessInitialSearchQuery');
-      this.store_.dispatch(updateSearch({
-        query: searchQuery,
-        status: PropStatus.STARTED,
-        options: getDefaultSearchOptions(),
-      }));
+      if (!isNewDirectoryTreeEnabled()) {
+        this.store_.dispatch(updateSearch({
+          query: searchQuery,
+          status: PropStatus.STARTED,
+          options: getDefaultSearchOptions(),
+        }));
+      }
       // Show a spinner, as the crossover search function call could be slow.
       // @ts-ignore: error TS2531: Object is possibly 'null'.
       const hideSpinnerCallback = this.spinnerController_.show();
@@ -1847,11 +1849,19 @@
           // @ts-ignore: error TS2531: Object is possibly 'null'.
           this.directoryModel_.selectEntry(opt_selectionEntry);
         }
-        // @ts-ignore: error TS2531: Object is possibly 'null'.
-        if (this.launchParams_.searchQuery) {
-          this.store_.dispatch(
-              // @ts-ignore: error TS2531: Object is possibly 'null'.
-              updateSearch({query: this.launchParams_.searchQuery}));
+        if (this.launchParams_?.searchQuery) {
+          const searchState = this.store_.getState().search;
+          this.store_.dispatch(updateSearch({
+            query: this.launchParams_.searchQuery,
+            status: undefined,
+            // Make sure the current directory can be highlighted in the
+            // directory tree.
+            options: {
+              ...getDefaultSearchOptions(),
+              ...searchState?.options,
+              location: SearchLocation.THIS_FOLDER,
+            },
+          }));
         }
       } else {
         console.warn('No entry for finishSetupCurrentDirectory_');
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
index 7770a82..e24f635 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -27,7 +27,7 @@
 import {getFileData, getStore} from '../../state/store.js';
 import {XfTreeItem} from '../../widgets/xf_tree_item.js';
 
-import {ActionsModel} from './actions_model.js';
+import {CommonActionId, InternalActionId} from './actions_model.js';
 import {constants} from './constants.js';
 import {DirectoryModel} from './directory_model.js';
 import {FileSelection, FileSelectionHandler} from './file_selection.js';
@@ -2879,10 +2879,10 @@
           if (!actionsModel) {
             return;
           }
-          const saveForOfflineAction = actionsModel.getAction(
-              ActionsModel.CommonActionId.SAVE_FOR_OFFLINE);
-          const offlineNotNeededAction = actionsModel.getAction(
-              ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY);
+          const saveForOfflineAction =
+              actionsModel.getAction(CommonActionId.SAVE_FOR_OFFLINE);
+          const offlineNotNeededAction =
+              actionsModel.getAction(CommonActionId.OFFLINE_NOT_NECESSARY);
           // Saving for offline has a priority if both actions are available.
           let action = offlineNotNeededAction;
           if (saveForOfflineAction && saveForOfflineAction.canExecute()) {
@@ -2931,9 +2931,9 @@
         return;
       }
       const saveForOfflineAction =
-          actionsModel.getAction(ActionsModel.CommonActionId.SAVE_FOR_OFFLINE);
-      const offlineNotNeededAction = actionsModel.getAction(
-          ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY);
+          actionsModel.getAction(CommonActionId.SAVE_FOR_OFFLINE);
+      const offlineNotNeededAction =
+          actionsModel.getAction(CommonActionId.OFFLINE_NOT_NECESSARY);
       let action = offlineNotNeededAction;
       command.checked = !!offlineNotNeededAction;
       if (saveForOfflineAction && saveForOfflineAction.canExecute()) {
@@ -3110,8 +3110,7 @@
           if (!actionsModel) {
             return;
           }
-          const action =
-              actionsModel.getAction(ActionsModel.CommonActionId.SHARE);
+          const action = actionsModel.getAction(CommonActionId.SHARE);
           if (action) {
             actionsController.executeAction(action);
           }
@@ -3140,7 +3139,7 @@
       if (!actionsModel) {
         return;
       }
-      const action = actionsModel.getAction(ActionsModel.CommonActionId.SHARE);
+      const action = actionsModel.getAction(CommonActionId.SHARE);
       event.canExecute = action && action.canExecute();
       command.disabled = !event.canExecute;
       command.setHidden(!action);
@@ -3180,8 +3179,8 @@
           if (!actionsModel) {
             return;
           }
-          const action = actionsModel.getAction(
-              ActionsModel.InternalActionId.MANAGE_IN_DRIVE);
+          const action =
+              actionsModel.getAction(InternalActionId.MANAGE_IN_DRIVE);
           if (action) {
             actionsController.executeAction(action);
           }
@@ -3210,8 +3209,7 @@
       if (!actionsModel) {
         return;
       }
-      const action =
-          actionsModel.getAction(ActionsModel.InternalActionId.MANAGE_IN_DRIVE);
+      const action = actionsModel.getAction(InternalActionId.MANAGE_IN_DRIVE);
       if (action) {
         command.setHidden(!action);
         event.canExecute = action && action.canExecute();
@@ -3545,8 +3543,8 @@
           if (!actionsModel) {
             return;
           }
-          const action = actionsModel.getAction(
-              ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT);
+          const action =
+              actionsModel.getAction(InternalActionId.CREATE_FOLDER_SHORTCUT);
           if (action) {
             actionsController.executeAction(action);
           }
@@ -3575,8 +3573,8 @@
       if (!actionsModel) {
         return;
       }
-      const action = actionsModel.getAction(
-          ActionsModel.InternalActionId.CREATE_FOLDER_SHORTCUT);
+      const action =
+          actionsModel.getAction(InternalActionId.CREATE_FOLDER_SHORTCUT);
       event.canExecute = action && action.canExecute();
       command.disabled = !event.canExecute;
       command.setHidden(!action);
@@ -3617,8 +3615,8 @@
           if (!actionsModel) {
             return;
           }
-          const action = actionsModel.getAction(
-              ActionsModel.InternalActionId.REMOVE_FOLDER_SHORTCUT);
+          const action =
+              actionsModel.getAction(InternalActionId.REMOVE_FOLDER_SHORTCUT);
           if (action) {
             actionsController.executeAction(action);
           }
@@ -3647,8 +3645,8 @@
       if (!actionsModel) {
         return;
       }
-      const action = actionsModel.getAction(
-          ActionsModel.InternalActionId.REMOVE_FOLDER_SHORTCUT);
+      const action =
+          actionsModel.getAction(InternalActionId.REMOVE_FOLDER_SHORTCUT);
       command.setHidden(!action);
       event.canExecute = action && action.canExecute();
       command.disabled = !event.canExecute;
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.ts b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.ts
index 8bbc43f..ea73985a 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.ts
+++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.ts
@@ -4,8 +4,6 @@
 
 import {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
-import {reportPromise} from '../../../common/js/test_error_reporting.js';
-
 import {ContentMetadataProvider} from './content_metadata_provider.js';
 import {MetadataRequest} from './metadata_request.js';
 
@@ -66,7 +64,7 @@
 
 const entryB = makeFileEntryFromDataURL('empty.jpg', 'data:image/jpeg;base64,');
 
-export function testExternalMetadataProviderBasic(callback: () => void) {
+export async function testExternalMetadataProviderBasic() {
   // Mocking SharedWorker's port.
   const port = {
     postMessage: function(message) {
@@ -90,26 +88,19 @@
 
   // TODO(ryoh): chrome.mediaGalleries API is not available in unit tests.
   const provider = new ContentMetadataProvider(port);
-  reportPromise(
-      provider
-          .get([
-            new MetadataRequest(
-                entryA as unknown as FileSystemEntry,
-                ['contentThumbnailUrl', 'contentThumbnailTransform']),
-            new MetadataRequest(
-                entryB as unknown as FileSystemEntry,
-                ['contentThumbnailUrl', 'contentThumbnailTransform']),
-          ])
-          .then(results => {
-            assertEquals(2, results.length);
-            assertEquals(entryA.url + ',url', results[0]!.contentThumbnailUrl);
-            assertEquals(
-                entryA.url + ',transform',
-                results[0]!.contentThumbnailTransform);
-            assertEquals(entryB.url + ',url', results[1]!.contentThumbnailUrl);
-            assertEquals(
-                entryB.url + ',transform',
-                results[1]!.contentThumbnailTransform);
-          }),
-      callback);
+  const results = await provider.get([
+    new MetadataRequest(
+        entryA as unknown as FileSystemEntry,
+        ['contentThumbnailUrl', 'contentThumbnailTransform']),
+    new MetadataRequest(
+        entryB as unknown as FileSystemEntry,
+        ['contentThumbnailUrl', 'contentThumbnailTransform']),
+  ]);
+  assertEquals(2, results.length);
+  assertEquals(entryA.url + ',url', results[0]!.contentThumbnailUrl);
+  assertEquals(
+      entryA.url + ',transform', results[0]!.contentThumbnailTransform);
+  assertEquals(entryB.url + ',url', results[1]!.contentThumbnailUrl);
+  assertEquals(
+      entryB.url + ',transform', results[1]!.contentThumbnailTransform);
 }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.ts b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.ts
index 3e0a690f1..a08f76f 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.ts
+++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.ts
@@ -4,8 +4,6 @@
 
 import {assertEquals, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
-import {reportPromise} from '../../../common/js/test_error_reporting.js';
-
 import {FileSystemMetadataProvider} from './file_system_metadata_provider.js';
 import {MetadataKey} from './metadata_item.js';
 import {MetadataRequest} from './metadata_request.js';
@@ -30,7 +28,7 @@
   },
 } as Entry;
 
-export function testFileSystemMetadataProviderBasic(callback: () => void) {
+export async function testFileSystemMetadataProviderBasic() {
   const provider = new FileSystemMetadataProvider();
   const names: MetadataKey[] = [
     'modificationTime',
@@ -39,41 +37,33 @@
     'present',
     'availableOffline',
   ];
-  reportPromise(
-      provider
-          .get([
-            new MetadataRequest(entryA, names),
-            new MetadataRequest(entryB, names),
-          ])
-          .then(results => {
-            assertEquals(2, results.length);
-            assertEquals(
-                new Date(2015, 1, 1).toString(),
-                results[0]!.modificationTime!.toString());
-            assertEquals(1024, results[0]!.size);
-            assertTrue(!!results[0]!.present);
-            assertTrue(!!results[0]!.availableOffline);
-            assertEquals(
-                new Date(2015, 2, 2).toString(),
-                results[1]!.modificationTime!.toString());
-            assertEquals(2048, results[1]!.size);
-            assertTrue(!!results[1]!.present);
-            assertTrue(!!results[1]!.availableOffline);
-          }),
-      callback);
+  const results = await provider.get([
+    new MetadataRequest(entryA, names),
+    new MetadataRequest(entryB, names),
+  ]);
+  assertEquals(2, results.length);
+  assertEquals(
+      new Date(2015, 1, 1).toString(),
+      results[0]!.modificationTime!.toString());
+  assertEquals(1024, results[0]!.size);
+  assertTrue(!!results[0]!.present);
+  assertTrue(!!results[0]!.availableOffline);
+  assertEquals(
+      new Date(2015, 2, 2).toString(),
+      results[1]!.modificationTime!.toString());
+  assertEquals(2048, results[1]!.size);
+  assertTrue(!!results[1]!.present);
+  assertTrue(!!results[1]!.availableOffline);
 }
 
-export function testFileSystemMetadataProviderPartialRequest(
-    callback: () => void) {
+export async function testFileSystemMetadataProviderPartialRequest() {
   const provider = new FileSystemMetadataProvider();
-  reportPromise(
-      provider.get([new MetadataRequest(entryA, ['modificationTime', 'size'])])
-          .then(results => {
-            assertEquals(1, results.length);
-            assertEquals(
-                new Date(2015, 1, 1).toString(),
-                results[0]!.modificationTime!.toString());
-            assertEquals(1024, results[0]!.size);
-          }),
-      callback);
+  const results = await provider.get(
+      [new MetadataRequest(entryA, ['modificationTime', 'size'])]);
+
+  assertEquals(1, results.length);
+  assertEquals(
+      new Date(2015, 1, 1).toString(),
+      results[0]!.modificationTime!.toString());
+  assertEquals(1024, results[0]!.size);
 }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js b/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js
deleted file mode 100644
index 09a1f5afd..0000000
--- a/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.js
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2012 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {MetadataParser} from './metadata_parser.js';
-
-/**
- * @class FunctionSequence to invoke steps in sequence.
- */
-export class FunctionSequence {
-  /**
-   * @param {string} name Name of the function.
-   * @param {Array<Function>} steps Array of functions to invoke in sequence.
-   * @param {MetadataParser} logger Logger object.
-   * @param {function():void} callback Callback to invoke on success.
-   * @param {function(string):void} failureCallback Callback to invoke on
-   *     failure.
-   */
-  constructor(name, steps, logger, callback, failureCallback) {
-    // Private variables hidden in closure
-    this.currentStepIdx_ = -1;
-    this.failed_ = false;
-    this.steps_ = steps;
-    this.callback_ = callback;
-    this.failureCallback_ = failureCallback;
-    this.logger = logger;
-    this.name = name;
-    /** @public @type {boolean} */
-    this.started = false;
-
-    this.onError = this.onError_.bind(this);
-    this.finish = this.finish_.bind(this);
-    this.nextStep = this.nextStep_.bind(this);
-    this.apply = this.apply_.bind(this);
-  }
-
-  /**
-   * Sets new callback
-   *
-   * @param {function():void} callback New callback to call on succeed.
-   */
-  setCallback(callback) {
-    this.callback_ = callback;
-  }
-
-  /**
-   * Sets new error callback
-   *
-   * @param {function(string):void} failureCallback New callback to call on
-   *     failure.
-   */
-  setFailureCallback(failureCallback) {
-    this.failureCallback_ = failureCallback;
-  }
-
-
-  /**
-   * Error handling function, which traces current error step, stops sequence
-   * advancing and fires error callback.
-   *
-   * @param {string} err Error message.
-   * @private
-   */
-  onError_(err) {
-    this.logger.vlog(
-        'Failed step: ' + this.steps_[this.currentStepIdx_]?.name + ': ' + err);
-    if (!this.failed_) {
-      this.failed_ = true;
-      this.failureCallback_(err);
-    }
-  }
-
-  /**
-   * Finishes sequence processing and jumps to the last step.
-   * This method should not be used externally. In external
-   * cases should be used finish function, which is defined in closure and thus
-   * has access to internal variables of functionsequence.
-   * @private
-   */
-  finish_() {
-    if (!this.failed_ && this.currentStepIdx_ < this.steps_.length) {
-      this.currentStepIdx_ = this.steps_.length;
-      this.callback_();
-    }
-  }
-
-  /**
-   * Advances to next step.
-   * This method should not be used externally. In external
-   * cases should be used nextStep function, which is defined in closure and
-   * thus has access to internal variables of functionsequence.
-   * @param {...*} var_args Arguments to be passed to the next step.
-   * @private
-   */
-  // @ts-ignore: error TS6133: 'var_args' is declared but its value is never
-  // read.
-  nextStep_(var_args) {
-    if (this.failed_) {
-      return;
-    }
-
-    if (++this.currentStepIdx_ >= this.steps_.length) {
-      this.logger.vlog('Sequence ended');
-      // @ts-ignore: error TS2345: Argument of type 'IArguments' is not
-      // assignable to parameter of type '[]'.
-      this.callback_.apply(this, arguments);
-    } else {
-      this.logger.vlog(
-          'Attempting to start step [' +
-          this.steps_[this.currentStepIdx_]?.name + ']');
-      try {
-        this.steps_[this.currentStepIdx_]?.apply(this, arguments);
-      } catch (e) {
-        // @ts-ignore: error TS18046: 'e' is of type 'unknown'.
-        this.onError(e.toString());
-      }
-    }
-  }
-
-  /**
-   * This function should be called only once on start, so start sequence
-   * pipeline
-   * @param {...*} var_args Arguments to be passed to the first step.
-   */
-  // @ts-ignore: error TS6133: 'var_args' is declared but its value is never
-  // read.
-  start(var_args) {
-    if (this.started) {
-      throw new Error('"Start" method of FunctionSequence was called twice');
-    }
-
-    this.logger.log(
-        'Starting sequence with ' + arguments.length + ' arguments');
-
-    this.started = true;
-    // @ts-ignore: error TS2345: Argument of type 'IArguments' is not assignable
-    // to parameter of type 'any[]'.
-    this.nextStep.apply(this, arguments);
-  }
-
-  /**
-   * Add Function object mimics to FunctionSequence
-   * @private
-   * @param {*} obj Object.
-   * @param {Array<*>} args Arguments.
-   */
-  // @ts-ignore: error TS6133: 'obj' is declared but its value is never read.
-  apply_(obj, args) {
-    this.start.apply(this, args);
-  }
-}
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.ts b/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.ts
new file mode 100644
index 0000000..168f798
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/metadata/function_sequence.ts
@@ -0,0 +1,123 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {MetadataParser} from './metadata_parser.js';
+
+/**
+ * Invoke steps in sequence.
+ */
+export class FunctionSequence {
+  private currentStepIdx_ = -1;
+  private failed_ = false;
+
+  started = false;
+  onError: (err: string) => void;
+  finish: () => void;
+  nextStep: (...args: unknown[]) => void;
+
+  /**
+   * @param steps Array of functions to invoke in sequence.
+   * @param logger Logger object.
+   * @param callback Callback to invoke on success.
+   * @param failureCallback Callback to invoke on failure.
+   */
+  constructor(
+      private steps_: Function[], private logger: MetadataParser,
+      private callback_: VoidCallback,
+      private failureCallback_: (error: string) => void) {
+    this.onError = this.onError_.bind(this);
+    this.finish = this.finish_.bind(this);
+    this.nextStep = this.nextStep_.bind(this);
+  }
+
+  /**
+   * Sets new callback
+   *
+   * @param callback New callback to call on succeed.
+   */
+  setCallback(callback: VoidCallback) {
+    this.callback_ = callback;
+  }
+
+  /**
+   * Sets new error callback
+   *
+   * @param failureCallback New callback to call on failure.
+   */
+  setFailureCallback(failureCallback: (error: string) => void) {
+    this.failureCallback_ = failureCallback;
+  }
+
+
+  /**
+   * Error handling function, which traces current error step, stops sequence
+   * advancing and fires error callback.
+   *
+   * @param err Error message.
+   */
+  private onError_(err: string) {
+    this.logger.vlog(
+        'Failed step: ' + this.steps_[this.currentStepIdx_]?.name + ': ' + err);
+    if (!this.failed_) {
+      this.failed_ = true;
+      this.failureCallback_(err);
+    }
+  }
+
+  /**
+   * Finishes sequence processing and jumps to the last step.
+   * This method should not be used externally. In external
+   * cases should be used finish function, which is defined in closure and thus
+   * has access to internal variables of functionsequence.
+   */
+  private finish_() {
+    if (!this.failed_ && this.currentStepIdx_ < this.steps_.length) {
+      this.currentStepIdx_ = this.steps_.length;
+      this.callback_();
+    }
+  }
+
+  /**
+   * Advances to next step.
+   * This method should not be used externally. In external cases should be used
+   * nextStep function, which is defined in closure and thus has access to
+   * internal variables of functionsequence.
+   * @param args Arguments to be passed to the next step.
+   */
+  private nextStep_(...args: unknown[]) {
+    if (this.failed_) {
+      return;
+    }
+
+    if (++this.currentStepIdx_ >= this.steps_.length) {
+      this.logger.vlog('Sequence ended');
+      this.callback_.apply(this);
+    } else {
+      this.logger.vlog(
+          'Attempting to start step [' +
+          this.steps_[this.currentStepIdx_]?.name + ']');
+      try {
+        this.steps_[this.currentStepIdx_]?.apply(this, args);
+      } catch (e) {
+        this.onError(e!.toString());
+      }
+    }
+  }
+
+  /**
+   * This function should be called only once on start, so start sequence
+   * pipeline
+   * @param args Arguments to be passed to the first step.
+   */
+  start(...args: unknown[]) {
+    if (this.started) {
+      throw new Error('"Start" method of FunctionSequence was called twice');
+    }
+
+    this.logger.log('Starting sequence with ' + args.length + ' arguments');
+
+    this.started = true;
+    this.nextStep.apply(this, args);
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js b/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js
index fffff4b4..92c4edf 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/id3_parser.js
@@ -309,7 +309,7 @@
     this.log('Starting id3 parser for ' + file.name);
 
     const id3v1Parser = new FunctionSequence(
-        'id3v1parser', [
+        [
           /**
            * Reads last 128 bytes of file in bytebuffer,
            * which passes further.
@@ -376,7 +376,7 @@
         this, () => {}, error => {});
 
     const id3v2Parser = new FunctionSequence(
-        'id3v2parser', [
+        [
           // @ts-ignore: error TS7006: Parameter 'file' implicitly has an 'any'
           // type.
           function readHead(file) {
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set.js
index 445a8ec..09091ad 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set.js
@@ -12,6 +12,26 @@
 import {MetadataRequest} from './metadata_request.js';
 
 /**
+ * Custom event dispatched by the metadata cache set when results from metadata
+ * provider are set on it.
+ */
+export class MetadataSetEvent extends Event {
+  /**
+   * @param {string} name
+   * @param {!Array<!FileEntry>} entries
+   * @param {!Map<string, !FileEntry>} entriesMap
+   * @param {!Set<string>} names
+   */
+  constructor(name, entries, entriesMap, names) {
+    super(name);
+    this.entries = entries;
+    this.entriesMap = entriesMap;
+    this.names = names;
+  }
+}
+
+
+/**
  * A collection of MetadataCacheItem objects. This class acts as a map from file
  * entry URLs to metadata items. You can store metadata for entries, you can
  * retrieve metadata for entries, clear the entire cache, or just selected
@@ -86,6 +106,7 @@
    * @return {boolean} Whether at least one result is stored or not.
    */
   storeProperties(requestId, entries, results, names) {
+    /** @type {!Array<!FileEntry>} */
     const changedEntries = [];
     const urls = entriesToURLs(entries);
     const entriesMap = new Map();
@@ -94,7 +115,7 @@
       const url = urls[i];
       const item = this.items_.get(url);
       if (item && item.storeProperties(requestId, results[i])) {
-        changedEntries.push(entries[i]);
+        changedEntries.push(/** @type{!FileEntry} */ (entries[i]));
         entriesMap.set(url, entries[i]);
       }
     }
@@ -103,16 +124,8 @@
       return false;
     }
 
-    const event = new Event('update');
-    // @ts-ignore: error TS2339: Property 'entries' does not exist on type
-    // 'Event'.
-    event.entries = changedEntries;
-    // @ts-ignore: error TS2339: Property 'entriesMap' does not exist on type
-    // 'Event'.
-    event.entriesMap = entriesMap;
-    // @ts-ignore: error TS2339: Property 'names' does not exist on type
-    // 'Event'.
-    event.names = new Set(names);
+    const event = new MetadataSetEvent(
+        'update', changedEntries, entriesMap, new Set(names));
     this.dispatchEvent(event);
     return true;
   }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js b/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
index 186b492..b28ee8f 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata/mock_metadata.js
@@ -13,11 +13,11 @@
  * @final
  */
 export class MockMetadataModel {
-  /** @param {Object} initial_properties */
+  /** @param {Record<string, any>} initial_properties */
   constructor(initial_properties) {
     /**
      * Dummy properties, which can be overwritten by a test.
-     * @public @const @type {Object}
+     * @public @const @type {Record<string, any>}
      */
     this.properties = initial_properties;
 
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js
deleted file mode 100644
index 702ee2f..0000000
--- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {isAudio, isImage} from '../../../common/js/file_type.js';
-
-import {MetadataModel} from './metadata_model.js';
-
-/**
- * Metadata containing thumbnail information.
- * @typedef {Object}
- */
-let ThumbnailMetadataItem;
-
-export class ThumbnailModel {
-  /**
-   * @param {!MetadataModel} metadataModel
-   */
-  constructor(metadataModel) {
-    /**
-     * @private @type {!MetadataModel}
-     * @const
-     */
-    this.metadataModel_ = metadataModel;
-  }
-
-  /**
-   * @param {!Array<!Entry>} entries
-   * @return {Promise<ThumbnailMetadataItem>} Promise fulfilled with old format
-   *     metadata list.
-   */
-  get(entries) {
-    const results = {};
-    return this.metadataModel_
-        .get(
-            entries,
-            [
-              'modificationTime',
-              'customIconUrl',
-              'contentMimeType',
-              'thumbnailUrl',
-              'croppedThumbnailUrl',
-              'present',
-            ])
-        // @ts-ignore: error TS7030: Not all code paths return a value.
-        .then(metadataList => {
-          // @ts-ignore: error TS7034: Variable 'contentRequestEntries'
-          // implicitly has type 'any[]' in some locations where its type cannot
-          // be determined.
-          const contentRequestEntries = [];
-          for (let i = 0; i < entries.length; i++) {
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-            const url = entries[i].toURL();
-            // TODO(hirono): Use the provider results directly after removing
-            // code using old metadata format.
-            // @ts-ignore: error TS7053: Element implicitly has an 'any' type
-            // because expression of type 'string' can't be used to index type
-            // '{}'.
-            results[url] = {
-              filesystem: {
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                modificationTime: metadataList[i].modificationTime,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                modificationTimeError: metadataList[i].modificationTimeError,
-              },
-              external: {
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                thumbnailUrl: metadataList[i].thumbnailUrl,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                thumbnailUrlError: metadataList[i].thumbnailUrlError,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                croppedThumbnailUrl: metadataList[i].croppedThumbnailUrl,
-                croppedThumbnailUrlError:
-                    // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                    metadataList[i].croppedThumbnailUrlError,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                customIconUrl: metadataList[i].customIconUrl,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                customIconUrlError: metadataList[i].customIconUrlError,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                present: metadataList[i].present,
-                // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                presentError: metadataList[i].presentError,
-              },
-              thumbnail: {},
-              media: {},
-            };
-            // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-            const canUseContentThumbnail = metadataList[i].present &&
-                (isImage(
-                     // @ts-ignore: error TS2532: Object is possibly
-                     // 'undefined'.
-                     entries[i], metadataList[i].contentMimeType) ||
-                 // @ts-ignore: error TS2532: Object is possibly 'undefined'.
-                 isAudio(entries[i], metadataList[i].contentMimeType));
-            if (canUseContentThumbnail) {
-              contentRequestEntries.push(entries[i]);
-            }
-          }
-          if (contentRequestEntries.length) {
-            return this.metadataModel_
-                .get(
-                    // @ts-ignore: error TS2345: Argument of type
-                    // '(FileSystemEntry | undefined)[]' is not assignable to
-                    // parameter of type 'FileSystemEntry[]'.
-                    contentRequestEntries,
-                    [
-                      'contentThumbnailUrl',
-                      'contentThumbnailTransform',
-                      'contentImageTransform',
-                    ])
-                .then(contentMetadataList => {
-                  for (let i = 0; i < contentRequestEntries.length; i++) {
-                    // @ts-ignore: error TS7005: Variable
-                    // 'contentRequestEntries' implicitly has an 'any[]' type.
-                    const url = contentRequestEntries[i].toURL();
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].thumbnail.url =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentThumbnailUrl;
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].thumbnail.urlError =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentThumbnailUrlError;
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].thumbnail.transform =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentThumbnailTransform;
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].thumbnail.transformError =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentThumbnailTransformError;
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].media.imageTransform =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentImageTransform;
-                    // @ts-ignore: error TS7053: Element implicitly has an 'any'
-                    // type because expression of type 'any' can't be used to
-                    // index type '{}'.
-                    results[url].media.imageTransformError =
-                        // @ts-ignore: error TS2532: Object is possibly
-                        // 'undefined'.
-                        contentMetadataList[i].contentImageTransformError;
-                  }
-                });
-          }
-        })
-        .then(() => {
-          return entries.map(entry => {
-            // @ts-ignore: error TS7053: Element implicitly has an 'any' type
-            // because expression of type 'string' can't be used to index type
-            // '{}'.
-            return results[entry.toURL()];
-          });
-        });
-  }
-}
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.ts b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.ts
new file mode 100644
index 0000000..8020b97
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model.ts
@@ -0,0 +1,111 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {isAudio, isImage} from '../../../common/js/file_type.js';
+
+import {ImageTransformation} from './metadata_item.js';
+import {MetadataModel} from './metadata_model.js';
+
+/**
+ * Metadata containing thumbnail information.
+ */
+interface ThumbnailMetadataItem {
+  filesystem: {modificationTime?: Date, modificationTimeError?: Error};
+  external: {
+    thumbnailUrl?: string,
+    thumbnailUrlError?: Error,
+    croppedThumbnailUrl?: string,
+    croppedThumbnailUrlError?: Error,
+    customIconUrl?: string,
+    customIconUrlError?: Error,
+    present?: boolean,
+    presentError?: Error,
+  };
+  thumbnail: {
+    url?: string,
+    urlError?: Error,
+    transform?: ImageTransformation,
+    transformError?: Error,
+  };
+  media: {imageTransform?: ImageTransformation, imageTransformError?: Error};
+}
+
+export class ThumbnailModel {
+  constructor(private readonly metadataModel_: MetadataModel) {}
+
+  /**
+   * @return Promise fulfilled with old format metadata list.
+   */
+  async get(entries: Entry[]): Promise<ThumbnailMetadataItem[]> {
+    const results: Record<string, ThumbnailMetadataItem> = {};
+    const metadataList = await this.metadataModel_.get(entries, [
+      'modificationTime',
+      'customIconUrl',
+      'contentMimeType',
+      'thumbnailUrl',
+      'croppedThumbnailUrl',
+      'present',
+    ]);
+
+    const contentRequestEntries: Entry[] = [];
+    for (let i = 0; i < entries.length; i++) {
+      const entry = entries[i]!;
+      const metadata = metadataList[i]!;
+      const url = entry.toURL();
+
+      // TODO(hirono): Use the provider results directly after removing
+      // code using old metadata format.
+      results[url] = {
+        filesystem: {
+          modificationTime: metadata.modificationTime,
+          modificationTimeError: metadata.modificationTimeError,
+        },
+        external: {
+          thumbnailUrl: metadata.thumbnailUrl,
+          thumbnailUrlError: metadata.thumbnailUrlError,
+          croppedThumbnailUrl: metadata.croppedThumbnailUrl,
+          croppedThumbnailUrlError: metadata.croppedThumbnailUrlError,
+          customIconUrl: metadata.customIconUrl,
+          customIconUrlError: metadata.customIconUrlError,
+          present: metadata.present,
+          presentError: metadata.presentError,
+        },
+        thumbnail: {},
+        media: {},
+      };
+      const canUseContentThumbnail = metadata.present &&
+          (isImage(entry, metadata.contentMimeType) ||
+           isAudio(entry, metadata.contentMimeType));
+      if (canUseContentThumbnail) {
+        contentRequestEntries.push(entry);
+      }
+    }
+    if (contentRequestEntries.length) {
+      const contentMetadataList =
+          await this.metadataModel_.get(contentRequestEntries, [
+            'contentThumbnailUrl',
+            'contentThumbnailTransform',
+            'contentImageTransform',
+          ]);
+      for (let i = 0; i < contentRequestEntries.length; i++) {
+        const url = contentRequestEntries[i]!.toURL();
+        const contentMetadata = contentMetadataList[i]!;
+        const result = results[url]!;
+
+        result.thumbnail.url = contentMetadata.contentThumbnailUrl;
+        result.thumbnail.urlError = contentMetadata.contentThumbnailUrlError;
+        result.thumbnail.transform = contentMetadata.contentThumbnailTransform;
+        result.thumbnail.transformError =
+            contentMetadata.contentThumbnailTransformError;
+        result.media.imageTransform = contentMetadata.contentImageTransform;
+        result.media.imageTransformError =
+            contentMetadata.contentImageTransformError;
+      }
+    }
+
+    return entries.map(entry => {
+      return results[entry.toURL()]!;
+    });
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
deleted file mode 100644
index f73d3b1..0000000
--- a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.js
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
-
-import {reportPromise} from '../../../common/js/test_error_reporting.js';
-
-import {MetadataItem} from './metadata_item.js';
-import {MetadataModel} from './metadata_model.js';
-import {ThumbnailModel} from './thumbnail_model.js';
-
-const imageEntry = {
-  name: 'image.jpg',
-  toURL: function() {
-    return 'filesystem://A';
-  },
-};
-
-const nonImageEntry = {
-  name: 'note.txt',
-  toURL: function() {
-    return 'filesystem://B';
-  },
-};
-
-const contentThumbnailTransform = {
-  scaleX: 0,
-  scaleY: 0,
-  rotate90: 0,
-};
-
-const imageTransformation = {
-  scaleX: 1,
-  scaleY: 1,
-  rotate90: 2,
-};
-
-// @ts-ignore: error TS7034: Variable 'metadata' implicitly has type 'any' in
-// some locations where its type cannot be determined.
-let metadata;
-// @ts-ignore: error TS6133: 'contentMetadata' is declared but its value is
-// never read.
-let contentMetadata;
-// @ts-ignore: error TS7034: Variable 'thumbnailModel' implicitly has type 'any'
-// in some locations where its type cannot be determined.
-let thumbnailModel;
-
-export function setUp() {
-  metadata = new MetadataItem();
-  metadata.modificationTime = new Date(2015, 0, 1);
-  metadata.present = true;
-  metadata.thumbnailUrl = 'EXTERNAL_THUMBNAIL_URL';
-  metadata.customIconUrl = 'CUSTOM_ICON_URL';
-  metadata.contentThumbnailUrl = 'CONTENT_THUMBNAIL_URL';
-  metadata.contentThumbnailTransform = contentThumbnailTransform;
-  metadata.contentImageTransform = imageTransformation;
-
-  thumbnailModel = new ThumbnailModel(/** @type {!MetadataModel} */ ({
-    // @ts-ignore: error TS6133: 'entries' is declared but its value is never
-    // read.
-    get: function(entries, names) {
-      const result = new MetadataItem();
-      for (let i = 0; i < names.length; i++) {
-        const name = names[i];
-        // @ts-ignore: error TS2538: Type 'undefined' cannot be used as an index
-        // type.
-        result[name] = metadata[name];
-      }
-      return Promise.resolve([result]);
-    },
-  }));
-}
-
-/** @param {()=>void} callback */
-export function testThumbnailModelGetBasic(callback) {
-  reportPromise(
-      // @ts-ignore: error TS7006: Parameter 'results' implicitly has an 'any'
-      // type.
-      thumbnailModel.get([imageEntry]).then(results => {
-        assertEquals(1, results.length);
-        assertEquals(
-            new Date(2015, 0, 1).toString(),
-            results[0].filesystem.modificationTime.toString());
-        assertEquals(
-            'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl);
-        assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl);
-        assertTrue(results[0].external.present);
-        assertEquals('CONTENT_THUMBNAIL_URL', results[0].thumbnail.url);
-        assertEquals(contentThumbnailTransform, results[0].thumbnail.transform);
-        assertEquals(imageTransformation, results[0].media.imageTransform);
-      }),
-      callback);
-}
-
-/** @param {()=>void} callback */
-export function testThumbnailModelGetNotPresent(callback) {
-  // @ts-ignore: error TS7005: Variable 'metadata' implicitly has an 'any' type.
-  metadata.present = false;
-  reportPromise(
-      // @ts-ignore: error TS7006: Parameter 'results' implicitly has an 'any'
-      // type.
-      thumbnailModel.get([imageEntry]).then(results => {
-        assertEquals(1, results.length);
-        assertEquals(
-            new Date(2015, 0, 1).toString(),
-            results[0].filesystem.modificationTime.toString());
-        assertEquals(
-            'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl);
-        assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl);
-        assertFalse(results[0].external.present);
-        assertEquals(undefined, results[0].thumbnail.url);
-        assertEquals(undefined, results[0].thumbnail.transform);
-        assertEquals(undefined, results[0].media.imageTransform);
-      }),
-      callback);
-}
-
-/** @param {()=>void} callback */
-export function testThumbnailModelGetNonImage(callback) {
-  reportPromise(
-      // @ts-ignore: error TS7006: Parameter 'results' implicitly has an 'any'
-      // type.
-      thumbnailModel.get([nonImageEntry]).then(results => {
-        assertEquals(1, results.length);
-        assertEquals(
-            new Date(2015, 0, 1).toString(),
-            results[0].filesystem.modificationTime.toString());
-        assertEquals(
-            'EXTERNAL_THUMBNAIL_URL', results[0].external.thumbnailUrl);
-        assertEquals('CUSTOM_ICON_URL', results[0].external.customIconUrl);
-        assertTrue(results[0].external.present);
-        assertEquals(undefined, results[0].thumbnail.url);
-        assertEquals(undefined, results[0].thumbnail.transform);
-        assertEquals(undefined, results[0].media.imageTransform);
-      }),
-      callback);
-}
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.ts b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.ts
new file mode 100644
index 0000000..12761521
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/metadata/thumbnail_model_unittest.ts
@@ -0,0 +1,105 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
+
+import {MetadataItem} from './metadata_item.js';
+import {MetadataModel} from './metadata_model.js';
+import {ThumbnailModel} from './thumbnail_model.js';
+
+const imageEntry: Entry = {
+  name: 'image.jpg',
+  toURL: function() {
+    return 'filesystem://A';
+  },
+} as Entry;
+
+const nonImageEntry: Entry = {
+  name: 'note.txt',
+  toURL: function() {
+    return 'filesystem://B';
+  },
+} as Entry;
+
+const contentThumbnailTransform = {
+  scaleX: 0,
+  scaleY: 0,
+  rotate90: 0,
+};
+
+const imageTransformation = {
+  scaleX: 1,
+  scaleY: 1,
+  rotate90: 2,
+};
+
+let metadata: MetadataItem;
+let thumbnailModel: ThumbnailModel;
+
+export function setUp() {
+  metadata = new MetadataItem();
+  metadata.modificationTime = new Date(2015, 0, 1);
+  metadata.present = true;
+  metadata.thumbnailUrl = 'EXTERNAL_THUMBNAIL_URL';
+  metadata.customIconUrl = 'CUSTOM_ICON_URL';
+  metadata.contentThumbnailUrl = 'CONTENT_THUMBNAIL_URL';
+  metadata.contentThumbnailTransform = contentThumbnailTransform;
+  metadata.contentImageTransform = imageTransformation;
+
+  thumbnailModel = new ThumbnailModel({
+    get: function(_: Entry[], names: string[]) {
+      const result = new MetadataItem();
+      // Assign all the properties from `metadata` with keys in `names` to the
+      // same named property in `result`.
+      (names as Array<keyof MetadataItem>)
+          .forEach(
+              <K extends keyof MetadataItem>(name: K) => result[name] =
+                  metadata[name]);
+      return Promise.resolve([result]);
+    },
+  } as MetadataModel);
+}
+
+export async function testThumbnailModelGetBasic() {
+  const results = await thumbnailModel.get([imageEntry]);
+  assertEquals(1, results.length);
+  assertEquals(
+      new Date(2015, 0, 1).toString(),
+      results[0]!.filesystem!.modificationTime!.toString());
+  assertEquals('EXTERNAL_THUMBNAIL_URL', results[0]!.external.thumbnailUrl);
+  assertEquals('CUSTOM_ICON_URL', results[0]!.external.customIconUrl);
+  assertTrue(!!results[0]!.external.present);
+  assertEquals('CONTENT_THUMBNAIL_URL', results[0]!.thumbnail.url);
+  assertEquals(contentThumbnailTransform, results[0]!.thumbnail.transform);
+  assertEquals(imageTransformation, results[0]!.media.imageTransform);
+}
+
+export async function testThumbnailModelGetNotPresent() {
+  metadata.present = false;
+  const results = await thumbnailModel.get([imageEntry]);
+  assertEquals(1, results.length);
+  assertEquals(
+      new Date(2015, 0, 1).toString(),
+      results[0]!.filesystem!.modificationTime!.toString());
+  assertEquals('EXTERNAL_THUMBNAIL_URL', results[0]!.external.thumbnailUrl);
+  assertEquals('CUSTOM_ICON_URL', results[0]!.external.customIconUrl);
+  assertFalse(!!results[0]!.external.present);
+  assertEquals(undefined, results[0]!.thumbnail.url);
+  assertEquals(undefined, results[0]!.thumbnail.transform);
+  assertEquals(undefined, results[0]!.media.imageTransform);
+}
+
+export async function testThumbnailModelGetNonImage() {
+  const results = await thumbnailModel.get([nonImageEntry]);
+  assertEquals(1, results.length);
+  assertEquals(
+      new Date(2015, 0, 1).toString(),
+      results[0]!.filesystem!.modificationTime!.toString());
+  assertEquals('EXTERNAL_THUMBNAIL_URL', results[0]!.external.thumbnailUrl);
+  assertEquals('CUSTOM_ICON_URL', results[0]!.external.customIconUrl);
+  assertTrue(!!results[0]!.external.present);
+  assertEquals(undefined, results[0]!.thumbnail.url);
+  assertEquals(undefined, results[0]!.thumbnail.transform);
+  assertEquals(undefined, results[0]!.media.imageTransform);
+}
diff --git a/ui/file_manager/file_manager/foreground/js/mock_actions_model.js b/ui/file_manager/file_manager/foreground/js/mock_actions_model.js
deleted file mode 100644
index ce9bfd9..0000000
--- a/ui/file_manager/file_manager/foreground/js/mock_actions_model.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
-import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
-
-export class MockActionModel extends EventTarget {
-  /**
-   * @param {string} title
-   * @param {Array<!Entry>} entries
-   */
-  constructor(title, entries) {
-    super();
-
-    this.title = title;
-    this.entries = entries;
-    this.actionsModel = null;
-  }
-
-  getTitle() {
-    return this.title;
-  }
-
-  onCanExecute() {}
-
-  onExecute() {
-    dispatchSimpleEvent(this, 'invalidated', true);
-  }
-}
-
-export class MockActionsModel extends EventTarget {
-  // @ts-ignore: error TS7006: Parameter 'actions' implicitly has an 'any' type.
-  constructor(actions) {
-    super();
-
-    this.actions_ = actions;
-    Object.keys(actions).forEach(function(key) {
-      // @ts-ignore: error TS2683: 'this' implicitly has type 'any' because it
-      // does not have a type annotation.
-      actions[key].actionsModel = this;
-    });
-  }
-
-  initialize() {
-    return Promise.resolve();
-  }
-
-  getActions() {
-    return this.actions_;
-  }
-}
diff --git a/ui/file_manager/file_manager/foreground/js/mock_actions_model.ts b/ui/file_manager/file_manager/foreground/js/mock_actions_model.ts
new file mode 100644
index 0000000..4b2e946
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/js/mock_actions_model.ts
@@ -0,0 +1,44 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
+import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
+
+export class MockActionModel extends EventTarget {
+  constructor(
+      public title: string, public entries: Entry[],
+      public actionsModel: MockActionsModel|null = null) {
+    super();
+  }
+
+  getTitle() {
+    return this.title;
+  }
+
+  onCanExecute() {}
+
+  onExecute() {
+    dispatchSimpleEvent(this, 'invalidated', true);
+  }
+}
+
+export class MockActionsModel extends EventTarget {
+  constructor(private actions_: Record<string, MockActionModel>) {
+    super();
+
+    Object.keys(this.actions_).forEach((key) => {
+      if (this.actions_[key]) {
+        this.actions_[key]!.actionsModel = this;
+      }
+    });
+  }
+
+  initialize() {
+    return Promise.resolve();
+  }
+
+  getActions() {
+    return this.actions_;
+  }
+}
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
index 12a2320..3415665 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
+++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.ts
@@ -11,7 +11,6 @@
 import {isSameEntries} from '../../common/js/entry_utils.js';
 import {installMockChrome} from '../../common/js/mock_chrome.js';
 import {MockFileEntry, MockFileSystem} from '../../common/js/mock_entry.js';
-import {reportPromise} from '../../common/js/test_error_reporting.js';
 import {decorate} from '../../common/js/ui.js';
 import {descriptorEqual} from '../../common/js/util.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
@@ -159,7 +158,7 @@
 /**
  * Tests that executeEntryTask() runs the expected task.
  */
-export function testExecuteEntryTask(callback: () => void) {
+export async function testExecuteEntryTask() {
   const selectionHandler = window.fileManager.selectionHandler;
 
   const fileSystem = downloads.fileSystem as MockFileSystem;
@@ -170,23 +169,22 @@
   const testEntry = fileSystem.entries['/test.png'] as Entry;
   taskController.executeEntryTask(testEntry);
 
-  reportPromise(
-      new Promise<chrome.fileManagerPrivate.FileTaskDescriptor>((resolve) => {
-        chrome.fileManagerPrivate.executeTask = resolve;
-      }).then((descriptor: chrome.fileManagerPrivate.FileTaskDescriptor) => {
-        assert(descriptorEqual(
-            {appId: 'handler-extension-id', taskType: 'file', actionId: 'play'},
-            descriptor));
-      }),
-      callback);
+  const descriptor =
+      await new Promise<chrome.fileManagerPrivate.FileTaskDescriptor>(
+          (resolve) => {
+            chrome.fileManagerPrivate.executeTask = resolve;
+          });
+
+  assert(descriptorEqual(
+      {appId: 'handler-extension-id', taskType: 'file', actionId: 'play'},
+      descriptor));
 }
 
 /**
  * Tests that getFileTasks() does not call .fileManagerPrivate.getFileTasks()
  * multiple times when the selected entries are not changed.
  */
-export async function testGetFileTasksShouldNotBeCalledMultipleTimes(
-    done: () => void) {
+export async function testGetFileTasksShouldNotBeCalledMultipleTimes() {
   const selectionHandler = window.fileManager.selectionHandler;
   const store = getStore();
   const taskController =
@@ -237,8 +235,6 @@
       'both tasks should have hello.txt as entry');
   assert(isSameEntries(tasks3.entries, selectionHandler.selection.entries));
   assert(mockChrome.fileManagerPrivate.getFileTaskCalledCount_ === 3);
-
-  done();
 }
 
 
@@ -246,8 +242,7 @@
  * Tests the file tasks in the store are updated each time the selected entries
  * are changed, including when there are no selected entries.
  */
-export async function testFileTasksUpdatedAfterSelectionChange(
-    done: () => void) {
+export async function testFileTasksUpdatedAfterSelectionChange() {
   const selectionHandler = window.fileManager.selectionHandler;
   const store = getStore();
   const fileSystem = downloads.fileSystem;
@@ -277,7 +272,6 @@
       (st: State) =>
           st.currentDirectory?.selection.fileTasks.tasks !== undefined &&
           st.currentDirectory?.selection.fileTasks.tasks.length === 0);
-  done();
 }
 
 /**
@@ -285,8 +279,7 @@
  * correspond to FileSelectionHandler.selection at the time getFileTasks() is
  * called.
  */
-export function testGetFileTasksShouldNotReturnObsoletePromise(
-    callback: () => void) {
+export async function testGetFileTasksShouldNotReturnObsoletePromise() {
   const selectionHandler = window.fileManager.selectionHandler;
   const store = getStore();
   const fileSystem = downloads.fileSystem;
@@ -295,31 +288,24 @@
   selectionHandler.updateSelection(
       [MockFileEntry.create(fileSystem, '/test.png')], ['image/png'], store);
 
-  taskController.getFileTasks()
-      .then(tasks => {
-        assert(
-            isSameEntries(tasks.entries, selectionHandler.selection.entries));
-        selectionHandler.updateSelection(
-            [MockFileEntry.create(fileSystem, '/testtest.jpg')], ['image/jpeg'],
-            store);
-        return taskController.getFileTasks();
-      })
-      .then(tasks => {
-        assert(
-            isSameEntries(tasks.entries, selectionHandler.selection.entries));
-        callback();
-      })
-      .catch(error => {
-        assertNotReached(error.toString());
-      });
+  let tasks = await taskController.getFileTasks();
+  assert(isSameEntries(tasks.entries, selectionHandler.selection.entries));
+  selectionHandler.updateSelection(
+      [MockFileEntry.create(fileSystem, '/testtest.jpg')], ['image/jpeg'],
+      store);
+  try {
+    tasks = await taskController.getFileTasks();
+    assert(isSameEntries(tasks.entries, selectionHandler.selection.entries));
+  } catch (error) {
+    assertNotReached(error!.toString());
+  }
 }
 
 /**
  * Tests that changing the file selection during a getFileTasks() call causes
  * the getFileTasks() promise to reject.
  */
-export async function testGetFileTasksShouldNotCacheRejectedPromise(
-    done: () => void) {
+export async function testGetFileTasksShouldNotCacheRejectedPromise() {
   const selectionHandler = window.fileManager.selectionHandler;
   const store = getStore();
   const fileSystem = downloads.fileSystem;
@@ -366,5 +352,4 @@
                   entries.filter((e: Entry) => e.name === '/test.png').length)
           .length,
       'Should have NO calls to private API for the initial selection');
-  done();
 }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
index 8c31163f..5731b10 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {queryDecoratedElement, queryRequiredElement} from '../../../common/js/dom_utils.js';
-import {ActionsModel} from '../actions_model.js';
+import {ActionsModel, CommonActionId, InternalActionId} from '../actions_model.js';
 
 import {Command} from './command.js';
 import {FilesMenuItem} from './files_menu.js';
@@ -75,7 +75,7 @@
     // First add the sharing item (if available).
     // @ts-ignore: error TS7053: Element implicitly has an 'any' type because
     // expression of type 'string' can't be used to index type '{}'.
-    const shareAction = remainingActions[ActionsModel.CommonActionId.SHARE];
+    const shareAction = remainingActions[CommonActionId.SHARE];
     if (shareAction) {
       const menuItem = this.addMenuItem_({});
       // @ts-ignore: error TS2339: Property 'command' does not exist on type
@@ -84,7 +84,7 @@
       menuItem.classList.toggle('hide-on-toolbar', true);
       // @ts-ignore: error TS7053: Element implicitly has an 'any' type because
       // expression of type 'string' can't be used to index type '{}'.
-      delete remainingActions[ActionsModel.CommonActionId.SHARE];
+      delete remainingActions[CommonActionId.SHARE];
     }
     queryDecoratedElement('#share', Command).canExecuteChange(element);
 
@@ -92,7 +92,7 @@
     const manageInDriveAction =
         // @ts-ignore: error TS7053: Element implicitly has an 'any' type
         // because expression of type 'string' can't be used to index type '{}'.
-        remainingActions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
+        remainingActions[InternalActionId.MANAGE_IN_DRIVE];
     if (manageInDriveAction) {
       const menuItem = this.addMenuItem_({});
       // @ts-ignore: error TS2339: Property 'command' does not exist on type
@@ -101,7 +101,7 @@
       menuItem.classList.toggle('hide-on-toolbar', true);
       // @ts-ignore: error TS7053: Element implicitly has an 'any' type because
       // expression of type 'string' can't be used to index type '{}'.
-      delete remainingActions[ActionsModel.InternalActionId.MANAGE_IN_DRIVE];
+      delete remainingActions[InternalActionId.MANAGE_IN_DRIVE];
     }
     queryDecoratedElement('#manage-in-drive', Command)
         .canExecuteChange(element);
@@ -116,11 +116,11 @@
     const saveForOfflineAction =
         // @ts-ignore: error TS7053: Element implicitly has an 'any' type
         // because expression of type 'string' can't be used to index type '{}'.
-        remainingActions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
+        remainingActions[CommonActionId.SAVE_FOR_OFFLINE];
     const offlineNotNecessaryAction =
         // @ts-ignore: error TS7053: Element implicitly has an 'any' type
         // because expression of type 'string' can't be used to index type '{}'.
-        remainingActions[ActionsModel.CommonActionId.OFFLINE_NOT_NECESSARY];
+        remainingActions[CommonActionId.OFFLINE_NOT_NECESSARY];
     if (saveForOfflineAction || offlineNotNecessaryAction) {
       const menuItem = this.addMenuItem_({});
       // @ts-ignore: error TS2339: Property 'command' does not exist on type
@@ -130,13 +130,12 @@
       if (saveForOfflineAction) {
         // @ts-ignore: error TS7053: Element implicitly has an 'any' type
         // because expression of type 'string' can't be used to index type '{}'.
-        delete remainingActions[ActionsModel.CommonActionId.SAVE_FOR_OFFLINE];
+        delete remainingActions[CommonActionId.SAVE_FOR_OFFLINE];
       }
       if (offlineNotNecessaryAction) {
         // @ts-ignore: error TS7053: Element implicitly has an 'any' type
         // because expression of type 'string' can't be used to index type '{}'.
-        delete remainingActions[ActionsModel.CommonActionId
-                                    .OFFLINE_NOT_NECESSARY];
+        delete remainingActions[CommonActionId.OFFLINE_NOT_NECESSARY];
       }
     }
     queryDecoratedElement('#toggle-pinned', Command).canExecuteChange(element);
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni
index 5eaf9ba..5daa93c2 100644
--- a/ui/file_manager/file_names.gni
+++ b/ui/file_manager/file_names.gni
@@ -49,8 +49,6 @@
   "file_manager/externs/ts/store.js",
 
   # Files app Foreground:
-  "file_manager/foreground/js/actions_controller.js",
-  "file_manager/foreground/js/actions_model.js",
   "file_manager/foreground/js/android_app_list_model.js",
   "file_manager/foreground/js/app_state_controller.js",
   "file_manager/foreground/js/constants.js",
@@ -76,7 +74,6 @@
   "file_manager/foreground/js/list_thumbnail_loader.js",
   "file_manager/foreground/js/metadata_update_controller.js",
   "file_manager/foreground/js/metrics_start.js",
-  "file_manager/foreground/js/mock_actions_model.js",
   "file_manager/foreground/js/mock_directory_model.js",
   "file_manager/foreground/js/mock_folder_shortcut_data_model.js",
   "file_manager/foreground/js/mock_navigation_list_model.js",
@@ -95,7 +92,6 @@
 
   # Metadata:
   "file_manager/foreground/js/metadata/external_metadata_provider.js",
-  "file_manager/foreground/js/metadata/function_sequence.js",
   "file_manager/foreground/js/metadata/id3_parser.js",
   "file_manager/foreground/js/metadata/image_parsers.js",
   "file_manager/foreground/js/metadata/metadata_cache_item.js",
@@ -104,7 +100,6 @@
   "file_manager/foreground/js/metadata/mock_metadata.js",
   "file_manager/foreground/js/metadata/mpeg_parser.js",
   "file_manager/foreground/js/metadata/multi_metadata_provider.js",
-  "file_manager/foreground/js/metadata/thumbnail_model.js",
 
   # Files app UI:
   "file_manager/foreground/js/ui/a11y_announce.js",
@@ -293,6 +288,8 @@
   # Don't remove this.
   # These lines will be removed at the end of the TS migration.
   # Background.
+  "file_manager/foreground/js/actions_model.ts",
+  "file_manager/foreground/js/actions_controller.ts",
   "file_manager/background/js/app_window_wrapper.ts",
   "file_manager/background/js/crostini.ts",
   "file_manager/background/js/drive_sync_handler.ts",
@@ -301,6 +298,7 @@
   "file_manager/background/js/launcher.ts",
   "file_manager/foreground/js/main_window_component.ts",
   "file_manager/background/js/metrics_start.ts",
+  "file_manager/foreground/js/mock_actions_model.ts",
   "file_manager/background/js/mock_crostini.ts",
   "file_manager/background/js/mock_progress_center.ts",
   "file_manager/background/js/mock_volume_manager.ts",
@@ -364,11 +362,13 @@
   "file_manager/foreground/js/metadata/exif_parser.ts",
   "file_manager/foreground/js/metadata/file_system_metadata_provider.ts",
   "file_manager/foreground/js/metadata/function_parallel.ts",
+  "file_manager/foreground/js/metadata/function_sequence.ts",
   "file_manager/foreground/js/metadata/metadata_item.ts",
   "file_manager/foreground/js/metadata/metadata_model.ts",
   "file_manager/foreground/js/metadata/metadata_parser.ts",
   "file_manager/foreground/js/metadata/metadata_provider.ts",
   "file_manager/foreground/js/metadata/metadata_request.ts",
+  "file_manager/foreground/js/metadata/thumbnail_model.ts",
 ]
 
 # Isolate Polymer TS to avoid sending them to Closure via the rule `js_from_ts`.
@@ -509,6 +509,7 @@
   "file_manager/foreground/elements/files_tooltip_unittest.ts",
   "file_manager/foreground/elements/files_toast_unittest.ts",
   "file_manager/foreground/elements/files_xf_elements_unittest.ts",
+  "file_manager/foreground/js/actions_model_unittest.ts",
   "file_manager/foreground/js/banner_controller_unittest.ts",
   "file_manager/foreground/js/banner_util_unittest.ts",
   "file_manager/foreground/js/directory_contents_unittest.ts",
@@ -547,6 +548,7 @@
   "file_manager/foreground/js/metadata/exif_parser_unittest.ts",
   "file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.ts",
   "file_manager/foreground/js/metadata/metadata_model_unittest.ts",
+  "file_manager/foreground/js/metadata/thumbnail_model_unittest.ts",
 ]
 
 ts_generated_templates = []
@@ -612,7 +614,6 @@
 
   # Foreground:
   "file_manager/foreground/js/metadata/metadata_cache_item_unittest.js",
-  "file_manager/foreground/js/metadata/thumbnail_model_unittest.js",
   "file_manager/foreground/js/metadata/external_metadata_provider_unittest.js",
   "file_manager/foreground/js/metadata/metadata_cache_set_unittest.js",
   "file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js",
@@ -624,7 +625,6 @@
   "file_manager/foreground/js/list_thumbnail_loader_unittest.js",
   "file_manager/foreground/js/file_type_filters_controller_unittest.js",
   "file_manager/foreground/js/path_component_unittest.js",
-  "file_manager/foreground/js/actions_model_unittest.js",
   "file_manager/foreground/js/ui/file_manager_dialog_base_unittest.js",
   "file_manager/foreground/js/ui/actions_submenu_unittest.js",
   "file_manager/foreground/js/ui/command_unittest.js",
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree.js b/ui/file_manager/integration_tests/file_manager/directory_tree.js
index 6071be1..a9cce18 100644
--- a/ui/file_manager/integration_tests/file_manager/directory_tree.js
+++ b/ui/file_manager/integration_tests/file_manager/directory_tree.js
@@ -542,3 +542,44 @@
   await directoryTree.waitForItemToHaveChildrenByLabel(
       'middle-child-folder', /* hasChildren= */ true);
 };
+
+/**
+ * When drag a file and hover over the directory tree item, the item should be
+ * expanded and selected, current directory should also change to that folder.
+ */
+testcase.directoryTreeExpandAndSelectedOnDragMove = async () => {
+  // Create a file and a folder.
+  const entries = [
+    // file to drag.
+    ENTRIES.hello,
+    // folder to drag over and drop.
+    createFolderTestEntry('aaa'),
+  ];
+
+  // Open Files app.
+  const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS, entries, []);
+  const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall);
+  await directoryTree.waitForSelectedItemByLabel('Downloads');
+
+  // File to drag.
+  const source =
+      `#file-list li[file-name="${ENTRIES.hello.nameText}"] .entry-name`;
+
+  // Drag file to the Downloads folder without drop.
+  const finishDragToDownloads = await directoryTree.dragFilesToItemByLabel(
+      source, 'Downloads', /* skipDrop= */ true);
+
+  // Downloads folder should be expanded.
+  await directoryTree.waitForItemToExpandByLabel('Downloads');
+
+  // Send dragleave on the Downloads folder and move the drag to aaa folder.
+  await finishDragToDownloads(
+      directoryTree.itemSelectorByLabel('Downloads'), /* dragleave= */ true);
+  await directoryTree.dragFilesToItemByLabel(
+      source, 'aaa', /* skipDrop= */ true);
+
+  // aaa folder should be expanded and selected.
+  await remoteCall.waitUntilCurrentDirectoryIsChanged(
+      appId, '/My files/Downloads/aaa');
+  await directoryTree.waitForSelectedItemByLabel('aaa');
+};
diff --git a/ui/file_manager/integration_tests/file_manager/page_objects/directory_tree.js b/ui/file_manager/integration_tests/file_manager/page_objects/directory_tree.js
index ab19a6a..b5a2f90 100644
--- a/ui/file_manager/integration_tests/file_manager/page_objects/directory_tree.js
+++ b/ui/file_manager/integration_tests/file_manager/page_objects/directory_tree.js
@@ -91,6 +91,16 @@
   }
 
   /**
+   * Returns the selector by the tree label.
+   *
+   * @param {string} label Label of the tree item
+   * @return {string}
+   */
+  itemSelectorByLabel(label) {
+    return this.selectors_.itemByLabel(label);
+  }
+
+  /**
    * Wait for the selected(aka "active" in the old tree implementation) tree
    * item with the label.
    *
@@ -103,6 +113,18 @@
   }
 
   /**
+   * Wait for the selected(aka "active" in the old tree implementation) tree
+   * item with the label to be lost.
+   *
+   * @param {string} label Label of the tree item.
+   * @return {!Promise<void>}
+   */
+  async waitForSelectedItemLostByLabel(label) {
+    await this.remoteCall_.waitForElementLost(
+        this.appId_, this.selectors_.itemByLabel(label, {selected: true}));
+  }
+
+  /**
    * Wait for the tree item with the label to have focused (aka "selected" in
    * the old tree implementation) state.
    *
diff --git a/ui/file_manager/integration_tests/file_manager/search.js b/ui/file_manager/integration_tests/file_manager/search.js
index 4c5ca817..1945bf0e 100644
--- a/ui/file_manager/integration_tests/file_manager/search.js
+++ b/ui/file_manager/integration_tests/file_manager/search.js
@@ -8,7 +8,7 @@
 
 import {mountCrostini, remoteCall, setupAndWaitUntilReady} from './background.js';
 import {DirectoryTreePageObject} from './page_objects/directory_tree.js';
-import {BASIC_ANDROID_ENTRY_SET, BASIC_DRIVE_ENTRY_SET, BASIC_LOCAL_ENTRY_SET, COMPLEX_DOCUMENTS_PROVIDER_ENTRY_SET, NESTED_ENTRY_SET} from './test_data.js';
+import {BASIC_ANDROID_ENTRY_SET, BASIC_DRIVE_ENTRY_SET, BASIC_LOCAL_ENTRY_SET, COMPLEX_DOCUMENTS_PROVIDER_ENTRY_SET, COMPUTERS_ENTRY_SET, NESTED_ENTRY_SET} from './test_data.js';
 
 /**
  * @param {string} appId The ID that identifies the files app.
@@ -326,10 +326,10 @@
     nestedHello,
   ]));
 
-  // Click the second button, which is This Chromebook.
+  // Click the second button, which is My files.
   chrome.test.assertTrue(
       !!await remoteCall.selectSearchOption(appId, 'location', 2),
-      'Failed to click "This Chromebook" location selector');
+      'Failed to click "My files" location selector');
 
   // Expect all hello files to be found.
   await remoteCall.waitForFiles(appId, TestEntryInfo.getExpectedRows([
@@ -1174,3 +1174,101 @@
   chrome.test.assertEq(
       'Google Drive', await getSelectedOptionText(appId, 'location'));
 };
+
+/*
+ * Checks that search with non-current folder in Downloads should unselect the
+ * current directory item in the tree.
+ */
+testcase.unselectCurrentDirectoryInTreeOnSearchInDownloads = async () => {
+  // Setup default file set within Downloads.
+  const appId = await setupAndWaitUntilReady(RootPath.DOWNLOADS);
+  const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall);
+  await directoryTree.waitForSelectedItemByLabel('Downloads');
+
+  // Search "hello".
+  await remoteCall.typeSearchText(appId, 'hello');
+  await remoteCall.waitForFiles(
+      appId, TestEntryInfo.getExpectedRows([ENTRIES.hello]));
+  chrome.test.assertEq(
+      'Downloads', await getSelectedOptionText(appId, 'location'));
+  // Expect the Downloads folder is still selected.
+  await directoryTree.waitForSelectedItemByLabel('Downloads');
+
+  // Change location to "My files".
+  chrome.test.assertTrue(
+      !!await remoteCall.selectSearchOption(appId, 'location', 2),
+      'Failed to click "My files" location selector');
+  // Expect the Downloads folder to be unselected.
+  await directoryTree.waitForSelectedItemLostByLabel('Downloads');
+
+  // Change location back to "Downloads".
+  chrome.test.assertTrue(
+      !!await remoteCall.selectSearchOption(appId, 'location', 3),
+      'Failed to click "Downloads" location selector');
+  // Expect the Downloads folder to be selected again.
+  await directoryTree.waitForSelectedItemByLabel('Downloads');
+
+  if (directoryTree.isNewTree) {
+    // Change location to "My files" and click the Downloads.
+    chrome.test.assertTrue(
+        !!await remoteCall.selectSearchOption(appId, 'location', 2),
+        'Failed to click "My files" location selector');
+    await directoryTree.waitForSelectedItemLostByLabel('Downloads');
+    await directoryTree.selectItemByLabel('Downloads');
+    // Expect the search will be cleared.
+    await remoteCall.waitForElement(appId, '#search-wrapper[collapsed]');
+  }
+};
+
+/**
+ * Checks that search with non-root folder in Drive should unselect the current
+ * directory item in the tree.
+ */
+testcase.unselectCurrentDirectoryInTreeOnSearchInDrive = async () => {
+  // Setup Drive with Computers files.
+  const appId =
+      await setupAndWaitUntilReady(RootPath.DRIVE, [], COMPUTERS_ENTRY_SET);
+  const directoryTree = await DirectoryTreePageObject.create(appId, remoteCall);
+  await directoryTree.waitForSelectedItemByLabel('My Drive');
+
+  // Search "txt", both My Drive and Computers folder will be searched.
+  await remoteCall.typeSearchText(appId, 'txt');
+  await remoteCall.waitForFiles(appId, TestEntryInfo.getExpectedRows([
+    ENTRIES.hello,
+    ENTRIES.computerAFile,
+  ]));
+  chrome.test.assertEq(
+      'Google Drive', await getSelectedOptionText(appId, 'location'));
+  if (directoryTree.isNewTree) {
+    // Expect the My Drive folder is still selected.
+    await directoryTree.waitForSelectedItemByLabel('My Drive');
+  }
+
+  // Change location to "Everywhere".
+  chrome.test.assertTrue(
+      !!await remoteCall.selectSearchOption(appId, 'location', 1),
+      'Failed to click "Everywhere" location selector');
+  // Expect the My Drive folder to be unselected.
+  await directoryTree.waitForSelectedItemLostByLabel('My Drive');
+
+  // Change location back to "Google Drive".
+  chrome.test.assertTrue(
+      !!await remoteCall.selectSearchOption(appId, 'location', 2),
+      'Failed to click "Google Drive" location selector');
+  if (directoryTree.isNewTree) {
+    // Expect the My Drive folder to be selected again.
+    await directoryTree.waitForSelectedItemByLabel('My Drive');
+  }
+
+  if (directoryTree.isNewTree) {
+    // Change location to "Everywhere" and click the My Drive.
+    chrome.test.assertTrue(
+        !!await remoteCall.selectSearchOption(appId, 'location', 1),
+        'Failed to click "Everywhere" location selector');
+    await directoryTree.waitForSelectedItemLostByLabel('My Drive');
+    await directoryTree.selectItemByLabel('My Drive');
+
+    // Expect the search will be cleared.
+    await remoteCall.waitForElement(appId, '#search-wrapper[collapsed]');
+  }
+};
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc
index 14603f0..2aed455 100644
--- a/ui/message_center/views/notification_header_view.cc
+++ b/ui/message_center/views/notification_header_view.cc
@@ -254,7 +254,7 @@
 }
 
 void NotificationHeaderView::SetAppIcon(const gfx::ImageSkia& img) {
-  app_icon_view_->SetImage(img);
+  app_icon_view_->SetImage(ui::ImageModel::FromImageSkia(img));
   using_default_app_icon_ = false;
 }
 
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index 962b132..da0dacd6 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -319,12 +319,11 @@
 
 void BubbleFrameView::UpdateWindowIcon() {
   DCHECK(GetWidget());
-  gfx::ImageSkia image;
+  ui::ImageModel image;
   if (GetWidget()->widget_delegate()->ShouldShowWindowIcon()) {
-    image = GetWidget()->widget_delegate()->GetWindowIcon().Rasterize(
-        GetColorProvider());
+    image = GetWidget()->widget_delegate()->GetWindowIcon();
   }
-  title_icon_->SetImage(&image);
+  title_icon_->SetImage(image);
 }
 
 void BubbleFrameView::UpdateWindowTitle() {
@@ -422,11 +421,11 @@
 
     const int border_radius = LayoutProvider::Get()->GetCornerRadiusMetric(
         Emphasis::kHigh, gfx::Size());
-    main_image_->SetImage(
+    main_image_->SetImage(ui::ImageModel::FromImageSkia(
         gfx::ImageSkiaOperations::CreateCroppedCenteredRoundRectImage(
             gfx::Size(main_image_dimension, main_image_dimension),
             border_radius - 2 * kBorderStrokeThickness,
-            model.GetImage().AsImageSkia()));
+            model.GetImage().AsImageSkia())));
     main_image_->SetBorder(views::CreateRoundedRectBorder(
         kBorderStrokeThickness, border_radius, image_insets,
         GetColorProvider()
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index 30a4011..0d31448 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -82,10 +82,6 @@
   return GetImageModel(for_state).Rasterize(GetColorProvider());
 }
 
-void LabelButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
-  SetImageModel(for_state, ui::ImageModel::FromImageSkia(image));
-}
-
 const ui::ImageModel& LabelButton::GetImageModel(ButtonState for_state) const {
   return button_state_image_models_[for_state];
 }
@@ -491,7 +487,7 @@
 
 void LabelButton::UpdateImage() {
   if (GetWidget())
-    image_->SetImage(GetImage(GetVisualState()));
+    image_->SetImage(ui::ImageModel::FromImageSkia(GetImage(GetVisualState())));
 }
 
 void LabelButton::AddLayerToRegion(ui::Layer* new_layer,
diff --git a/ui/views/controls/button/label_button.h b/ui/views/controls/button/label_button.h
index bd646d55..bc53de04b 100644
--- a/ui/views/controls/button/label_button.h
+++ b/ui/views/controls/button/label_button.h
@@ -48,8 +48,6 @@
   // Gets or sets the image shown for the specified button state.
   // GetImage returns the image for STATE_NORMAL if the state's image is empty.
   virtual gfx::ImageSkia GetImage(ButtonState for_state) const;
-  // TODO(http://crbug.com/1100034) prefer SetImageModel over SetImage().
-  void SetImage(ButtonState for_state, const gfx::ImageSkia& image);
 
   const ui::ImageModel& GetImageModel(ButtonState for_state) const;
   virtual void SetImageModel(ButtonState for_state,
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc
index bd4fa3b..30de4e6 100644
--- a/ui/views/controls/button/label_button_unittest.cc
+++ b/ui/views/controls/button/label_button_unittest.cc
@@ -237,7 +237,9 @@
     button()->SetMultiLine(is_multiline);
     for (bool set_image : {false, true}) {
       if (set_image)
-        button()->SetImage(Button::STATE_NORMAL, CreateTestImage(16, 16));
+        button()->SetImageModel(
+            Button::STATE_NORMAL,
+            ui::ImageModel::FromImageSkia(CreateTestImage(16, 16)));
 
       bool preferred_size_is_sometimes_narrower_than_max = false;
       bool preferred_height_shrinks_as_max_width_grows = false;
@@ -413,27 +415,32 @@
 
   EXPECT_LT(button()->GetPreferredSize().width(), small_size);
   EXPECT_LT(button()->GetPreferredSize().height(), small_size);
-  button()->SetImage(Button::STATE_NORMAL, small_image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(small_image));
   EXPECT_GT(button()->GetPreferredSize().width(), small_size);
   EXPECT_GT(button()->GetPreferredSize().height(), small_size);
   EXPECT_LT(button()->GetPreferredSize().width(), large_size);
   EXPECT_LT(button()->GetPreferredSize().height(), large_size);
-  button()->SetImage(Button::STATE_NORMAL, large_image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(large_image));
   EXPECT_GT(button()->GetPreferredSize().width(), large_size);
   EXPECT_GT(button()->GetPreferredSize().height(), large_size);
-  button()->SetImage(Button::STATE_NORMAL, small_image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(small_image));
   EXPECT_GT(button()->GetPreferredSize().width(), small_size);
   EXPECT_GT(button()->GetPreferredSize().height(), small_size);
   EXPECT_LT(button()->GetPreferredSize().width(), large_size);
   EXPECT_LT(button()->GetPreferredSize().height(), large_size);
 
   // Clamp the size to a maximum value.
-  button()->SetImage(Button::STATE_NORMAL, large_image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(large_image));
   button()->SetMaxSize(gfx::Size(large_size, 1));
   EXPECT_EQ(button()->GetPreferredSize(), gfx::Size(large_size, 1));
 
   // Clamp the size to a minimum value.
-  button()->SetImage(Button::STATE_NORMAL, small_image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(small_image));
   button()->SetMaxSize(gfx::Size());
   button()->SetMinSize(gfx::Size(large_size, large_size));
   EXPECT_EQ(button()->GetPreferredSize(), gfx::Size(large_size, large_size));
@@ -450,7 +457,8 @@
 
   const int image_size = 16;
   const gfx::ImageSkia image = CreateTestImage(image_size, image_size);
-  button()->SetImage(Button::STATE_NORMAL, image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(image));
 
   button()->SetBoundsRect(gfx::Rect(button()->GetPreferredSize()));
   views::test::RunScheduledLayout(button());
@@ -481,7 +489,8 @@
   EXPECT_GT(button()->GetPreferredSize().height(), font_list.GetHeight());
   EXPECT_LT(button()->GetPreferredSize().width(), text_width + image_size);
   EXPECT_LT(button()->GetPreferredSize().height(), image_size);
-  button()->SetImage(Button::STATE_NORMAL, image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(image));
   EXPECT_GT(button()->GetPreferredSize().width(), text_width + image_size);
   EXPECT_GT(button()->GetPreferredSize().height(), image_size);
 
@@ -511,13 +520,14 @@
   EXPECT_LT(button()->GetPreferredSize().width(), text_width + image_size);
   EXPECT_GT(button()->GetPreferredSize().width(), image_size);
   EXPECT_GT(button()->GetPreferredSize().height(), image_size);
-  button()->SetImage(Button::STATE_NORMAL, gfx::ImageSkia());
+  button()->SetImageModel(Button::STATE_NORMAL, ui::ImageModel());
   EXPECT_LT(button()->GetPreferredSize().width(), image_size);
   EXPECT_LT(button()->GetPreferredSize().height(), image_size);
 
   // Clamp the size to a minimum value.
   button()->SetText(text);
-  button()->SetImage(Button::STATE_NORMAL, image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(image));
   button()->SetMinSize(
       gfx::Size((text_width + image_size) * 2, image_size * 2));
   EXPECT_EQ(button()->GetPreferredSize().width(),
@@ -545,7 +555,8 @@
   const gfx::ImageSkia image = CreateTestImage(image_size, image_size);
   ASSERT_EQ(font_list.GetHeight(), image.width());
 
-  button()->SetImage(Button::STATE_NORMAL, image);
+  button()->SetImageModel(Button::STATE_NORMAL,
+                          ui::ImageModel::FromImageSkia(image));
   button()->SetImageCentered(false);
   button()->SetMaxSize(
       gfx::Size(image.width() + image_spacing + text_wrap_width, 0));
@@ -589,7 +600,8 @@
     SCOPED_TRACE(testing::Message() << "Image Size: " << image_size);
     // Set image and reset monotonic min size for every test iteration.
     const gfx::ImageSkia image = CreateTestImage(image_size, image_size);
-    button()->SetImage(Button::STATE_NORMAL, image);
+    button()->SetImageModel(Button::STATE_NORMAL,
+                            ui::ImageModel::FromImageSkia(image));
 
     const gfx::Size preferred_button_size = button()->GetPreferredSize();
 
@@ -681,7 +693,8 @@
 
 TEST_F(LabelButtonTest, ChangeLabelImageSpacing) {
   button()->SetText(u"abc");
-  button()->SetImage(Button::STATE_NORMAL, CreateTestImage(50, 50));
+  button()->SetImageModel(Button::STATE_NORMAL, ui::ImageModel::FromImageSkia(
+                                                    CreateTestImage(50, 50)));
 
   const int kOriginalSpacing = 5;
   button()->SetImageLabelSpacing(kOriginalSpacing);
@@ -769,8 +782,9 @@
 
   const gfx::FontList font_list = button()->label()->font_list();
   const int image_size = font_list.GetHeight();
-  button()->SetImage(Button::STATE_NORMAL,
-                     CreateTestImage(image_size, image_size));
+  button()->SetImageModel(
+      Button::STATE_NORMAL,
+      ui::ImageModel::FromImageSkia(CreateTestImage(image_size, image_size)));
 
   button()->SetBoundsRect(gfx::Rect(button()->GetPreferredSize()));
   // The border size + the content height is more than button's preferred size.
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index f04776b..f556d3d55 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -1418,17 +1418,17 @@
   last_paint_as_selected_ = paint_as_selected;
   const Colors colors = CalculateColors(paint_as_selected);
   if (submenu_arrow_image_view_) {
-    submenu_arrow_image_view_->SetImage(
-        gfx::CreateVectorIcon(features::IsChromeRefresh2023()
-                                  ? vector_icons::kSubmenuArrowChromeRefreshIcon
-                                  : vector_icons::kSubmenuArrowIcon,
-                              colors.icon_color));
+    submenu_arrow_image_view_->SetImage(ui::ImageModel::FromVectorIcon(
+        features::IsChromeRefresh2023()
+            ? vector_icons::kSubmenuArrowChromeRefreshIcon
+            : vector_icons::kSubmenuArrowIcon,
+        colors.icon_color));
   }
   MenuDelegate* delegate = GetDelegate();
   if (type_ == Type::kCheckbox && delegate &&
       delegate->IsItemChecked(GetCommand())) {
     radio_check_image_view_->SetImage(
-        gfx::CreateVectorIcon(kMenuCheckIcon, colors.icon_color));
+        ui::ImageModel::FromVectorIcon(kMenuCheckIcon, colors.icon_color));
   } else if (type_ == Type::kRadio) {
     const bool toggled = delegate && delegate->IsItemChecked(GetCommand());
     const gfx::VectorIcon& radio_icon =
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc
index 06dd86a..54330ce4 100644
--- a/ui/views/controls/table/table_view.cc
+++ b/ui/views/controls/table/table_view.cc
@@ -1347,15 +1347,20 @@
 }
 
 void TableView::SetActiveVisibleColumnIndex(absl::optional<size_t> index) {
-  if (active_visible_column_index_ == index)
+  if (active_visible_column_index_ == index) {
     return;
+  }
   active_visible_column_index_ = index;
-
-  if (selection_model_.active().has_value() &&
-      active_visible_column_index_.has_value()) {
-    ScrollRectToVisible(
-        GetCellBounds(ModelToView(selection_model_.active().value()),
-                      active_visible_column_index_.value()));
+  if (active_visible_column_index_.has_value()) {
+    if (selection_model_.active().has_value()) {
+      ScrollRectToVisible(
+          GetCellBounds(ModelToView(selection_model_.active().value()),
+                        active_visible_column_index_.value()));
+    } else if (header_row_is_active()) {
+      const TableView::VisibleColumn& column =
+          GetVisibleColumn(active_visible_column_index_.value());
+      ScrollRectToVisible(gfx::Rect(column.x, 0, column.width, height()));
+    }
   }
 
   UpdateFocusRings();
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc
index fcf2ceaf..4ffb9c8d 100644
--- a/ui/views/controls/table/table_view_unittest.cc
+++ b/ui/views/controls/table/table_view_unittest.cc
@@ -470,6 +470,7 @@
     }
     table_ = table.get();
     auto scroll_view = TableView::CreateScrollViewWithTable(std::move(table));
+    scroll_view_ = scroll_view.get();
     scroll_view->SetBounds(0, 0, 10000, 10000);
     helper_ = std::make_unique<TableViewTestHelper>(table_);
 
@@ -486,6 +487,7 @@
 
   void TearDown() override {
     table_ = nullptr;
+    scroll_view_ = nullptr;
     helper_.reset();
     widget_.reset();
     ViewsTestBase::TearDown();
@@ -610,6 +612,7 @@
 
   // Owned by the scroll view owned by `widget_`.
   raw_ptr<TableView> table_ = nullptr;
+  raw_ptr<ScrollView> scroll_view_ = nullptr;
 
   std::unique_ptr<TableViewTestHelper> helper_;
 
@@ -853,8 +856,9 @@
 // Verifies resizing a column works with the keyboard.
 // The resize keyboard amount is 5 pixels.
 TEST_P(TableViewTest, ResizeViaKeyboard) {
-  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell)
-    return;
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
 
   table_->RequestFocus();
   const int x = table_->GetVisibleColumn(0).width;
@@ -1056,8 +1060,9 @@
 // Verifies that pressing the space bar when a particular visible column is
 // active will sort by that column.
 TEST_P(TableViewTest, SortOnSpaceBar) {
-  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell)
-    return;
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
 
   table_->RequestFocus();
   ASSERT_TRUE(table_->sort_descriptors().empty());
@@ -1634,8 +1639,9 @@
 
 // Verifies left/right correctly navigate through visible columns.
 TEST_P(TableViewTest, KeyLeftRight) {
-  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell)
-    return;
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
 
   TableViewObserverImpl observer;
   table_->set_observer(&observer);
@@ -1731,6 +1737,95 @@
   table_->set_observer(nullptr);
 }
 
+// Verify table view that the left/right navigation scrolls the visible rect
+// correctly.
+TEST_P(TableViewTest, KeyLeftRightScrollRectToVisibleInTableView) {
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
+
+  table_->RequestFocus();
+  EXPECT_EQ(2u, helper_->visible_col_count());
+  // Initially no active visible column.
+  EXPECT_FALSE(helper_->GetActiveVisibleColumnIndex().has_value());
+  EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible());
+  scroll_view_->SetBounds(0, 0, 800, 800);
+  // Set the column width to make the horizontal scroll bar visible.
+  constexpr int kColumn0Width = 500;
+  constexpr int kColumn1Width = 1000;
+  table_->SetVisibleColumnWidth(0, kColumn0Width);
+  table_->SetVisibleColumnWidth(1, kColumn1Width);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(table_->GetVisibleColumn(0).width, kColumn0Width);
+  EXPECT_EQ(table_->GetVisibleColumn(1).width, kColumn1Width);
+  EXPECT_TRUE(scroll_view_->horizontal_scroll_bar()->GetVisible());
+
+  gfx::Rect visible_bounds = table_->GetVisibleBounds();
+  PressKey(ui::VKEY_RIGHT);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(0u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(visible_bounds, table_->GetVisibleBounds());
+
+  PressKey(ui::VKEY_RIGHT);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(1u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(table_->GetVisibleBounds(),
+            gfx::Rect(kColumn0Width, visible_bounds.y(), visible_bounds.width(),
+                      visible_bounds.height()));
+
+  PressKey(ui::VKEY_LEFT);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(0u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(visible_bounds, table_->GetVisibleBounds());
+}
+
+// Verify table header that the left/right navigation scrolls the visible rect
+// correctly.
+TEST_P(TableViewTest, KeyLeftRightScrollRectToVisibleInTableHeader) {
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
+
+  table_->RequestFocus();
+  EXPECT_EQ(2u, helper_->visible_col_count());
+  // Initially no active visible column.
+  EXPECT_FALSE(helper_->GetActiveVisibleColumnIndex().has_value());
+  EXPECT_FALSE(scroll_view_->horizontal_scroll_bar()->GetVisible());
+  scroll_view_->SetBounds(0, 0, 800, 800);
+  // Set the column width to make the horizontal scroll bar visible.
+  constexpr int kColumn0Width = 500;
+  constexpr int kColumn1Width = 1000;
+  table_->SetVisibleColumnWidth(0, kColumn0Width);
+  table_->SetVisibleColumnWidth(1, kColumn1Width);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(table_->GetVisibleColumn(0).width, kColumn0Width);
+  EXPECT_EQ(table_->GetVisibleColumn(1).width, kColumn1Width);
+  EXPECT_TRUE(scroll_view_->horizontal_scroll_bar()->GetVisible());
+  gfx::Rect visible_bounds = table_->GetVisibleBounds();
+
+  // Navigate to the table header
+  PressKey(ui::VKEY_RIGHT);
+  EXPECT_FALSE(table_->header_row_is_active());
+  PressKey(ui::VKEY_UP);
+  EXPECT_TRUE(table_->header_row_is_active());
+
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(0u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(visible_bounds, table_->GetVisibleBounds());
+
+  PressKey(ui::VKEY_RIGHT);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(1u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(table_->GetVisibleBounds(),
+            gfx::Rect(kColumn0Width, visible_bounds.y(), visible_bounds.width(),
+                      visible_bounds.height()));
+
+  PressKey(ui::VKEY_LEFT);
+  test::RunScheduledLayout(scroll_view_);
+  EXPECT_EQ(0u, helper_->GetActiveVisibleColumnIndex());
+  EXPECT_EQ(visible_bounds, table_->GetVisibleBounds());
+}
+
 // Verifies home/end do the right thing.
 TEST_P(TableViewTest, HomeEnd) {
   // Configure the grouper so that there are three groups:
@@ -2048,8 +2143,9 @@
 // Ensure that the TableView's header columns are keyboard accessible.
 // Tests for crbug.com/1189851.
 TEST_P(TableViewTest, TableHeaderColumnAccessibleViewsFocusable) {
-  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell)
-    return;
+  if (!PlatformStyle::kTableViewSupportsKeyboardNavigationByCell) {
+    GTEST_SKIP() << "platform doesn't support table keyboard navigation";
+  }
 
   ASSERT_NE(nullptr, helper_->header());
   table_->RequestFocus();
diff --git a/ui/views/examples/vector_example.cc b/ui/views/examples/vector_example.cc
index 2ff8242..9704806 100644
--- a/ui/views/examples/vector_example.cc
+++ b/ui/views/examples/vector_example.cc
@@ -224,8 +224,9 @@
 
         ImageView* icon_view =
             image_view_container_->AddChildView(std::make_unique<ImageView>());
-        icon_view->SetImage(gfx::CreateVectorIconFromSource(
-            CleanUpContents(file_content), size_, color_));
+        icon_view->SetImage(
+            ui::ImageModel::FromImageSkia(gfx::CreateVectorIconFromSource(
+                CleanUpContents(file_content), size_, color_)));
         icon_view->SetTooltipText(file.BaseName().AsUTF16Unsafe());
         file = file_iter.Next();
       }
@@ -235,8 +236,8 @@
 
   void Update() {
     if (!contents_.empty() && image_view_ != nullptr) {
-      image_view_->SetImage(
-          gfx::CreateVectorIconFromSource(contents_, size_, color_));
+      image_view_->SetImage(ui::ImageModel::FromImageSkia(
+          gfx::CreateVectorIconFromSource(contents_, size_, color_)));
     }
     InvalidateLayout();
   }
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
index a30c2f13..2e69d7e0 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
@@ -73,7 +73,7 @@
 
   std::unique_ptr<views::ImageView> image_view =
       std::make_unique<views::ImageView>();
-  image_view->SetImage(image);
+  image_view->SetImage(ui::ImageModel::FromImageSkia(image));
   widget->SetContentsView(std::move(image_view));
   widget->Show();
   widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);