diff --git a/DEPS b/DEPS
index 1da0f55f..b8a0d30 100644
--- a/DEPS
+++ b/DEPS
@@ -245,15 +245,15 @@
   # 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': 'fdbc37f4d82bc38bef536b042a846823f3f96fd5',
+  'skia_revision': '5dee0a27e0d2306541f4a6214b75c8f405e99ac4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '8280a12b2bdf7c22235d44f27998d6de3b47a3bd',
+  'v8_revision': '612603ba2fc6194ab9c9b142a123ff68e236be03',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'acd8fc76b212c1e8e8cc6c68c8be1de4a3878029',
+  'angle_revision': 'b90bcb9c820844608e6d57668b4712c476425e28',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -292,7 +292,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': 'bf9b1ef90564987856a42461147435f143e9e7cd',
+  'freetype_revision': 'a25e85ed95dc855e42e6bb55138e27d362c5ea1e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -320,7 +320,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': '0f04721d0b29c31fc2f003107001fd4cf9c7d3db',
+  'devtools_frontend_revision': 'c880d6528b4e3abc72e179b047ea68aa3324f08b',
   # 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.
@@ -360,7 +360,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': '51721746d9ed6479fc0ee9cd22f3af0436de53da',
+  'dawn_revision': '500411b77e88d80a4d38c7d816400d8f078b9ee8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -722,7 +722,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/linux-amd64',
-          'version': '2f4xgLZNEF_vLqjVgHGILrXCgRxjQQ_kVizKzGWhZqEC',
+          'version': 'vA_jsPe65KdcCsmQ4fg10mYT8K0SPDwBEZ-x0b-2DnMC',
         },
       ],
       'dep_type': 'cipd',
@@ -733,7 +733,7 @@
       'packages': [
         {
           'package': 'chromium/rts/model/mac-amd64',
-          'version': 'JSxqGgZySiUIwnoTmlR0pp2v53jYH7HlNQU0uJmJ0ZkC',
+          'version': 's7qu7MJuaO1dxFvnILm-lgdafQvYtB5ldFO8l4PqVPsC',
         },
       ],
       'dep_type': 'cipd',
@@ -1648,7 +1648,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'fca7b339442bd70c5dc49bb33ee7f9466b560a97',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '651586c4e1b97a4615b8522a3a3d56bb4376e72f',
+    Var('webrtc_git') + '/src.git' + '@' + 'c58adb753a286fad87c0470e04c2a12766927e48',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1730,7 +1730,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1e8249e253dacb870c376b6100cf409f32180de6',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c608bd0c2766732c761ef2f2d5e1d81e968d982c',
     'condition': 'checkout_src_internal',
   },
 
@@ -1782,7 +1782,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'sNz5xKgOP8jR2UzmAGi4aDvNxnBK8FIyABM2ejNOGlgC',
+        'version': 'Vt7JWDElraHtItHlW1gnrXKuTV4wZ0ZwvNaUb6ZBVFcC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index e0abbff8..d1cc6fa 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -2403,7 +2403,6 @@
     'chromeos_lkgm': ['achuith+watch@chromium.org',
                       'bpastene+watch@chromium.org'],
     'chromeos_login': ['alemate+watch@chromium.org',
-                       'rsorokin+watch@chromium.org',
                        'tbarzic+watch@chromium.org'],
     'chromeos_media_app': ['cros-essential-apps-dev-watch@chromium.org'],
     'chromeos_net': ['azeemarshad+watch-network@chromium.org',
diff --git a/ash/assistant/assistant_controller_impl.cc b/ash/assistant/assistant_controller_impl.cc
index 1fce05cf..6c449b07 100644
--- a/ash/assistant/assistant_controller_impl.cc
+++ b/ash/assistant/assistant_controller_impl.cc
@@ -175,8 +175,8 @@
     // such, the browser will always be instructed to open |url| in a new
     // browser tab and Assistant UI state will be updated downstream to respect
     // |in_background|.
-    NewWindowDelegate::GetInstance()->OpenUrl(url,
-                                              /*from_user_interaction=*/true);
+    NewWindowDelegate::GetPrimary()->OpenUrl(url,
+                                             /*from_user_interaction=*/true);
   }
   NotifyUrlOpened(url, from_server);
 }
diff --git a/ash/login/LOGIN_LOCK_OWNERS b/ash/login/LOGIN_LOCK_OWNERS
index eb25357..f471097 100644
--- a/ash/login/LOGIN_LOCK_OWNERS
+++ b/ash/login/LOGIN_LOCK_OWNERS
@@ -5,3 +5,4 @@
 # Secondary (in PST)
 tbarzic@chromium.org
 xiyuan@chromium.org
+alemate@chromium.org
diff --git a/ash/quick_pair/fast_pair_handshake/fake_fast_pair_handshake.cc b/ash/quick_pair/fast_pair_handshake/fake_fast_pair_handshake.cc
index 3647c92..213068ae 100644
--- a/ash/quick_pair/fast_pair_handshake/fake_fast_pair_handshake.cc
+++ b/ash/quick_pair/fast_pair_handshake/fake_fast_pair_handshake.cc
@@ -34,8 +34,9 @@
 
 void FakeFastPairHandshake::InvokeCallback(
     absl::optional<PairFailure> failure) {
+  bool has_failure = failure.has_value();
   std::move(on_complete_callback_).Run(device_, std::move(failure));
-  completed_successfully_ = !failure.has_value();
+  completed_successfully_ = !has_failure;
 }
 
 }  // namespace quick_pair
diff --git a/ash/services/ime/public/mojom/input_method_host.mojom b/ash/services/ime/public/mojom/input_method_host.mojom
index c1eb6dc..f8ad0bd9 100644
--- a/ash/services/ime/public/mojom/input_method_host.mojom
+++ b/ash/services/ime/public/mojom/input_method_host.mojom
@@ -6,7 +6,7 @@
 // the Chromium repo. This file should be updated first, before syncing in the
 // other repos.
 
-// Next MinVersion: 6
+// Next MinVersion: 7
 
 module chromeos.ime.mojom;
 
@@ -191,21 +191,32 @@
   string? annotation@2;
 };
 
+// The highlighted candidate in a candidates window.
+// Need to be wrapped in a struct so that its nullable.
+[Stable, MinVersion=6]
+struct HighlightedCandidate {
+  uint32 index@0;
+};
+
 // The candidates window shows a list of potential candidates for the user's
 // current input. It is usually shown as a window below the current composition.
 //
-// Next ordinal: 2
+// Next ordinal: 3
 [Stable, MinVersion=2]
 struct CandidatesWindow {
   // List of candidates to be displayed. Must not be empty.
   array<Candidate> candidates@0;
 
   // The index of the candidate that should be highlighted visually.
-  uint32 highlighted_candidate@1;
+  // DEPRECATED: Use highlighted_candidate instead.
+  uint32 DEPRECATED_highlighted_candidate@1;
 
   // The text to show at the footer of the candidates window.
   // If empty, no footer is shown.
   [MinVersion=4] string? auxiliary_text@2;
+
+  // If this is null, then no candidate is highlighted.
+  [MinVersion=6] HighlightedCandidate? highlighted_candidate@3;
 };
 
 // Metrics enum for various actions that can be performed on the Korean IME.
diff --git a/ash/system/message_center/ash_notification_expand_button.cc b/ash/system/message_center/ash_notification_expand_button.cc
index 2e8cc7244f..4e374d6 100644
--- a/ash/system/message_center/ash_notification_expand_button.cc
+++ b/ash/system/message_center/ash_notification_expand_button.cc
@@ -17,12 +17,15 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/text_constants.h"
 #include "ui/views/animation/animation_builder.h"
 #include "ui/views/animation/animation_sequence_block.h"
 #include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/layout_types.h"
+#include "ui/views/view_class_properties.h"
 
 namespace ash {
 
@@ -32,18 +35,15 @@
 AshNotificationExpandButton::AshNotificationExpandButton(
     PressedCallback callback)
     : Button(std::move(callback)) {
-  auto* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>(
-      views::BoxLayout::Orientation::kHorizontal,
-      kNotificationExpandButtonInsets, kNotificationExpandButtonChildSpacing));
-  layout_manager->set_main_axis_alignment(
-      views::BoxLayout::MainAxisAlignment::kEnd);
+  SetLayoutManager(std::make_unique<views::FlexLayout>())
+      ->SetMainAxisAlignment(views::LayoutAlignment::kEnd);
 
   auto label = std::make_unique<views::Label>();
   label->SetFontList(gfx::FontList({kGoogleSansFont}, gfx::Font::NORMAL,
                                    kNotificationExpandButtonLabelFontSize,
                                    gfx::Font::Weight::MEDIUM));
-
-  label->SetPreferredSize(kNotificationExpandButtonLabelSize);
+  label->SetProperty(views::kMarginsKey, kNotificationExpandButtonLabelInsets);
+  label->SetElideBehavior(gfx::ElideBehavior::NO_ELIDE);
   label->SetText(base::NumberToString16(total_grouped_notifications_));
   label->SetVisible(ShouldShowLabel());
   label_ = AddChildView(std::move(label));
@@ -51,6 +51,7 @@
   UpdateIcons();
 
   auto image = std::make_unique<views::ImageView>();
+  image->SetProperty(views::kMarginsKey, kNotificationExpandButtonImageInsets);
   image->SetImage(expanded_ ? expanded_image_ : collapsed_image_);
   image_ = AddChildView(std::move(image));
 
@@ -75,6 +76,9 @@
 void AshNotificationExpandButton::SetExpanded(bool expanded) {
   if (expanded_ == expanded)
     return;
+
+  previous_bounds_ = GetContentsBounds();
+
   expanded_ = expanded;
 
   label_->SetText(base::NumberToString16(total_grouped_notifications_));
@@ -138,11 +142,6 @@
     message_center_utils::FadeInView(label_, kExpandButtonFadeInLabelDelayMs,
                                      kExpandButtonFadeInLabelDurationMs);
 
-    // The button is going from circle to pill shape, thus we need to add
-    // negative extra width to previous bounds.
-    extra_width = kNotificationExpandButtonSize.width() -
-                  kNotificationExpandButtonWithLabelSize.width();
-
     bounds_animation_duration = kExpandButtonShowLabelBoundsChangeDurationMs;
     bounds_animation_tween_type = gfx::Tween::LINEAR_OUT_SLOW_IN;
   } else {
@@ -162,11 +161,6 @@
             weak_factory_.GetWeakPtr(), label_),
         0, kExpandButtonFadeOutLabelDurationMs);
 
-    // The button is going from with pill to circle shape, thus we need to add
-    // positive extra width previous bounds.
-    extra_width = kNotificationExpandButtonWithLabelSize.width() -
-                  kNotificationExpandButtonSize.width();
-
     bounds_animation_duration = kExpandButtonHideLabelBoundsChangeDurationMs;
     bounds_animation_tween_type = gfx::Tween::ACCEL_20_DECEL_100;
   }
@@ -177,6 +171,9 @@
   // stay in the same location when the parent's bounds is moving.
   const gfx::Rect target_bounds = layer()->GetTargetBounds();
   const gfx::Rect image_target_bounds = image_->layer()->GetTargetBounds();
+
+  extra_width = previous_bounds_.width() - target_bounds.width();
+
   layer()->SetBounds(
       gfx::Rect(target_bounds.x() - extra_width, target_bounds.y(),
                 target_bounds.width() + extra_width, target_bounds.height()));
@@ -191,13 +188,6 @@
       .SetBounds(image_, image_target_bounds, bounds_animation_tween_type);
 }
 
-gfx::Size AshNotificationExpandButton::CalculatePreferredSize() const {
-  if (ShouldShowLabel())
-    return kNotificationExpandButtonWithLabelSize;
-
-  return kNotificationExpandButtonSize;
-}
-
 void AshNotificationExpandButton::OnThemeChanged() {
   views::Button::OnThemeChanged();
 
diff --git a/ash/system/message_center/ash_notification_expand_button.h b/ash/system/message_center/ash_notification_expand_button.h
index 698212f6..71efb554 100644
--- a/ash/system/message_center/ash_notification_expand_button.h
+++ b/ash/system/message_center/ash_notification_expand_button.h
@@ -47,7 +47,6 @@
   void PerformExpandCollapseAnimation();
 
   // views::Button:
-  gfx::Size CalculatePreferredSize() const override;
   void OnThemeChanged() override;
 
   views::Label* label_for_test() { return label_; }
@@ -61,6 +60,9 @@
   gfx::ImageSkia expanded_image_;
   gfx::ImageSkia collapsed_image_;
 
+  // Used in layer bounds animation.
+  gfx::Rect previous_bounds_;
+
   // Total number of grouped child notifications in this button's parent view.
   int total_grouped_notifications_ = 0;
 
diff --git a/ash/system/message_center/message_center_constants.h b/ash/system/message_center/message_center_constants.h
index 3a6ab97..094dd00 100644
--- a/ash/system/message_center/message_center_constants.h
+++ b/ash/system/message_center/message_center_constants.h
@@ -35,14 +35,11 @@
 // The width of notification that displayed inside the message center.
 constexpr int kNotificationInMessageCenterWidth = 344;
 
-constexpr gfx::Insets kNotificationExpandButtonInsets(4, 4);
-constexpr int kNotificationExpandButtonChildSpacing = 4;
+constexpr gfx::Insets kNotificationExpandButtonImageInsets(4, 4);
+constexpr gfx::Insets kNotificationExpandButtonLabelInsets(0, 8, 0, 0);
 constexpr int kNotificationExpandButtonCornerRadius = 12;
 constexpr int kNotificationExpandButtonChevronIconSize = 16;
 constexpr int kNotificationExpandButtonLabelFontSize = 12;
-constexpr gfx::Size kNotificationExpandButtonLabelSize(8, 16);
-constexpr gfx::Size kNotificationExpandButtonSize(24, 24);
-constexpr gfx::Size kNotificationExpandButtonWithLabelSize(40, 24);
 
 constexpr gfx::Insets kAppIconExpandButtonExpandedPadding(2, 0, 0, 0);
 constexpr gfx::Insets kAppIconExpandButtonCollapsedPadding(12, 0, 0, 0);
diff --git a/ash/webui/camera_app_ui/PRESUBMIT.py b/ash/webui/camera_app_ui/PRESUBMIT.py
index 27e7ecdc..5cf4b02f 100644
--- a/ash/webui/camera_app_ui/PRESUBMIT.py
+++ b/ash/webui/camera_app_ui/PRESUBMIT.py
@@ -2,6 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import os
+import subprocess
+
+
 USE_PYTHON3 = True
 
 
@@ -13,15 +17,38 @@
   return _CommonChecks(input_api, output_api)
 
 
+BASE_DIRECTORY = 'ash/webui/camera_app_ui/'
+STRING_RESOURCE_FILES = [os.path.join(BASE_DIRECTORY, f) for f in [
+  'resources.h',
+  'resources/js/i18n_string.ts',
+  'resources/strings/camera_strings.grd',
+]]
+
+
 def _CommonChecks(input_api, output_api):
   results = input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
                                                         check_js=True)
   affected = input_api.AffectedFiles()
   if any(f for f in affected if f.LocalPath().endswith('.html')):
     results += _CheckHtml(input_api, output_api)
+  if any(f for f in affected if f.LocalPath() in STRING_RESOURCE_FILES):
+    results += _CheckStringResouce(input_api, output_api)
   return results
 
 
 def _CheckHtml(input_api, output_api):
   return input_api.canned_checks.CheckLongLines(
       input_api, output_api, 80, lambda x: x.LocalPath().endswith('.html'))
+
+
+def _CheckStringResouce(input_api, output_api):
+  rv = subprocess.call(['./resources/utils/cca.py', 'check-strings'])
+
+  if rv:
+    return [
+        output_api.PresubmitPromptWarning(
+            'String resources check failed, ' +
+            'please make sure the relevant string files are all modified.')
+    ]
+
+  return []
diff --git a/ash/webui/camera_app_ui/resources/js/i18n_string.ts b/ash/webui/camera_app_ui/resources/js/i18n_string.ts
index 56a1255..84075ab 100644
--- a/ash/webui/camera_app_ui/resources/js/i18n_string.ts
+++ b/ash/webui/camera_app_ui/resources/js/i18n_string.ts
@@ -47,6 +47,7 @@
   EXPERT_ENABLE_FULL_SIZED_VIDEO_SNAPSHOT =
       'expert_enable_full_sized_video_snapshot',
   EXPERT_MODE_BUTTON = 'expert_mode_button',
+  EXPERT_MULTISTREAM_RECORDING = 'expert_multistream_recording',
   EXPERT_PREVIEW_METADATA = 'expert_preview_metadata',
   EXPERT_PRINT_PERFORMANCE_LOGS = 'expert_print_performance_logs',
   EXPERT_SAVE_METADATA = 'expert_save_metadata',
@@ -110,11 +111,11 @@
   NEW_CONTROL_NAVIGATION = 'new_control_navigation',
   NEW_CONTROL_TOAST = 'new_control_toast',
   NEW_DOCUMENT_SCAN_TOAST = 'new_document_scan_toast',
+  NO_DOCUMENT_GUIDE_MSG = 'no_document_guide_msg',
   OPEN_PTZ_PANEL_BUTTON = 'open_ptz_panel_button',
   PAN_LEFT_BUTTON = 'pan_left_button',
   PAN_RIGHT_BUTTON = 'pan_right_button',
   PHOTO_RESOLUTION_BUTTON = 'photo_resolution_button',
-  PLAY_RESULT_VIDEO_BUTTON = 'play_result_video_button',
   PRINT_BUTTON = 'print_button',
   PTZ_RESET_ALL_BUTTON = 'ptz_reset_all_button',
   RECORD_GIF_VIDEO_OPTION = 'record_gif_video_option',
@@ -124,6 +125,8 @@
   RECORD_VIDEO_RESUME_BUTTON = 'record_video_resume_button',
   RECORD_VIDEO_START_BUTTON = 'record_video_start_button',
   RECORD_VIDEO_STOP_BUTTON = 'record_video_stop_button',
+  ROTATE_CLOCKWISE_BUTTON = 'rotate_clockwise_button',
+  ROTATE_COUNTERCLOCKWISE_BUTTON = 'rotate_counterclockwise_button',
   SCAN_DOCUMENT_OPTION = 'scan_document_option',
   SCAN_QRCODE_OPTION = 'scan_qrcode_option',
   SETTINGS_BUTTON = 'settings_button',
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni
index be10205d..f77e4e7 100644
--- a/ash/webui/camera_app_ui/resources/js/js.gni
+++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -73,8 +73,8 @@
   "views/camera/layout.js",
   "views/camera/mode/index.ts",
   "views/camera/mode/mode_base.ts",
-  "views/camera/mode/photo.js",
-  "views/camera/mode/portrait.js",
+  "views/camera/mode/photo.ts",
+  "views/camera/mode/portrait.ts",
   "views/camera/mode/record_time.js",
   "views/camera/mode/scan.ts",
   "views/camera/mode/square.js",
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/mode_base.ts b/ash/webui/camera_app_ui/resources/js/views/camera/mode/mode_base.ts
index d3c5cf77..46444525 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera/mode/mode_base.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/mode/mode_base.ts
@@ -27,8 +27,7 @@
    * @param facing Camera facing of current mode.
    */
   constructor(
-      protected readonly stream: MediaStream,
-      protected readonly facing: Facing) {}
+      protected stream: MediaStream, protected readonly facing: Facing) {}
 
   /**
    * Initiates video/photo capture operation.
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.js b/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.js
deleted file mode 100644
index 7d80d1d..0000000
--- a/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.js
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assertNotReached} from '../../../assert.js';
-// eslint-disable-next-line no-unused-vars
-import {StreamConstraints} from '../../../device/stream_constraints.js';
-import {DeviceOperator, parseMetadata} from '../../../mojo/device_operator.js';
-import {CrosImageCapture} from '../../../mojo/image_capture.js';
-import {
-  CameraMetadataTag,
-  StreamType,
-} from '../../../mojo/type.js';
-import {
-  closeEndpoint,
-  MojoEndpoint,  // eslint-disable-line no-unused-vars
-} from '../../../mojo/util.js';
-import * as state from '../../../state.js';
-import {
-  Facing,    // eslint-disable-line no-unused-vars
-  Metadata,  // eslint-disable-line no-unused-vars
-  PerfEvent,
-  Resolution,
-} from '../../../type.js';
-import * as util from '../../../util.js';
-import {WaitableEvent} from '../../../waitable_event.js';
-
-import {ModeBase, ModeFactory} from './mode_base.js';
-
-/**
- * Contains photo taking result.
- * @typedef {{
- *     resolution: !Resolution,
- *     blob: !Blob,
- *     timestamp: number,
- *     metadata: ?Metadata,
- * }}
- */
-export let PhotoResult;
-
-/**
- * Provides external dependency functions used by photo mode and handles the
- * captured result photo.
- * @interface
- */
-export class PhotoHandler {
-  /**
-   * Plays UI effect when taking photo.
-   */
-  playShutterEffect() {}
-
-  /**
-   * @return {!Promise}
-   * @abstract
-   */
-  waitPreviewReady() {
-    assertNotReached();
-  }
-
-  /**
-   * Called when error happen in the capture process.
-   * @abstract
-   */
-  onPhotoError() {
-    assertNotReached();
-  }
-
-  /**
-   * @param {!Promise<!PhotoResult>} pendingPhotoResult
-   * @return {!Promise<void>}
-   * @abstract
-   */
-  onPhotoCaptureDone(pendingPhotoResult) {
-    assertNotReached();
-  }
-}
-
-/**
- * Photo mode capture controller.
- */
-export class Photo extends ModeBase {
-  /**
-   * @param {!MediaStream} stream
-   * @param {!Facing} facing
-   * @param {!Resolution} captureResolution
-   * @param {!PhotoHandler} handler
-   */
-  constructor(stream, facing, captureResolution, handler) {
-    super(stream, facing);
-
-    /**
-     * Capture resolution. May be null on device not support of setting
-     * resolution.
-     * @type {!Resolution}
-     * @protected
-     */
-    this.captureResolution_ = captureResolution;
-
-    /**
-     * @const {!PhotoHandler}
-     * @protected
-     */
-    this.handler_ = handler;
-
-    /**
-     * CrosImageCapture object to capture still photos.
-     * @type {!CrosImageCapture}
-     * @protected
-     */
-    this.crosImageCapture_ =
-        new CrosImageCapture(this.stream.getVideoTracks()[0]);
-
-    /**
-     * The observer endpoint for saving metadata.
-     * @type {?MojoEndpoint}
-     * @protected
-     */
-    this.metadataObserver_ = null;
-
-    /**
-     * Pending |PhotoResult| waiting for arrival of their corresponding
-     * metadata..
-     * @type {!Array<!WaitableEvent<!Metadata>>}
-     * @protected
-     */
-    this.pendingResultForMetadata_ = [];
-  }
-
-  /**
-   * @param {!MediaStream} stream
-   */
-  updatePreview(stream) {
-    this.stream = stream;
-    this.crosImageCapture_ =
-        new CrosImageCapture(this.stream.getVideoTracks()[0]);
-  }
-
-  /**
-   * @override
-   */
-  async start() {
-    const timestamp = Date.now();
-    state.set(PerfEvent.PHOTO_CAPTURE_SHUTTER, true);
-    const {blob, pendingMetadata} = await (async () => {
-      let hasError = false;
-      try {
-        return await this.takePhoto_();
-      } catch (e) {
-        hasError = true;
-        this.handler_.onPhotoError();
-        throw e;
-      } finally {
-        state.set(
-            PerfEvent.PHOTO_CAPTURE_SHUTTER, false,
-            hasError ? {hasError} : {facing: this.facing});
-      }
-    })();
-
-    const pendingPhotoResult = (async () => {
-      const image = await util.blobToImage(blob);
-      const resolution = new Resolution(image.width, image.height);
-      return {resolution, blob, timestamp, metadata: await pendingMetadata};
-    })();
-
-    return async () => this.handler_.onPhotoCaptureDone(pendingPhotoResult);
-  }
-
-  /**
-   * @private
-   * @return {!Promise<{blob: !Blob, pendingMetadata: ?Promise<!Metadata>}>}
-   */
-  async takePhoto_() {
-    if (state.get(state.State.ENABLE_PTZ)) {
-      // Workaround for b/184089334 on PTZ camera to use preview frame as
-      // photo result.
-      return {
-        blob: await this.crosImageCapture_.grabJpegFrame(),
-        pendingMetadata: null,
-      };
-    }
-    let photoSettings;
-    if (this.captureResolution_) {
-      photoSettings = /** @type {!PhotoSettings} */ ({
-        imageWidth: this.captureResolution_.width,
-        imageHeight: this.captureResolution_.height,
-      });
-    } else {
-      const caps = await this.crosImageCapture_.getPhotoCapabilities();
-      photoSettings = /** @type {!PhotoSettings} */ ({
-        imageWidth: caps.imageWidth.max,
-        imageHeight: caps.imageHeight.max,
-      });
-    }
-
-    let /** ?WaitableEvent<!Metadata> */ waitForMetadata = null;
-    if (this.metadataObserver_ !== null) {
-      waitForMetadata =
-          /** @type{!WaitableEvent<!Metadata>} */ (new WaitableEvent());
-      this.pendingResultForMetadata_.push(waitForMetadata);
-    }
-    await this.handler_.waitPreviewReady();
-    const results = await this.crosImageCapture_.takePhoto(photoSettings);
-    this.handler_.playShutterEffect();
-    return {
-      blob: await results[0],
-      pendingMetadata: waitForMetadata?.wait() ?? null,
-    };
-  }
-
-  /**
-   * Adds an observer to save metadata.
-   * @return {!Promise} Promise for the operation.
-   */
-  async addMetadataObserver() {
-    if (!this.stream) {
-      return;
-    }
-
-    const deviceOperator = await DeviceOperator.getInstance();
-    if (!deviceOperator) {
-      return;
-    }
-
-    const cameraMetadataTagInverseLookup = {};
-    Object.entries(CameraMetadataTag).forEach(([key, value]) => {
-      if (key === 'MIN_VALUE' || key === 'MAX_VALUE') {
-        return;
-      }
-      cameraMetadataTagInverseLookup[value] = key;
-    });
-
-    const callback = (metadata) => {
-      const parsedMetadata = /** @type {!Record<string, unknown>} */ ({});
-      for (const entry of metadata.entries) {
-        const key = cameraMetadataTagInverseLookup[entry.tag];
-        if (key === undefined) {
-          // TODO(kaihsien): Add support for vendor tags.
-          continue;
-        }
-
-        const val = parseMetadata(entry);
-        parsedMetadata[key] = val;
-      }
-
-      this.pendingResultForMetadata_.shift()?.signal(parsedMetadata);
-    };
-
-    const deviceId = this.stream.getVideoTracks()[0].getSettings().deviceId;
-    this.metadataObserver_ = await deviceOperator.addMetadataObserver(
-        deviceId, callback, StreamType.JPEG_OUTPUT);
-  }
-
-  /**
-   * Removes the observer that saves metadata.
-   * @return {!Promise} Promise for the operation.
-   */
-  async removeMetadataObserver() {
-    if (!this.stream || this.metadataObserver_ === null) {
-      return;
-    }
-
-    const deviceOperator = await DeviceOperator.getInstance();
-    if (!deviceOperator) {
-      return;
-    }
-
-    closeEndpoint(this.metadataObserver_);
-    this.metadataObserver_ = null;
-  }
-}
-
-/**
- * Factory for creating photo mode capture object.
- */
-export class PhotoFactory extends ModeFactory {
-  /**
-   * @param {!StreamConstraints} constraints Constraints for preview
-   *     stream.
-   * @param {!Resolution} captureResolution
-   * @param {!PhotoHandler} handler
-   */
-  constructor(constraints, captureResolution, handler) {
-    super(constraints, captureResolution);
-
-    /**
-     * @const {!PhotoHandler}
-     * @protected
-     */
-    this.handler_ = handler;
-  }
-
-  /**
-   * @override
-   */
-  produce() {
-    return new Photo(
-        this.previewStream, this.facing, this.captureResolution, this.handler_);
-  }
-}
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.ts b/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.ts
new file mode 100644
index 0000000..df1d25e3
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/mode/photo.ts
@@ -0,0 +1,242 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {StreamConstraints} from '../../../device/stream_constraints.js';
+import {DeviceOperator, parseMetadata} from '../../../mojo/device_operator.js';
+import {CrosImageCapture} from '../../../mojo/image_capture.js';
+import {
+  CameraMetadataTag,
+  StreamType,
+} from '../../../mojo/type.js';
+import {
+  closeEndpoint,
+  MojoEndpoint,
+} from '../../../mojo/util.js';
+import * as state from '../../../state.js';
+import {
+  Facing,
+  Metadata,
+  PerfEvent,
+  Resolution,
+} from '../../../type.js';
+import * as util from '../../../util.js';
+import {WaitableEvent} from '../../../waitable_event.js';
+
+import {ModeBase, ModeFactory} from './mode_base.js';
+
+/**
+ * Contains photo taking result.
+ */
+export interface PhotoResult {
+  resolution: Resolution;
+  blob: Blob;
+  timestamp: number;
+  metadata: Metadata|null;
+}
+
+/**
+ * Provides external dependency functions used by photo mode and handles the
+ * captured result photo.
+ */
+export interface PhotoHandler {
+  /**
+   * Plays UI effect when taking photo.
+   */
+  playShutterEffect(): void;
+
+  waitPreviewReady(): Promise<void>;
+
+  /**
+   * Called when error happen in the capture process.
+   */
+  onPhotoError(): void;
+
+  onPhotoCaptureDone(pendingPhotoResult: Promise<PhotoResult>): Promise<void>;
+}
+
+/**
+ * Photo mode capture controller.
+ */
+export class Photo extends ModeBase {
+  /**
+   * CrosImageCapture object to capture still photos.
+   */
+  protected crosImageCapture: CrosImageCapture;
+
+  /**
+   * The observer endpoint for saving metadata.
+   */
+  protected metadataObserver: MojoEndpoint|null = null;
+
+  /**
+   * Pending |PhotoResult| waiting for arrival of their corresponding
+   * metadata.
+   */
+  protected pendingResultForMetadata: Array<WaitableEvent<Metadata>> = [];
+
+  /**
+   * @param captureResolution Capture resolution. May be null on device not
+   *     support of setting resolution.
+   */
+  constructor(
+      stream: MediaStream, facing: Facing,
+      protected readonly captureResolution: Resolution,
+      protected readonly handler: PhotoHandler) {
+    super(stream, facing);
+
+    this.crosImageCapture =
+        new CrosImageCapture(this.stream.getVideoTracks()[0]);
+  }
+
+  updatePreview(stream: MediaStream): void {
+    this.stream = stream;
+    this.crosImageCapture =
+        new CrosImageCapture(this.stream.getVideoTracks()[0]);
+  }
+
+  async start(): Promise<() => Promise<void>> {
+    const timestamp = Date.now();
+    state.set(PerfEvent.PHOTO_CAPTURE_SHUTTER, true);
+    const {blob, pendingMetadata} = await (async () => {
+      let hasError = false;
+      try {
+        return await this.takePhoto();
+      } catch (e) {
+        hasError = true;
+        this.handler.onPhotoError();
+        throw e;
+      } finally {
+        state.set(
+            PerfEvent.PHOTO_CAPTURE_SHUTTER, false,
+            hasError ? {hasError} : {facing: this.facing});
+      }
+    })();
+
+    const pendingPhotoResult = (async () => {
+      const image = await util.blobToImage(blob);
+      const resolution = new Resolution(image.width, image.height);
+      return {resolution, blob, timestamp, metadata: await pendingMetadata};
+    })();
+
+    return async () => this.handler.onPhotoCaptureDone(pendingPhotoResult);
+  }
+
+  private async takePhoto():
+      Promise<{blob: Blob, pendingMetadata: Promise<Metadata>|null}> {
+    if (state.get(state.State.ENABLE_PTZ)) {
+      // Workaround for b/184089334 on PTZ camera to use preview frame as
+      // photo result.
+      return {
+        blob: await this.crosImageCapture.grabJpegFrame(),
+        pendingMetadata: null,
+      };
+    }
+    let photoSettings: PhotoSettings;
+    if (this.captureResolution) {
+      photoSettings = {
+        imageWidth: this.captureResolution.width,
+        imageHeight: this.captureResolution.height,
+      };
+    } else {
+      const caps = await this.crosImageCapture.getPhotoCapabilities();
+      photoSettings = {
+        imageWidth: caps.imageWidth.max,
+        imageHeight: caps.imageHeight.max,
+      };
+    }
+
+    let waitForMetadata: WaitableEvent<Metadata>|null = null;
+    if (this.metadataObserver !== null) {
+      waitForMetadata = new WaitableEvent();
+      this.pendingResultForMetadata.push(waitForMetadata);
+    }
+    await this.handler.waitPreviewReady();
+    const results = await this.crosImageCapture.takePhoto(photoSettings);
+    this.handler.playShutterEffect();
+    return {
+      blob: await results[0],
+      pendingMetadata: waitForMetadata?.wait() ?? null,
+    };
+  }
+
+  /**
+   * Adds an observer to save metadata.
+   * @return Promise for the operation.
+   */
+  async addMetadataObserver(): Promise<void> {
+    if (!this.stream) {
+      return;
+    }
+
+    const deviceOperator = await DeviceOperator.getInstance();
+    if (!deviceOperator) {
+      return;
+    }
+
+    const cameraMetadataTagInverseLookup = {};
+    Object.entries(CameraMetadataTag).forEach(([key, value]) => {
+      if (key === 'MIN_VALUE' || key === 'MAX_VALUE') {
+        return;
+      }
+      cameraMetadataTagInverseLookup[value] = key;
+    });
+
+    const callback = (metadata) => {
+      const parsedMetadata = /** @type {!Record<string, unknown>} */ ({});
+      for (const entry of metadata.entries) {
+        const key = cameraMetadataTagInverseLookup[entry.tag];
+        if (key === undefined) {
+          // TODO(kaihsien): Add support for vendor tags.
+          continue;
+        }
+
+        const val = parseMetadata(entry);
+        parsedMetadata[key] = val;
+      }
+
+      this.pendingResultForMetadata.shift()?.signal(parsedMetadata);
+    };
+
+    const deviceId = this.stream.getVideoTracks()[0].getSettings().deviceId;
+    this.metadataObserver = await deviceOperator.addMetadataObserver(
+        deviceId, callback, StreamType.JPEG_OUTPUT);
+  }
+
+  /**
+   * Removes the observer that saves metadata.
+   * @return Promise for the operation.
+   */
+  async removeMetadataObserver(): Promise<void> {
+    if (!this.stream || this.metadataObserver === null) {
+      return;
+    }
+
+    const deviceOperator = await DeviceOperator.getInstance();
+    if (!deviceOperator) {
+      return;
+    }
+
+    closeEndpoint(this.metadataObserver);
+    this.metadataObserver = null;
+  }
+}
+
+/**
+ * Factory for creating photo mode capture object.
+ */
+export class PhotoFactory extends ModeFactory {
+  /**
+   * @param constraints Constraints for preview stream.
+   */
+  constructor(
+      constraints: StreamConstraints, captureResolution: Resolution,
+      protected readonly handler: PhotoHandler) {
+    super(constraints, captureResolution);
+  }
+
+  produce(): ModeBase {
+    return new Photo(
+        this.previewStream, this.facing, this.captureResolution, this.handler);
+  }
+}
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.js b/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.js
deleted file mode 100644
index 7b94039e..0000000
--- a/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.js
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assertNotReached} from '../../../assert.js';
-// eslint-disable-next-line no-unused-vars
-import {StreamConstraints} from '../../../device/stream_constraints.js';
-import {I18nString} from '../../../i18n_string.js';
-import {CrosImageCapture} from '../../../mojo/image_capture.js';
-import {Effect} from '../../../mojo/type.js';
-import * as toast from '../../../toast.js';
-import {
-  Facing,      // eslint-disable-line no-unused-vars
-  Metadata,    // eslint-disable-line no-unused-vars
-  Resolution,  // eslint-disable-line no-unused-vars
-} from '../../../type.js';
-import * as util from '../../../util.js';
-import {WaitableEvent} from '../../../waitable_event.js';
-
-import {
-  Photo,
-  PhotoFactory,
-  PhotoHandler,  // eslint-disable-line no-unused-vars
-} from './photo.js';
-
-/**
- * Contains photo taking result.
- * @typedef {{
- *     timestamp: number,
- *     resolution: !Resolution,
- *     blob: !Blob,
- *     metadata: ?Metadata,
- *     pendingPortrait: !Promise<?{blob: !Blob, metadata: ?Metadata}>,
- * }}
- */
-export let PortraitResult;
-
-/**
- * Provides external dependency functions used by portrait mode and handles the
- * captured result photo.
- * @interface
- */
-export class PortraitHandler extends PhotoHandler {
-  /**
-   * @param {!Promise<!PortraitResult>} pendingPortraitResult
-   * @return {!Promise<void>}
-   * @abstract
-   */
-  onPortraitCaptureDone(pendingPortraitResult) {
-    assertNotReached();
-  }
-}
-
-/**
- * Portrait mode capture controller.
- */
-export class Portrait extends Photo {
-  /**
-   * @param {!MediaStream} stream
-   * @param {!Facing} facing
-   * @param {!Resolution} captureResolution
-   * @param {!PortraitHandler} handler
-   */
-  constructor(stream, facing, captureResolution, handler) {
-    super(stream, facing, captureResolution, handler);
-
-    /**
-     * @const {!PortraitHandler}
-     * @private
-     */
-    this.portraitHandler_ = handler;
-  }
-
-  /**
-   * @override
-   */
-  async start() {
-    const timestamp = Date.now();
-    if (this.crosImageCapture_ === null) {
-      this.crosImageCapture_ =
-          new CrosImageCapture(this.stream.getVideoTracks()[0]);
-    }
-
-    let photoSettings;
-    if (this.captureResolution_) {
-      photoSettings = /** @type {!PhotoSettings} */ ({
-        imageWidth: this.captureResolution_.width,
-        imageHeight: this.captureResolution_.height,
-      });
-    } else {
-      const caps = await this.crosImageCapture_.getPhotoCapabilities();
-      photoSettings = /** @type {!PhotoSettings} */ ({
-        imageWidth: caps.imageWidth.max,
-        imageHeight: caps.imageHeight.max,
-      });
-    }
-
-    let /** !Promise<!Blob> */ reference;
-    let /** !Promise<!Blob> */ portrait;
-    let /** ?WaitableEvent<!Metadata> */ waitForMetadata = null;
-    let /** ?WaitableEvent<!Metadata> */ waitForPortraitMetadata = null;
-    if (this.metadataObserver_ !== null) {
-      waitForMetadata =
-          /** @type{!WaitableEvent<!Metadata>} */ (new WaitableEvent());
-      waitForPortraitMetadata =
-          /** @type{!WaitableEvent<!Metadata>} */ (new WaitableEvent());
-      this.pendingResultForMetadata_.push(
-          waitForMetadata, waitForPortraitMetadata);
-    }
-    try {
-      [reference, portrait] = await this.crosImageCapture_.takePhoto(
-          photoSettings, [Effect.PORTRAIT_MODE]);
-      this.portraitHandler_.playShutterEffect();
-    } catch (e) {
-      toast.show(I18nString.ERROR_MSG_TAKE_PHOTO_FAILED);
-      throw e;
-    }
-
-    const pendingPortraitResult = (async () => {
-      const blob = await reference;
-      const image = await util.blobToImage(blob);
-      const resolution = new Resolution(image.width, image.height);
-      const metadata = await (waitForMetadata?.wait() ?? null);
-      const pendingPortrait = (async () => {
-        let /** !Blob */ portraitBlob;
-        try {
-          portraitBlob = await portrait;
-        } catch (e) {
-          // Portrait image may failed due to absence of human faces.
-          // TODO(inker): Log non-intended error.
-          return null;
-        }
-        const metadata = await (waitForPortraitMetadata?.wait() ?? null);
-        return {blob: portraitBlob, metadata};
-      })();
-
-      return {timestamp, resolution, blob, metadata, pendingPortrait};
-    })();
-
-    return () => this.portraitHandler_.onPortraitCaptureDone(
-               pendingPortraitResult);
-  }
-}
-
-/**
- * Factory for creating portrait mode capture object.
- */
-export class PortraitFactory extends PhotoFactory {
-  /**
-   * @param {!StreamConstraints} constraints Constraints for preview
-   *     stream.
-   * @param {!Resolution} captureResolution
-   * @param {!PortraitHandler} handler
-   */
-  constructor(constraints, captureResolution, handler) {
-    super(constraints, captureResolution, handler);
-
-    /**
-     * @const {!PhotoHandler}
-     * @protected
-     */
-    this.portraitHandler_ = handler;
-  }
-
-  /**
-   * @override
-   */
-  produce() {
-    return new Portrait(
-        this.previewStream, this.facing, this.captureResolution,
-        this.portraitHandler_);
-  }
-}
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.ts b/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.ts
new file mode 100644
index 0000000..db87427
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/mode/portrait.ts
@@ -0,0 +1,144 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {StreamConstraints} from '../../../device/stream_constraints.js';
+import {I18nString} from '../../../i18n_string.js';
+import {CrosImageCapture} from '../../../mojo/image_capture.js';
+import {Effect} from '../../../mojo/type.js';
+import * as toast from '../../../toast.js';
+import {
+  Facing,
+  Metadata,
+  Resolution,
+} from '../../../type.js';
+import * as util from '../../../util.js';
+import {WaitableEvent} from '../../../waitable_event.js';
+import {ModeBase} from './mode_base.js';
+
+import {
+  Photo,
+  PhotoFactory,
+  PhotoHandler,
+} from './photo.js';
+
+/**
+ * Contains photo taking result.
+ */
+export interface PortraitResult {
+  timestamp: number;
+  resolution: Resolution;
+  blob: Blob;
+  metadata: Metadata|null;
+  pendingPortrait: Promise<{blob: Blob, metadata: Metadata|null}>|null;
+}
+
+/**
+ * Provides external dependency functions used by portrait mode and handles the
+ * captured result photo.
+ */
+export interface PortraitHandler extends PhotoHandler {
+  onPortraitCaptureDone(pendingPortraitResult: Promise<PortraitResult>):
+      Promise<void>;
+}
+
+/**
+ * Portrait mode capture controller.
+ */
+export class Portrait extends Photo {
+  constructor(
+      stream: MediaStream,
+      facing: Facing,
+      captureResolution: Resolution,
+      private readonly portraitHandler: PortraitHandler,
+  ) {
+    super(stream, facing, captureResolution, portraitHandler);
+  }
+
+  async start(): Promise<() => Promise<void>> {
+    const timestamp = Date.now();
+    if (this.crosImageCapture === null) {
+      this.crosImageCapture =
+          new CrosImageCapture(this.stream.getVideoTracks()[0]);
+    }
+
+    let photoSettings: PhotoSettings;
+    if (this.captureResolution) {
+      photoSettings = {
+        imageWidth: this.captureResolution.width,
+        imageHeight: this.captureResolution.height,
+      };
+    } else {
+      const caps = await this.crosImageCapture.getPhotoCapabilities();
+      photoSettings = {
+        imageWidth: caps.imageWidth.max,
+        imageHeight: caps.imageHeight.max,
+      };
+    }
+
+    let reference: Promise<Blob>;
+    let portrait: Promise<Blob>;
+    let waitForMetadata: WaitableEvent<Metadata>|null = null;
+    let waitForPortraitMetadata: WaitableEvent<Metadata>|null = null;
+    if (this.metadataObserver !== null) {
+      waitForMetadata = new WaitableEvent();
+      waitForPortraitMetadata = new WaitableEvent();
+      this.pendingResultForMetadata.push(
+          waitForMetadata, waitForPortraitMetadata);
+    }
+    try {
+      [reference, portrait] = await this.crosImageCapture.takePhoto(
+          photoSettings, [Effect.PORTRAIT_MODE]);
+      this.portraitHandler.playShutterEffect();
+    } catch (e) {
+      toast.show(I18nString.ERROR_MSG_TAKE_PHOTO_FAILED);
+      throw e;
+    }
+
+    const pendingPortraitResult = (async () => {
+      const blob = await reference;
+      const image = await util.blobToImage(blob);
+      const resolution = new Resolution(image.width, image.height);
+      const metadata = await (waitForMetadata?.wait() ?? null);
+      const pendingPortrait = (async () => {
+        let portraitBlob: Blob;
+        try {
+          portraitBlob = await portrait;
+        } catch (e) {
+          // Portrait image may failed due to absence of human faces.
+          // TODO(inker): Log non-intended error.
+          return null;
+        }
+        const metadata = await (waitForPortraitMetadata?.wait() ?? null);
+        return {blob: portraitBlob, metadata};
+      })();
+
+      return {timestamp, resolution, blob, metadata, pendingPortrait};
+    })();
+
+    return () => this.portraitHandler.onPortraitCaptureDone(
+               pendingPortraitResult);
+  }
+}
+
+/**
+ * Factory for creating portrait mode capture object.
+ */
+export class PortraitFactory extends PhotoFactory {
+  /**
+   * @param constraints Constraints for preview stream.
+   */
+  constructor(
+      constraints: StreamConstraints,
+      captureResolution: Resolution,
+      protected readonly portraitHandler: PortraitHandler,
+  ) {
+    super(constraints, captureResolution, portraitHandler);
+  }
+
+  produce(): ModeBase {
+    return new Portrait(
+        this.previewStream, this.facing, this.captureResolution,
+        this.portraitHandler);
+  }
+}
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera/mode/square.js b/ash/webui/camera_app_ui/resources/js/views/camera/mode/square.js
index a4b6d47..83064fb5 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera/mode/square.js
+++ b/ash/webui/camera_app_ui/resources/js/views/camera/mode/square.js
@@ -114,6 +114,6 @@
    */
   produce() {
     return new Square(
-        this.previewStream, this.facing, this.captureResolution, this.handler_);
+        this.previewStream, this.facing, this.captureResolution, this.handler);
   }
 }
diff --git a/ash/webui/camera_app_ui/resources/utils/cca.py b/ash/webui/camera_app_ui/resources/utils/cca.py
index a4979aa..b435317 100755
--- a/ash/webui/camera_app_ui/resources/utils/cca.py
+++ b/ash/webui/camera_app_ui/resources/utils/cca.py
@@ -14,6 +14,7 @@
 import subprocess
 import sys
 import tempfile
+import xml.sax
 
 
 @functools.lru_cache(1)
@@ -242,6 +243,88 @@
         print('TypeScript check failed, return code =', e.returncode)
 
 
+RESOURCES_H_PATH = '../resources.h'
+I18N_STRING_TS_PATH = './js/i18n_string.ts'
+CAMERA_STRINGS_GRD_PATH = './strings/camera_strings.grd'
+
+
+def parse_resources_h():
+    with open(RESOURCES_H_PATH, 'r') as f:
+        content = f.read()
+        return set(re.findall(r'\{"(\w+)",\s*(\w+)\}', content))
+
+
+def parse_i18n_string_ts():
+    with open(I18N_STRING_TS_PATH, 'r') as f:
+        content = f.read()
+        return set([(name, f'IDS_{id}')
+                    for (id, name) in re.findall(r"(\w+) =\s*'(\w+)'", content)
+                    ])
+
+
+# Same as tools/check_grd_for_unused_strings.py
+class GrdIDExtractor(xml.sax.handler.ContentHandler):
+    """Extracts the IDs from messages in GRIT files"""
+
+    def __init__(self):
+        self.id_set_ = set()
+
+    def startElement(self, name, attrs):
+        if name == 'message':
+            self.id_set_.add(attrs['name'])
+
+    def allIDs(self):
+        """Return all the IDs found"""
+        return self.id_set_.copy()
+
+
+def parse_camera_strings_grd():
+    handler = GrdIDExtractor()
+    xml.sax.parse(CAMERA_STRINGS_GRD_PATH, handler)
+    return handler.allIDs()
+
+
+def check_strings(args):
+    returncode = 0
+
+    def check_name_id_consistent(strings, filename):
+        nonlocal returncode
+        bad = [(name, id) for (name, id) in strings
+               if id != f'IDS_{name.upper()}']
+        if bad:
+            print(f'{filename} includes string id with inconsistent name:')
+            for (name, id) in bad:
+                print(f'    {name}: Expect IDS_{name.upper()}, got {id}')
+            returncode = 1
+
+    def check_all_ids_exist(all_ids, ids, filename):
+        nonlocal returncode
+        missing = all_ids.difference(ids)
+        if missing:
+            print(f'{filename} is missing the following string id:')
+            print(f'    {", ".join(sorted(missing))}')
+            returncode = 1
+
+    resources_h_strings = parse_resources_h()
+    check_name_id_consistent(resources_h_strings, RESOURCES_H_PATH)
+    resources_h_ids = set([id for (name, id) in resources_h_strings])
+
+    i18n_string_ts_strings = parse_i18n_string_ts()
+    check_name_id_consistent(i18n_string_ts_strings, I18N_STRING_TS_PATH)
+    i18n_string_ts_ids = set([id for (name, id) in i18n_string_ts_strings])
+
+    camera_strings_grd_ids = parse_camera_strings_grd()
+
+    all_ids = resources_h_ids.union(i18n_string_ts_ids, camera_strings_grd_ids)
+
+    check_all_ids_exist(all_ids, resources_h_ids, RESOURCES_H_PATH)
+    check_all_ids_exist(all_ids, i18n_string_ts_ids, I18N_STRING_TS_PATH)
+    check_all_ids_exist(all_ids, camera_strings_grd_ids,
+                        CAMERA_STRINGS_GRD_PATH)
+
+    return returncode
+
+
 def parse_args(args):
     parser = argparse.ArgumentParser(description='CCA developer tools.')
     parser.add_argument('--debug', action='store_true')
@@ -281,6 +364,17 @@
     tsc_parser.set_defaults(func=tsc)
     tsc_parser.add_argument('board')
 
+    # TODO(pihsun): Add argument to automatically generate / fix the files to a
+    # consistent state.
+    check_strings_parser = subparsers.add_parser(
+        'check-strings',
+        help='check string resources',
+        description='''Ensure files related to string resources are having the
+            same strings. This includes resources.h,
+            resources/strings/camera_strings.grd and
+            resources/js/i18n_string.ts.''')
+    check_strings_parser.set_defaults(func=check_strings)
+
     parser.set_defaults(func=lambda _args: parser.print_help())
 
     return parser.parse_args(args)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 3f9b187..d02bbc31 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-7.20220109.2.1
+7.20220110.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 3f9b187..d02bbc31 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-7.20220109.2.1
+7.20220110.1.1
diff --git a/chrome/VERSION b/chrome/VERSION
index b2feade7..6893191b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=99
 MINOR=0
-BUILD=4818
+BUILD=4819
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3a126ad7..79a3e66 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1461,6 +1461,7 @@
     "//components/content_settings/android:content_settings_enums_java",
     "//components/content_settings/android:java",
     "//components/crash/android:java",
+    "//components/crash/android:javatests",
     "//components/dom_distiller/core/android:dom_distiller_core_java",
     "//components/dom_distiller/core/mojom:mojom_java",
     "//components/download/internal/background_service:internal_java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 115cabc..5954fd79 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -422,6 +422,7 @@
   "java/src/org/chromium/chrome/browser/contextualsearch/TapWordLengthSuppression.java",
   "java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploadJobServiceImpl.java",
   "java/src/org/chromium/chrome/browser/crash/ChromeMinidumpUploaderDelegate.java",
+  "java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java",
   "java/src/org/chromium/chrome/browser/crash/CrashUploadCountStore.java",
   "java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java",
   "java/src/org/chromium/chrome/browser/crash/MinidumpUploadRetry.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index bbf00290..56b4fd9 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -138,7 +138,6 @@
   "javatests/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchFullUiTest.java",
   "javatests/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableTest.java",
   "javatests/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceTest.java",
-  "javatests/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporterTest.java",
   "javatests/src/org/chromium/chrome/browser/crypto/CipherFactoryTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoMetricTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
index 8b95125..ec703bba 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
@@ -11,12 +11,11 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
-import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.autofill_assistant.onboarding.AssistantOnboardingResult;
 import org.chromium.chrome.browser.autofill_assistant.onboarding.BaseOnboardingCoordinator;
 import org.chromium.chrome.browser.autofill_assistant.onboarding.OnboardingCoordinatorFactory;
 import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator;
-import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -31,13 +30,13 @@
 class AutofillAssistantActionHandlerImpl implements AutofillAssistantActionHandler {
     private final OnboardingCoordinatorFactory mOnboardingCoordinatorFactory;
     private final AssistantDependenciesFactory mDependenciesFactory;
-    private final ActivityTabProvider mActivityTabProvider;
+    private final Supplier<WebContents> mWebContentsSupplier;
 
     AutofillAssistantActionHandlerImpl(OnboardingCoordinatorFactory onboardingCoordinatorFactory,
-            ActivityTabProvider activityTabProvider,
+            Supplier<WebContents> webContentsSupplier,
             AssistantDependenciesFactory dependenciesFactory) {
         mOnboardingCoordinatorFactory = onboardingCoordinatorFactory;
-        mActivityTabProvider = activityTabProvider;
+        mWebContentsSupplier = webContentsSupplier;
         mDependenciesFactory = dependenciesFactory;
     }
 
@@ -128,31 +127,6 @@
         client.showFatalError();
     }
 
-    @Nullable
-    private WebContents getWebContents() {
-        Tab tab = mActivityTabProvider.get();
-        if (tab == null) {
-            return null;
-        }
-
-        return tab.getWebContents();
-    }
-
-    @Nullable
-    private Activity getActivity() {
-        Tab tab = mActivityTabProvider.get();
-        if (tab == null) {
-            return null;
-        }
-
-        WindowAndroid windowAndroid = tab.getWindowAndroid();
-        if (windowAndroid == null) {
-            return null;
-        }
-
-        return windowAndroid.getActivity().get();
-    }
-
     /**
      * Returns a client for the current tab or {@code null} if there's no current tab or the current
      * tab doesn't have an associated browser content.
@@ -161,8 +135,8 @@
     private AutofillAssistantClient getOrCreateClient() {
         ThreadUtils.assertOnUiThread();
 
-        WebContents webContents = getWebContents();
-        Activity activity = getActivity();
+        WebContents webContents = mWebContentsSupplier.get();
+        Activity activity = getActivityFromWebContents(webContents);
         if (webContents == null || activity == null) {
             return null;
         }
@@ -171,6 +145,25 @@
                 webContents, mDependenciesFactory.createDependencies(activity));
     }
 
+    /**
+     * Looks up the Activity of the given web contents. This can be null. Should never be cached,
+     * because web contents can change activities, e.g., when user selects "Open in Chrome" menu
+     * item.
+     *
+     * @param webContents The web contents for which to lookup the Activity.
+     * @return Activity currently related to webContents. Could be <c>null</c> and could change,
+     *         therefore do not cache.
+     */
+    @Nullable
+    private static Activity getActivityFromWebContents(@Nullable WebContents webContents) {
+        if (webContents == null || webContents.isDestroyed()) return null;
+
+        WindowAndroid window = webContents.getTopLevelNativeWindow();
+        if (window == null) return null;
+
+        return window.getActivity().get();
+    }
+
     /** Extracts string arguments from a bundle. */
     private Map<String, String> toArgumentMap(Bundle bundle) {
         Map<String, String> map = new HashMap<>();
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
index 66b09f3f..b61fc680a 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
@@ -8,7 +8,7 @@
 import android.view.View;
 
 import org.chromium.base.annotations.UsedByReflection;
-import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.autofill_assistant.onboarding.OnboardingCoordinatorFactory;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
@@ -35,7 +35,7 @@
     public AutofillAssistantActionHandler createActionHandler(Context context,
             BottomSheetController bottomSheetController,
             BrowserControlsStateProvider browserControls, View rootView,
-            ActivityTabProvider activityTabProvider,
+            Supplier<WebContents> webContentsSupplier,
             AssistantDependenciesFactory dependenciesFactory) {
         AssistantStaticDependencies staticDependencies =
                 dependenciesFactory.createStaticDependencies();
@@ -43,6 +43,6 @@
                 new OnboardingCoordinatorFactory(context, bottomSheetController, browserControls,
                         rootView, staticDependencies.getAccessibilityUtil(),
                         staticDependencies.getInfoPageUtil()),
-                activityTabProvider, dependenciesFactory);
+                webContentsSupplier, dependenciesFactory);
     }
 }
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
index eb6861d..e89440e 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandlerTest.java
@@ -29,6 +29,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.Callback;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
@@ -42,6 +43,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /** Tests the direct actions exposed by AA. */
@@ -66,10 +68,13 @@
         mModuleEntryProvider = new TestingAutofillAssistantModuleEntryProvider();
         mModuleEntryProvider.setCannotInstall();
 
+        Supplier<WebContents> webContentsSupplier =
+                () -> mActivity.getActivityTabProvider().get().getWebContents();
+
         mHandler = new AutofillAssistantDirectActionHandler(mActivity, mBottomSheetController,
                 mActivity.getBrowserControlsManager(),
                 mActivity.getCompositorViewHolderForTesting(), mActivity.getActivityTabProvider(),
-                mModuleEntryProvider);
+                webContentsSupplier, mModuleEntryProvider);
 
         AutofillAssistantPreferencesUtil.removeOnboardingAcceptedPreference();
         AutofillAssistantPreferencesUtil.removeSkipInitScreenPreference();
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java
index 65f2c81..fed6e3bb 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java
@@ -8,7 +8,7 @@
 import android.view.View;
 
 import org.chromium.base.Callback;
-import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.autofill_assistant.onboarding.OnboardingCoordinatorFactory;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
@@ -36,13 +36,13 @@
         public MockAutofillAssistantActionHandler(Context context,
                 BottomSheetController bottomSheetController,
                 BrowserControlsStateProvider browserControls, View rootView,
-                ActivityTabProvider activityTabProvider,
+                Supplier<WebContents> webContentsSupplier,
                 AssistantDependenciesFactory dependenciesFactory) {
             super(new OnboardingCoordinatorFactory(context, bottomSheetController, browserControls,
                           rootView,
                           dependenciesFactory.createStaticDependencies().getAccessibilityUtil(),
                           dependenciesFactory.createStaticDependencies().getInfoPageUtil()),
-                    activityTabProvider, dependenciesFactory);
+                    webContentsSupplier, dependenciesFactory);
         }
 
         @Override
@@ -75,10 +75,10 @@
         public AutofillAssistantActionHandler createActionHandler(Context context,
                 BottomSheetController bottomSheetController,
                 BrowserControlsStateProvider browserControls, View rootView,
-                ActivityTabProvider activityTabProvider,
+                Supplier<WebContents> webContentsSupplier,
                 AssistantDependenciesFactory dependenciesFactory) {
             return new MockAutofillAssistantActionHandler(context, bottomSheetController,
-                    browserControls, rootView, activityTabProvider, dependenciesFactory);
+                    browserControls, rootView, webContentsSupplier, dependenciesFactory);
         }
     }
 
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
index ef837b4..81d006f2 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionHandler.java
@@ -12,6 +12,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.directactions.DirectActionHandler;
@@ -20,6 +21,7 @@
 import org.chromium.chrome.browser.directactions.DirectActionReporter.Type;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.content_public.browser.WebContents;
 
 /**
  * A handler that provides just enough functionality to allow on-demand loading of the module
@@ -41,6 +43,7 @@
     private final BrowserControlsStateProvider mBrowserControls;
     private final View mRootView;
     private final ActivityTabProvider mActivityTabProvider;
+    private final Supplier<WebContents> mWebContentsSupplier;
     private final AutofillAssistantModuleEntryProvider mModuleEntryProvider;
 
     @Nullable
@@ -49,13 +52,14 @@
     AutofillAssistantDirectActionHandler(Context context,
             BottomSheetController bottomSheetController,
             BrowserControlsStateProvider browserControls, View rootView,
-            ActivityTabProvider activityTabProvider,
+            ActivityTabProvider activityTabProvider, Supplier<WebContents> webContentsSupplier,
             AutofillAssistantModuleEntryProvider moduleEntryProvider) {
         mContext = context;
         mBottomSheetController = bottomSheetController;
         mBrowserControls = browserControls;
         mRootView = rootView;
         mActivityTabProvider = activityTabProvider;
+        mWebContentsSupplier = webContentsSupplier;
         mModuleEntryProvider = moduleEntryProvider;
     }
 
@@ -267,6 +271,6 @@
         if (entry == null) return null;
 
         return entry.createActionHandler(mContext, mBottomSheetController, mBrowserControls,
-                mRootView, mActivityTabProvider, entry.createDependenciesFactory());
+                mRootView, mWebContentsSupplier, entry.createDependenciesFactory());
     }
 }
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index 6322393..0a3c1fd7 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -17,6 +17,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.Function;
 import org.chromium.base.Log;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason;
@@ -26,6 +27,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.external_intents.ExternalNavigationDelegate.IntentToAutofillAllowingAppResult;
+import org.chromium.content_public.browser.WebContents;
 
 /** Facade for starting Autofill Assistant on a tab. */
 public class AutofillAssistantFacade {
@@ -121,8 +123,10 @@
             BottomSheetController bottomSheetController,
             BrowserControlsStateProvider browserControls, View rootView,
             ActivityTabProvider activityTabProvider) {
+        Supplier<WebContents> webContentsSupplier = () -> getWebContents(activityTabProvider);
+
         return new AutofillAssistantDirectActionHandler(context, bottomSheetController,
-                browserControls, rootView, activityTabProvider,
+                browserControls, rootView, activityTabProvider, webContentsSupplier,
                 AutofillAssistantModuleEntryProvider.INSTANCE);
     }
 
@@ -145,6 +149,16 @@
         });
     }
 
+    @Nullable
+    private static WebContents getWebContents(ActivityTabProvider activityTabProvider) {
+        Tab tab = activityTabProvider.get();
+        if (tab == null) {
+            return null;
+        }
+
+        return tab.getWebContents();
+    }
+
     public static boolean isAutofillAssistantEnabled(Intent intent) {
         return AssistantFeatures.AUTOFILL_ASSISTANT.isEnabled()
                 && AutofillAssistantFacade.isConfigured(
diff --git a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java
index 437db2b..4ecd60c 100644
--- a/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java
+++ b/chrome/android/features/autofill_assistant/public/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntry.java
@@ -7,7 +7,7 @@
 import android.content.Context;
 import android.view.View;
 
-import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.module_installer.builder.ModuleInterface;
@@ -40,12 +40,12 @@
      * @param bottomSheetController bottom sheet controller instance of the activity
      * @param browserControls provider of browser controls state
      * @param rootView root view of the activity
-     * @param activityTabProvider activity tab provider
+     * @param webContentsSupplier supplier of the current WebContents
      * @param dependenciesFactory creates platform-specific dependencies
      */
     AutofillAssistantActionHandler createActionHandler(Context context,
             BottomSheetController bottomSheetController,
             BrowserControlsStateProvider browserControls, View rootView,
-            ActivityTabProvider activityTabProvider,
+            Supplier<WebContents> webContentsSupplier,
             AssistantDependenciesFactory dependenciesFactory);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
index 7c8f299..63b2387 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
@@ -206,11 +206,11 @@
             // Incremental install disables process isolation, so things in this block will
             // actually be run for incremental apks, but not normal apks.
             PureJavaExceptionHandler.installHandler(() -> {
-                // PureJavaExceptionReporter may be in the chrome module, so load by reflection
-                // from there.
+                // ChromePureJavaExceptionReporter may be in the chrome module, so load by
+                // reflection from there.
                 return (JavaExceptionReporter) SplitCompatUtils.newInstance(
                         SplitCompatUtils.createChromeContext(ContextUtils.getApplicationContext()),
-                        "org.chromium.chrome.browser.crash.PureJavaExceptionReporter");
+                        "org.chromium.chrome.browser.crash.ChromePureJavaExceptionReporter");
             });
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java
new file mode 100644
index 0000000..b55b198
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java
@@ -0,0 +1,56 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.crash;
+
+import org.chromium.base.annotations.MainDex;
+import org.chromium.base.annotations.UsedByReflection;
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
+import org.chromium.components.crash.PureJavaExceptionReporter;
+
+import java.io.File;
+
+/**
+ * A custom PureJavaExceptionReporter for Android Chrome's browser.
+ */
+@MainDex
+@UsedByReflection("SplitCompatApplication.java")
+public class ChromePureJavaExceptionReporter extends PureJavaExceptionReporter {
+    private static final String CHROME_CRASH_PRODUCT_NAME = "Chrome_Android";
+
+    @UsedByReflection("SplitCompatApplication.java")
+    public ChromePureJavaExceptionReporter() {}
+
+    @Override
+    protected String getProductName() {
+        return CHROME_CRASH_PRODUCT_NAME;
+    }
+
+    @Override
+    protected void uploadMinidump(File minidump) {
+        LogcatExtractionRunnable.uploadMinidump(minidump, true);
+    }
+
+    /**
+     * Report and upload the device info and stack trace as if it was a crash. Runs synchronously
+     * and results in I/O on the main thread.
+     *
+     * @param javaException The exception to report.
+     */
+    public static void reportJavaException(Throwable javaException) {
+        ChromePureJavaExceptionReporter reporter = new ChromePureJavaExceptionReporter();
+        reporter.createAndUploadReport(javaException);
+    }
+
+    /**
+     * Posts a task to report and upload the device info and stack trace as if it was a crash.
+     *
+     * @param javaException The exception to report.
+     */
+    public static void postReportJavaException(Throwable javaException) {
+        PostTask.postTask(
+                TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> reportJavaException(javaException));
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java
index f3e1d24..fd8d1036 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java
@@ -41,24 +41,25 @@
 
     @Override
     public void run() {
-        uploadMinidumpWithLogcat(false);
+        File fileToUpload = mLogcatExtractor.attachLogcatToMinidump(mMinidumpFile);
+        uploadMinidump(fileToUpload, false);
     }
 
     /**
+     * @param minidump the minidump file to be uploaded.
      * @param uploadNow If this flag is set to true, we will upload the minidump immediately,
      * otherwise the upload is controlled by the job scheduler.
      */
-    /* package */ void uploadMinidumpWithLogcat(boolean uploadNow) {
-        File fileToUpload = mLogcatExtractor.attachLogcatToMinidump(mMinidumpFile);
+    /* package */ static void uploadMinidump(File minidump, boolean uploadNow) {
         // Regardless of success, initiate the upload. That way, even if there are errors augmenting
         // the minidump with logcat data, the service can still upload the unaugmented minidump.
         try {
             if (uploadNow) {
-                MinidumpUploadServiceImpl.tryUploadCrashDumpNow(fileToUpload);
+                MinidumpUploadServiceImpl.tryUploadCrashDumpNow(minidump);
             } else if (MinidumpUploadServiceImpl.shouldUseJobSchedulerForUploads()) {
                 MinidumpUploadServiceImpl.scheduleUploadJob();
             } else {
-                MinidumpUploadServiceImpl.tryUploadCrashDump(fileToUpload);
+                MinidumpUploadServiceImpl.tryUploadCrashDump(minidump);
             }
         } catch (SecurityException e) {
             Log.w(TAG, e.toString());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
index dbf31ec..1542afc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
@@ -4,81 +4,12 @@
 
 package org.chromium.chrome.browser.crash;
 
-import android.annotation.SuppressLint;
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.content.Context;
-import android.os.Build;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.BuildInfo;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.PiiElider;
-import org.chromium.base.StrictModeContext;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.annotations.UsedByReflection;
-import org.chromium.base.task.PostTask;
-import org.chromium.base.task.TaskTraits;
-import org.chromium.components.crash.CrashKeys;
-import org.chromium.components.crash.PureJavaExceptionHandler;
-import org.chromium.components.version_info.VersionInfo;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicReferenceArray;
-
 /**
- * Creates a crash report and uploads it to crash server if there is a Java exception.
- *
- * This class is written in pure Java, so it can handle exception happens before native is loaded.
+ * This class has been moved to //components/crash/android.
  */
-@MainDex
-@UsedByReflection("PureJavaExceptionHandler.java")
-public class PureJavaExceptionReporter implements PureJavaExceptionHandler.JavaExceptionReporter {
-    // report fields, please keep the name sync with MIME blocks in breakpad_linux.cc
-    public static final String CHANNEL = "channel";
-    public static final String VERSION = "ver";
-    public static final String PRODUCT = "prod";
-    public static final String ANDROID_BUILD_ID = "android_build_id";
-    public static final String ANDROID_BUILD_FP = "android_build_fp";
-    public static final String SDK = "sdk";
-    public static final String DEVICE = "device";
-    public static final String GMS_CORE_VERSION = "gms_core_version";
-    public static final String INSTALLER_PACKAGE_NAME = "installer_package_name";
-    public static final String ABI_NAME = "abi_name";
-    public static final String PACKAGE = "package";
-    public static final String MODEL = "model";
-    public static final String BRAND = "brand";
-    public static final String BOARD = "board";
-    public static final String EXCEPTION_INFO = "exception_info";
-    public static final String PROCESS_TYPE = "ptype";
-    public static final String EARLY_JAVA_EXCEPTION = "early_java_exception";
-    public static final String CUSTOM_THEMES = "custom_themes";
-    public static final String RESOURCES_VERSION = "resources_version";
-
-    private static final String DUMP_LOCATION_SWITCH = "breakpad-dump-location";
-    private static final String CRASH_DUMP_DIR = "Crash Reports";
-    private static final String FILE_PREFIX = "chromium-browser-minidump-";
-    private static final String FILE_SUFFIX = ".dmp";
-    private static final String RN = "\r\n";
-    private static final String FORM_DATA_MESSAGE = "Content-Disposition: form-data; name=\"";
-
-    private boolean mUpload;
-    protected File mMinidumpFile;
-    private FileOutputStream mMinidumpFileStream;
-    private final String mLocalId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
-    private final String mBoundary = "------------" + UUID.randomUUID() + RN;
-
-    @UsedByReflection("PureJavaExceptionHandler.java")
-    public PureJavaExceptionReporter() {}
-
+// TODO(crbug.com/1081916): Remove this after migrating downstream deps to use
+// ChromePureJavaExceptionReporter.
+public class PureJavaExceptionReporter {
     /**
      * Report and upload the device info and stack trace as if it was a crash. Runs synchronously
      * and results in I/O on the main thread.
@@ -86,8 +17,7 @@
      * @param javaException The exception to report.
      */
     public static void reportJavaException(Throwable javaException) {
-        PureJavaExceptionReporter reporter = new PureJavaExceptionReporter();
-        reporter.createAndUploadReport(javaException);
+        ChromePureJavaExceptionReporter.reportJavaException(javaException);
     }
 
     /**
@@ -96,147 +26,6 @@
      * @param javaException The exception to report.
      */
     public static void postReportJavaException(Throwable javaException) {
-        PostTask.postTask(
-                TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> reportJavaException(javaException));
-    }
-
-    @Override
-    public void createAndUploadReport(Throwable javaException) {
-        // It is OK to do IO in main thread when we know there is a crash happens.
-        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
-            createReport(javaException);
-            flushToFile();
-            uploadReport();
-        }
-    }
-
-    @VisibleForTesting
-    File getMinidumpFile() {
-        return mMinidumpFile;
-    }
-
-    private void addPairedString(String messageType, String messageData) {
-        addString(mBoundary);
-        addString(FORM_DATA_MESSAGE + messageType + "\"");
-        addString(RN + RN + messageData + RN);
-    }
-
-    private void addString(String s) {
-        try {
-            mMinidumpFileStream.write(ApiCompatibilityUtils.getBytesUtf8(s));
-        } catch (IOException e) {
-            // Nothing we can do here.
-        }
-    }
-
-    @SuppressLint("WrongConstant")
-    private void createReport(Throwable javaException) {
-        try {
-            String minidumpFileName = FILE_PREFIX + mLocalId + FILE_SUFFIX;
-            File minidumpDir =
-                    new File(ContextUtils.getApplicationContext().getCacheDir(), CRASH_DUMP_DIR);
-            // Tests disable minidump uploading by not creating the minidump directory.
-            mUpload = minidumpDir.exists();
-            String overrideMinidumpDirPath =
-                    CommandLine.getInstance().getSwitchValue(DUMP_LOCATION_SWITCH);
-            if (overrideMinidumpDirPath != null) {
-                minidumpDir = new File(overrideMinidumpDirPath);
-                minidumpDir.mkdirs();
-            }
-            mMinidumpFile = new File(minidumpDir, minidumpFileName);
-            mMinidumpFileStream = new FileOutputStream(mMinidumpFile);
-        } catch (FileNotFoundException e) {
-            mMinidumpFile = null;
-            mMinidumpFileStream = null;
-            return;
-        }
-        String processName = detectCurrentProcessName();
-        if (processName == null || !processName.contains(":")) {
-            processName = "browser";
-        }
-
-        BuildInfo buildInfo = BuildInfo.getInstance();
-        addPairedString(PRODUCT, "Chrome_Android");
-        addPairedString(PROCESS_TYPE, processName);
-        addPairedString(DEVICE, Build.DEVICE);
-        addPairedString(VERSION, VersionInfo.getProductVersion());
-        addPairedString(CHANNEL, getChannel());
-        addPairedString(ANDROID_BUILD_ID, Build.ID);
-        addPairedString(MODEL, Build.MODEL);
-        addPairedString(BRAND, Build.BRAND);
-        addPairedString(BOARD, Build.BOARD);
-        addPairedString(ANDROID_BUILD_FP, buildInfo.androidBuildFingerprint);
-        addPairedString(SDK, String.valueOf(Build.VERSION.SDK_INT));
-        addPairedString(GMS_CORE_VERSION, buildInfo.gmsVersionCode);
-        addPairedString(INSTALLER_PACKAGE_NAME, buildInfo.installerPackageName);
-        addPairedString(ABI_NAME, buildInfo.abiString);
-        addPairedString(EXCEPTION_INFO,
-                PiiElider.sanitizeStacktrace(Log.getStackTraceString(javaException)));
-        addPairedString(EARLY_JAVA_EXCEPTION, "true");
-        addPairedString(PACKAGE,
-                String.format("%s v%s (%s)", BuildInfo.getFirebaseAppId(), buildInfo.versionCode,
-                        buildInfo.versionName));
-        addPairedString(CUSTOM_THEMES, buildInfo.customThemes);
-        addPairedString(RESOURCES_VERSION, buildInfo.resourcesVersion);
-
-        AtomicReferenceArray<String> values = CrashKeys.getInstance().getValues();
-        for (int i = 0; i < values.length(); i++) {
-            String value = values.get(i);
-            if (value != null) addPairedString(CrashKeys.getKey(i), value);
-        }
-
-        addString(mBoundary);
-    }
-
-    private void flushToFile() {
-        if (mMinidumpFileStream != null) {
-            try {
-                mMinidumpFileStream.flush();
-                mMinidumpFileStream.close();
-            } catch (Throwable e) {
-                mMinidumpFileStream = null;
-                mMinidumpFile = null;
-            }
-        }
-    }
-
-    private static String getChannel() {
-        if (VersionInfo.isCanaryBuild()) {
-            return "canary";
-        }
-        if (VersionInfo.isDevBuild()) {
-            return "dev";
-        }
-        if (VersionInfo.isBetaBuild()) {
-            return "beta";
-        }
-        // An empty string indicates the stable channel.
-        return "";
-    }
-
-    private static String detectCurrentProcessName() {
-        try {
-            int pid = android.os.Process.myPid();
-
-            ActivityManager manager =
-                    (ActivityManager) ContextUtils.getApplicationContext().getSystemService(
-                            Context.ACTIVITY_SERVICE);
-            for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
-                if (processInfo.pid == pid) {
-                    return processInfo.processName;
-                }
-            }
-            return null;
-        } catch (SecurityException e) {
-            return null;
-        }
-    }
-
-    @VisibleForTesting
-    public void uploadReport() {
-        if (mMinidumpFile == null || !mUpload) return;
-        LogcatExtractionRunnable logcatExtractionRunnable =
-                new LogcatExtractionRunnable(mMinidumpFile);
-        logcatExtractionRunnable.uploadMinidumpWithLogcat(true);
+        ChromePureJavaExceptionReporter.postReportJavaException(javaException);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
index fba32e3..86e2af0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -60,8 +60,6 @@
     private final Map<String, Integer> mTitleToItemIdMap = new HashMap<String, Integer>();
     private final Map<Integer, Integer> mItemIdToIndexMap = new HashMap<Integer, Integer>();
 
-    private boolean mIsCustomEntryAdded;
-
     /**
      * Creates an {@link CustomTabAppMenuPropertiesDelegate} instance.
      */
@@ -205,14 +203,11 @@
                 openInChromeItem.setVisible(false);
             }
 
-            // Add custom menu items. Make sure they are only added once.
-            if (!mIsCustomEntryAdded) {
-                mIsCustomEntryAdded = true;
-                for (int i = 0; i < mMenuEntries.size(); i++) {
-                    MenuItem item = menu.add(0, 0, 1, mMenuEntries.get(i));
-                    mTitleToItemIdMap.put(mMenuEntries.get(i), item.getItemId());
-                    mItemIdToIndexMap.put(item.getItemId(), i);
-                }
+            // Add custom menu items.
+            for (int i = 0; i < mMenuEntries.size(); i++) {
+                MenuItem item = menu.add(0, i, 1, mMenuEntries.get(i));
+                mTitleToItemIdMap.put(mMenuEntries.get(i), item.getItemId());
+                mItemIdToIndexMap.put(item.getItemId(), i);
             }
 
             updateRequestDesktopSiteMenuItem(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
index 99f17fc..fd69cc5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java
@@ -41,7 +41,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.IntentHandler;
@@ -288,7 +287,6 @@
 
     @Test
     @SmallTest
-    @FlakyTest(message = "crbug.com/1285271")
     public void testSupervisedUser() throws Exception {
         final HistoryManagerToolbar toolbar = mHistoryManager.getToolbarForTests();
         final HistoryItemView item = (HistoryItemView) getItemView(2);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java
index 8fac2c1..8301bae 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/RequestGeneratorTest.java
@@ -24,6 +24,7 @@
 import org.chromium.base.FeatureList;
 import org.chromium.base.test.util.AdvancedMockContext;
 import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.uid.SettingsSecureBasedIdentificationGenerator;
@@ -139,6 +140,7 @@
 
     @Test
     @SmallTest
+    @FlakyTest(message = "crbug.com/1285536")
     @Feature({"Omaha"})
     public void testXMLCreationWithUID() {
         FeatureList.TestValues overrides = new FeatureList.TestValues();
diff --git a/chrome/browser/apps/app_service/app_service_proxy_ash.cc b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
index 5b0fce3..ddada5a 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_ash.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
@@ -474,8 +474,8 @@
     const apps::AppUpdate& update,
     apps::mojom::LaunchSource launch_source,
     apps::mojom::LaunchContainer container) {
-  RecordAppLaunchMetrics(profile, update.AppType(), update.AppId(),
-                         launch_source, container);
+  RecordAppLaunchMetrics(profile, ConvertMojomAppTypToAppType(update.AppType()),
+                         update.AppId(), launch_source, container);
 }
 
 void AppServiceProxyAsh::InitAppPlatformMetrics() {
@@ -492,7 +492,7 @@
   if (app_platform_metrics_service_ &&
       app_platform_metrics_service_->AppPlatformMetrics()) {
     app_platform_metrics_service_->AppPlatformMetrics()->RecordAppUninstallUkm(
-        app_type, app_id, uninstall_source);
+        ConvertMojomAppTypToAppType(app_type), app_id, uninstall_source);
   }
 }
 
diff --git a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
index b759ea7..f46889d24 100644
--- a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
+++ b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
@@ -284,7 +284,7 @@
 
   web_app::AppId InstallWebApp(const std::string& start_url,
                                blink::mojom::DisplayMode user_display_mode) {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = GURL(start_url);
     info->user_display_mode = user_display_mode;
     Profile* profile = ProfileManager::GetPrimaryUserProfile();
diff --git a/chrome/browser/apps/app_service/browser_app_launcher.cc b/chrome/browser/apps/app_service/browser_app_launcher.cc
index e0fb659..39b8633 100644
--- a/chrome/browser/apps/app_service/browser_app_launcher.cc
+++ b/chrome/browser/apps/app_service/browser_app_launcher.cc
@@ -23,6 +23,7 @@
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/full_restore_save_handler.h"
 #include "components/app_restore/full_restore_utils.h"
+#include "components/services/app_service/public/cpp/app_types.h"
 #include "components/sessions/core/session_id.h"
 #endif
 
@@ -57,12 +58,12 @@
         web_app_launch_manager_.OpenApplication(std::move(params));
 
     if (!SessionID::IsValidValue(restore_id)) {
-      RecordAppLaunchMetrics(profile_, apps::mojom::AppType::kWeb, app_id,
+      RecordAppLaunchMetrics(profile_, apps::AppType::kWeb, app_id,
                              launch_source, container);
       return web_contents;
     }
 
-    RecordAppLaunchMetrics(profile_, apps::mojom::AppType::kWeb, app_id,
+    RecordAppLaunchMetrics(profile_, apps::AppType::kWeb, app_id,
                            apps::mojom::LaunchSource::kFromFullRestore,
                            container);
 
@@ -91,9 +92,9 @@
   // If the restore id is available, save the launch parameters to the full
   // restore file.
   if (SessionID::IsValidValue(params.restore_id)) {
-    RecordAppLaunchMetrics(
-        profile_, apps::mojom::AppType::kChromeApp, params.app_id,
-        apps::mojom::LaunchSource::kFromFullRestore, params.container);
+    RecordAppLaunchMetrics(profile_, apps::AppType::kChromeApp, params.app_id,
+                           apps::mojom::LaunchSource::kFromFullRestore,
+                           params.container);
 
     AppLaunchParams params_for_restore(params.app_id, params.container,
                                        params.disposition, params.launch_source,
@@ -108,9 +109,8 @@
     full_restore::SaveAppLaunchInfo(profile_->GetPath(),
                                     std::move(launch_info));
   } else {
-    RecordAppLaunchMetrics(profile_, apps::mojom::AppType::kChromeApp,
-                           params.app_id, params.launch_source,
-                           params.container);
+    RecordAppLaunchMetrics(profile_, apps::AppType::kChromeApp, params.app_id,
+                           params.launch_source, params.container);
   }
 #endif
 
diff --git a/chrome/browser/apps/app_service/media_access_browsertest.cc b/chrome/browser/apps/app_service/media_access_browsertest.cc
index f6bc1ab..39906be4 100644
--- a/chrome/browser/apps/app_service/media_access_browsertest.cc
+++ b/chrome/browser/apps/app_service/media_access_browsertest.cc
@@ -396,7 +396,7 @@
   ~MediaAccessWebAppsTest() override = default;
 
   std::string CreateWebApp(const GURL& url) const {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->scope = url;
     return web_app::test::InstallWebApp(browser()->profile(),
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.cc b/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.cc
index 16ad0d3..6f72f37 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.cc
@@ -154,7 +154,7 @@
 }
 
 void AppPlatformInputMetrics::SetAppInfoForActivatedWindow(
-    mojom::AppType app_type,
+    AppType app_type,
     const std::string& app_id,
     aura::Window* window,
     const base::UnguessableToken& instance_id) {
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.h b/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.h
index b8b5b4c..9918f0a 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_input_metrics.h
@@ -75,7 +75,7 @@
   void OnAppRegistryCacheWillBeDestroyed(AppRegistryCache* cache) override;
   void OnAppUpdate(const AppUpdate& update) override;
 
-  void SetAppInfoForActivatedWindow(mojom::AppType app_type,
+  void SetAppInfoForActivatedWindow(AppType app_type,
                                     const std::string& app_id,
                                     aura::Window* window,
                                     const base::UnguessableToken& instance_id);
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
index 1dbce63..8d7e7c2 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
-#include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/app_update.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "components/ukm/app_source_url_recorder.h"
@@ -100,22 +99,22 @@
 
 // Returns AppTypeNameV2 used for app running metrics.
 apps::AppTypeNameV2 GetAppTypeNameV2(Profile* profile,
-                                     apps::mojom::AppType app_type,
+                                     apps::AppType app_type,
                                      const std::string& app_id,
                                      aura::Window* window) {
   switch (app_type) {
-    case apps::mojom::AppType::kUnknown:
+    case apps::AppType::kUnknown:
       return apps::AppTypeNameV2::kUnknown;
-    case apps::mojom::AppType::kArc:
+    case apps::AppType::kArc:
       return apps::AppTypeNameV2::kArc;
-    case apps::mojom::AppType::kBuiltIn:
+    case apps::AppType::kBuiltIn:
       return apps::AppTypeNameV2::kBuiltIn;
-    case apps::mojom::AppType::kCrostini:
+    case apps::AppType::kCrostini:
       return apps::AppTypeNameV2::kCrostini;
-    case apps::mojom::AppType::kChromeApp:
+    case apps::AppType::kChromeApp:
       return apps::IsBrowser(window) ? apps::AppTypeNameV2::kChromeAppTab
                                      : apps::AppTypeNameV2::kChromeAppWindow;
-    case apps::mojom::AppType::kWeb: {
+    case apps::AppType::kWeb: {
       apps::AppTypeName app_type_name =
           apps::GetAppTypeNameForWebAppWindow(profile, app_id, window);
       if (app_type_name == apps::AppTypeName::kChromeBrowser) {
@@ -126,44 +125,44 @@
         return apps::AppTypeNameV2::kWebWindow;
       }
     }
-    case apps::mojom::AppType::kMacOs:
+    case apps::AppType::kMacOs:
       return apps::AppTypeNameV2::kMacOs;
-    case apps::mojom::AppType::kPluginVm:
+    case apps::AppType::kPluginVm:
       return apps::AppTypeNameV2::kPluginVm;
-    case apps::mojom::AppType::kStandaloneBrowser:
+    case apps::AppType::kStandaloneBrowser:
       return apps::AppTypeNameV2::kStandaloneBrowser;
-    case apps::mojom::AppType::kRemote:
+    case apps::AppType::kRemote:
       return apps::AppTypeNameV2::kRemote;
-    case apps::mojom::AppType::kBorealis:
+    case apps::AppType::kBorealis:
       return apps::AppTypeNameV2::kBorealis;
-    case apps::mojom::AppType::kSystemWeb:
+    case apps::AppType::kSystemWeb:
       return apps::AppTypeNameV2::kSystemWeb;
-    case apps::mojom::AppType::kStandaloneBrowserChromeApp:
+    case apps::AppType::kStandaloneBrowserChromeApp:
       return apps::AppTypeNameV2::kStandaloneBrowserChromeApp;
-    case apps::mojom::AppType::kExtension:
+    case apps::AppType::kExtension:
       return apps::AppTypeNameV2::kExtension;
   }
 }
 
 // Returns AppTypeNameV2 used for app launch metrics.
 apps::AppTypeNameV2 GetAppTypeNameV2(Profile* profile,
-                                     apps::mojom::AppType app_type,
+                                     apps::AppType app_type,
                                      const std::string& app_id,
                                      apps::mojom::LaunchContainer container) {
   switch (app_type) {
-    case apps::mojom::AppType::kUnknown:
+    case apps::AppType::kUnknown:
       return apps::AppTypeNameV2::kUnknown;
-    case apps::mojom::AppType::kArc:
+    case apps::AppType::kArc:
       return apps::AppTypeNameV2::kArc;
-    case apps::mojom::AppType::kBuiltIn:
+    case apps::AppType::kBuiltIn:
       return apps::AppTypeNameV2::kBuiltIn;
-    case apps::mojom::AppType::kCrostini:
+    case apps::AppType::kCrostini:
       return apps::AppTypeNameV2::kCrostini;
-    case apps::mojom::AppType::kChromeApp:
+    case apps::AppType::kChromeApp:
       return container == apps::mojom::LaunchContainer::kLaunchContainerWindow
                  ? apps::AppTypeNameV2::kChromeAppWindow
                  : apps::AppTypeNameV2::kChromeAppTab;
-    case apps::mojom::AppType::kWeb: {
+    case apps::AppType::kWeb: {
       apps::AppTypeName app_type_name =
           apps::GetAppTypeNameForWebApp(profile, app_id, container);
       if (app_type_name == apps::AppTypeName::kChromeBrowser) {
@@ -174,21 +173,21 @@
         return apps::AppTypeNameV2::kWebWindow;
       }
     }
-    case apps::mojom::AppType::kMacOs:
+    case apps::AppType::kMacOs:
       return apps::AppTypeNameV2::kMacOs;
-    case apps::mojom::AppType::kPluginVm:
+    case apps::AppType::kPluginVm:
       return apps::AppTypeNameV2::kPluginVm;
-    case apps::mojom::AppType::kStandaloneBrowser:
+    case apps::AppType::kStandaloneBrowser:
       return apps::AppTypeNameV2::kStandaloneBrowser;
-    case apps::mojom::AppType::kRemote:
+    case apps::AppType::kRemote:
       return apps::AppTypeNameV2::kRemote;
-    case apps::mojom::AppType::kBorealis:
+    case apps::AppType::kBorealis:
       return apps::AppTypeNameV2::kBorealis;
-    case apps::mojom::AppType::kSystemWeb:
+    case apps::AppType::kSystemWeb:
       return apps::AppTypeNameV2::kSystemWeb;
-    case apps::mojom::AppType::kStandaloneBrowserChromeApp:
+    case apps::AppType::kStandaloneBrowserChromeApp:
       return apps::AppTypeNameV2::kStandaloneBrowserChromeApp;
-    case apps::mojom::AppType::kExtension:
+    case apps::AppType::kExtension:
       return apps::AppTypeNameV2::kExtension;
   }
 }
@@ -334,11 +333,11 @@
 }
 
 void RecordAppLaunchMetrics(Profile* profile,
-                            apps::mojom::AppType app_type,
+                            AppType app_type,
                             const std::string& app_id,
                             apps::mojom::LaunchSource launch_source,
                             apps::mojom::LaunchContainer container) {
-  if (app_type == apps::mojom::AppType::kUnknown) {
+  if (app_type == AppType::kUnknown) {
     return;
   }
 
@@ -384,20 +383,20 @@
   }
 
   ukm::SourceId source_id = ukm::kInvalidSourceId;
-  apps::mojom::AppType app_type = GetAppType(profile, app_id);
-  if (!ShouldRecordUkmForAppTypeName(ConvertMojomAppTypToAppType(app_type))) {
+  AppType app_type = GetAppType(profile, app_id);
+  if (!ShouldRecordUkmForAppTypeName(app_type)) {
     return ukm::kInvalidSourceId;
   }
 
   switch (app_type) {
-    case apps::mojom::AppType::kBuiltIn:
-    case apps::mojom::AppType::kChromeApp:
-    case apps::mojom::AppType::kExtension:
+    case AppType::kBuiltIn:
+    case AppType::kChromeApp:
+    case AppType::kExtension:
       source_id = ukm::AppSourceUrlRecorder::GetSourceIdForChromeApp(app_id);
       break;
-    case apps::mojom::AppType::kArc:
-    case apps::mojom::AppType::kWeb:
-    case apps::mojom::AppType::kSystemWeb: {
+    case AppType::kArc:
+    case AppType::kWeb:
+    case AppType::kSystemWeb: {
       std::string publisher_id;
       apps::mojom::InstallReason install_reason;
       apps::AppServiceProxyFactory::GetForProfile(profile)
@@ -410,12 +409,12 @@
       if (publisher_id.empty()) {
         return ukm::kInvalidSourceId;
       }
-      if (app_type == apps::mojom::AppType::kArc) {
+      if (app_type == AppType::kArc) {
         source_id = ukm::AppSourceUrlRecorder::GetSourceIdForArcPackageName(
             publisher_id);
         break;
       }
-      if (app_type == apps::mojom::AppType::kSystemWeb ||
+      if (app_type == AppType::kSystemWeb ||
           install_reason == apps::mojom::InstallReason::kSystem) {
         // For system web apps, call GetSourceIdForChromeApp to record the app
         // id because the url could be filtered by the server side.
@@ -426,18 +425,18 @@
           ukm::AppSourceUrlRecorder::GetSourceIdForPWA(GURL(publisher_id));
       break;
     }
-    case apps::mojom::AppType::kCrostini:
+    case AppType::kCrostini:
       source_id = GetSourceIdForCrostini(profile, app_id);
       break;
-    case apps::mojom::AppType::kBorealis:
+    case AppType::kBorealis:
       source_id = GetSourceIdForBorealis(profile, app_id);
       break;
-    case apps::mojom::AppType::kUnknown:
-    case apps::mojom::AppType::kMacOs:
-    case apps::mojom::AppType::kPluginVm:
-    case apps::mojom::AppType::kStandaloneBrowser:
-    case apps::mojom::AppType::kStandaloneBrowserChromeApp:
-    case apps::mojom::AppType::kRemote:
+    case AppType::kUnknown:
+    case AppType::kMacOs:
+    case AppType::kPluginVm:
+    case AppType::kStandaloneBrowser:
+    case AppType::kStandaloneBrowserChromeApp:
+    case AppType::kRemote:
       return ukm::kInvalidSourceId;
   }
   return source_id;
@@ -595,12 +594,11 @@
 }
 
 void AppPlatformMetrics::RecordAppLaunchUkm(
-    apps::mojom::AppType app_type,
+    AppType app_type,
     const std::string& app_id,
     apps::mojom::LaunchSource launch_source,
     apps::mojom::LaunchContainer container) {
-  if (app_type == apps::mojom::AppType::kUnknown ||
-      !ShouldRecordUkm(profile_)) {
+  if (app_type == AppType::kUnknown || !ShouldRecordUkm(profile_)) {
     return;
   }
 
@@ -621,7 +619,7 @@
 }
 
 void AppPlatformMetrics::RecordAppUninstallUkm(
-    apps::mojom::AppType app_type,
+    AppType app_type,
     const std::string& app_id,
     apps::mojom::UninstallSource uninstall_source) {
   AppTypeName app_type_name =
@@ -677,7 +675,7 @@
 
   auto app_id = update.AppId();
   auto app_type = GetAppType(profile_, app_id);
-  if (app_type == apps::mojom::AppType::kUnknown) {
+  if (app_type == AppType::kUnknown) {
     return;
   }
 
@@ -790,15 +788,14 @@
     // The browser window is activated, start calculating the browser window
     // running time.
     // TODO(crbug.com/1251501): Handle lacros window.
-    SetWindowActivated(apps::mojom::AppType::kChromeApp,
-                       AppTypeName::kChromeBrowser,
+    SetWindowActivated(AppType::kChromeApp, AppTypeName::kChromeBrowser,
                        AppTypeNameV2::kChromeBrowser,
                        extension_misc::kChromeAppId, browser_id);
   }
 }
 
 void AppPlatformMetrics::SetWindowActivated(
-    apps::mojom::AppType app_type,
+    AppType app_type,
     AppTypeName app_type_name,
     AppTypeNameV2 app_type_name_v2,
     const std::string& app_id,
@@ -916,9 +913,9 @@
           return;
         }
 
-        AppTypeName app_type_name =
-            GetAppTypeName(profile_, update.AppType(), update.AppId(),
-                           apps::mojom::LaunchContainer::kLaunchContainerNone);
+        AppTypeName app_type_name = GetAppTypeName(
+            profile_, ConvertMojomAppTypToAppType(update.AppType()),
+            update.AppId(), apps::mojom::LaunchContainer::kLaunchContainerNone);
 
         if (app_type_name == AppTypeName::kChromeBrowser ||
             app_type_name == AppTypeName::kUnknown) {
@@ -1055,9 +1052,9 @@
 
 void AppPlatformMetrics::RecordAppsInstallUkm(const apps::AppUpdate& update,
                                               InstallTime install_time) {
-  AppTypeName app_type_name =
-      GetAppTypeName(profile_, update.AppType(), update.AppId(),
-                     apps::mojom::LaunchContainer::kLaunchContainerNone);
+  AppTypeName app_type_name = GetAppTypeName(
+      profile_, ConvertMojomAppTypToAppType(update.AppType()), update.AppId(),
+      apps::mojom::LaunchContainer::kLaunchContainerNone);
 
   ukm::SourceId source_id = GetSourceId(profile_, update.AppId());
   if (source_id == ukm::kInvalidSourceId) {
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
index 4b90f0e..a42caa1 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h"
 #include "chrome/browser/apps/app_service/metrics/browser_to_tab_list.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
+#include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/instance_registry.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -64,7 +65,7 @@
 
 // Records metrics when launching apps.
 void RecordAppLaunchMetrics(Profile* profile,
-                            apps::mojom::AppType app_type,
+                            AppType app_type,
                             const std::string& app_id,
                             apps::mojom::LaunchSource launch_source,
                             apps::mojom::LaunchContainer container);
@@ -128,13 +129,13 @@
   void OnFiveMinutes();
 
   // Records UKM when launching an app.
-  void RecordAppLaunchUkm(apps::mojom::AppType app_type,
+  void RecordAppLaunchUkm(AppType app_type,
                           const std::string& app_id,
                           apps::mojom::LaunchSource launch_source,
                           apps::mojom::LaunchContainer container);
 
   // Records UKM when uninstalling an app.
-  void RecordAppUninstallUkm(apps::mojom::AppType app_type,
+  void RecordAppUninstallUkm(AppType app_type,
                              const std::string& app_id,
                              apps::mojom::UninstallSource uninstall_source);
 
@@ -176,7 +177,7 @@
   // inactivated.
   void UpdateBrowserWindowStatus(const InstanceUpdate& update);
 
-  void SetWindowActivated(apps::mojom::AppType app_type,
+  void SetWindowActivated(AppType app_type,
                           AppTypeName app_type_name,
                           AppTypeNameV2 app_type_name_v2,
                           const std::string& app_id,
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc
index 979323c..9f85ba1 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc
@@ -29,7 +29,7 @@
   AppId InstallWebApp(const GURL& start_url,
                       blink::mojom::DisplayMode display_mode,
                       blink::mojom::DisplayMode user_display_mode) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->display_mode = display_mode;
@@ -48,14 +48,13 @@
 
   apps::AppTypeName GetWebAppTypeName(const std::string& app_id,
                                       apps::mojom::LaunchContainer container) {
-    return GetAppTypeName(profile(), apps::mojom::AppType::kWeb, app_id,
-                          container);
+    return GetAppTypeName(profile(), apps::AppType::kWeb, app_id, container);
   }
 
   apps::AppTypeName GetSystemWebAppTypeName(
       const std::string& app_id,
       apps::mojom::LaunchContainer container) {
-    return GetAppTypeName(profile(), apps::mojom::AppType::kSystemWeb, app_id,
+    return GetAppTypeName(profile(), apps::AppType::kSystemWeb, app_id,
                           container);
   }
 
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.cc
index 67c0038..30775e4 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.cc
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.cc
@@ -143,15 +143,14 @@
 }
 
 bool IsAppOpenedWithBrowserWindow(Profile* profile,
-                                  apps::mojom::AppType app_type,
+                                  AppType app_type,
                                   const std::string& app_id) {
-  if (app_type == mojom::AppType::kWeb ||
-      app_type == mojom::AppType::kSystemWeb ||
-      app_type == mojom::AppType::kExtension) {
+  if (app_type == AppType::kWeb || app_type == AppType::kSystemWeb ||
+      app_type == AppType::kExtension) {
     return true;
   }
 
-  if (app_type != mojom::AppType::kChromeApp) {
+  if (app_type != AppType::kChromeApp) {
     return false;
   }
 
@@ -183,38 +182,38 @@
 }
 
 AppTypeName GetAppTypeNameForWindow(Profile* profile,
-                                    apps::mojom::AppType app_type,
+                                    AppType app_type,
                                     const std::string& app_id,
                                     aura::Window* window) {
   switch (app_type) {
-    case apps::mojom::AppType::kUnknown:
+    case AppType::kUnknown:
       return apps::AppTypeName::kUnknown;
-    case apps::mojom::AppType::kArc:
+    case AppType::kArc:
       return apps::AppTypeName::kArc;
-    case apps::mojom::AppType::kBuiltIn:
+    case AppType::kBuiltIn:
       return apps::AppTypeName::kBuiltIn;
-    case apps::mojom::AppType::kCrostini:
+    case AppType::kCrostini:
       return apps::AppTypeName::kCrostini;
-    case apps::mojom::AppType::kChromeApp:
+    case AppType::kChromeApp:
       return IsBrowser(window) ? apps::AppTypeName::kChromeBrowser
                                : apps::AppTypeName::kChromeApp;
-    case apps::mojom::AppType::kWeb:
+    case AppType::kWeb:
       return GetAppTypeNameForWebAppWindow(profile, app_id, window);
-    case apps::mojom::AppType::kMacOs:
+    case AppType::kMacOs:
       return apps::AppTypeName::kMacOs;
-    case apps::mojom::AppType::kPluginVm:
+    case AppType::kPluginVm:
       return apps::AppTypeName::kPluginVm;
-    case apps::mojom::AppType::kStandaloneBrowser:
+    case AppType::kStandaloneBrowser:
       return apps::AppTypeName::kStandaloneBrowser;
-    case apps::mojom::AppType::kRemote:
+    case AppType::kRemote:
       return apps::AppTypeName::kRemote;
-    case apps::mojom::AppType::kBorealis:
+    case AppType::kBorealis:
       return apps::AppTypeName::kBorealis;
-    case apps::mojom::AppType::kSystemWeb:
+    case AppType::kSystemWeb:
       return apps::AppTypeName::kSystemWeb;
-    case apps::mojom::AppType::kStandaloneBrowserChromeApp:
+    case AppType::kStandaloneBrowserChromeApp:
       return apps::AppTypeName::kStandaloneBrowserChromeApp;
-    case apps::mojom::AppType::kExtension:
+    case AppType::kExtension:
       return apps::AppTypeName::kExtension;
   }
 }
@@ -275,53 +274,54 @@
 }
 
 AppTypeName GetAppTypeName(Profile* profile,
-                           apps::mojom::AppType app_type,
+                           AppType app_type,
                            const std::string& app_id,
                            apps::mojom::LaunchContainer container) {
   switch (app_type) {
-    case apps::mojom::AppType::kUnknown:
+    case AppType::kUnknown:
       return apps::AppTypeName::kUnknown;
-    case apps::mojom::AppType::kArc:
+    case AppType::kArc:
       return apps::AppTypeName::kArc;
-    case apps::mojom::AppType::kBuiltIn:
+    case AppType::kBuiltIn:
       return apps::AppTypeName::kBuiltIn;
-    case apps::mojom::AppType::kCrostini:
+    case AppType::kCrostini:
       return apps::AppTypeName::kCrostini;
-    case apps::mojom::AppType::kChromeApp:
+    case AppType::kChromeApp:
       return GetAppTypeNameForChromeApp(profile, app_id, container);
-    case apps::mojom::AppType::kWeb:
+    case AppType::kWeb:
       return GetAppTypeNameForWebApp(profile, app_id, container);
-    case apps::mojom::AppType::kMacOs:
+    case AppType::kMacOs:
       return apps::AppTypeName::kMacOs;
-    case apps::mojom::AppType::kPluginVm:
+    case AppType::kPluginVm:
       return apps::AppTypeName::kPluginVm;
-    case apps::mojom::AppType::kStandaloneBrowser:
+    case AppType::kStandaloneBrowser:
       return apps::AppTypeName::kStandaloneBrowser;
-    case apps::mojom::AppType::kRemote:
+    case AppType::kRemote:
       return apps::AppTypeName::kRemote;
-    case apps::mojom::AppType::kBorealis:
+    case AppType::kBorealis:
       return apps::AppTypeName::kBorealis;
-    case apps::mojom::AppType::kSystemWeb:
+    case AppType::kSystemWeb:
       return apps::AppTypeName::kSystemWeb;
-    case apps::mojom::AppType::kStandaloneBrowserChromeApp:
+    case AppType::kStandaloneBrowserChromeApp:
       return apps::AppTypeName::kStandaloneBrowserChromeApp;
-    case apps::mojom::AppType::kExtension:
+    case AppType::kExtension:
       return apps::AppTypeName::kExtension;
   }
 }
 
-mojom::AppType GetAppType(Profile* profile, const std::string& app_id) {
+AppType GetAppType(Profile* profile, const std::string& app_id) {
   DCHECK(AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile));
-  auto type = apps::AppServiceProxyFactory::GetForProfile(profile)
-                  ->AppRegistryCache()
-                  .GetAppType(app_id);
-  if (type != mojom::AppType::kUnknown) {
+  auto type = ConvertMojomAppTypToAppType(
+      apps::AppServiceProxyFactory::GetForProfile(profile)
+          ->AppRegistryCache()
+          .GetAppType(app_id));
+  if (type != AppType::kUnknown) {
     return type;
   }
   if (crostini::IsCrostiniShelfAppId(profile, app_id)) {
-    return mojom::AppType::kCrostini;
+    return AppType::kCrostini;
   }
-  return mojom::AppType::kUnknown;
+  return AppType::kUnknown;
 }
 
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h
index 9d6a771..ef48f7d 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h
@@ -95,7 +95,7 @@
 // Returns true if the app with |app_type| is opened with a browser window.
 // Otherwise, return false.
 bool IsAppOpenedWithBrowserWindow(Profile* profile,
-                                  apps::mojom::AppType app_type,
+                                  AppType app_type,
                                   const std::string& app_id);
 
 // Determines what app type a web app should be logged as based on |window|. In
@@ -106,7 +106,7 @@
 
 // Returns AppTypeName used for app running metrics.
 AppTypeName GetAppTypeNameForWindow(Profile* profile,
-                                    apps::mojom::AppType app_type,
+                                    AppType app_type,
                                     const std::string& app_id,
                                     aura::Window* window);
 
@@ -127,14 +127,14 @@
 
 // Returns AppTypeName used for app launch metrics.
 AppTypeName GetAppTypeName(Profile* profile,
-                           apps::mojom::AppType app_type,
+                           AppType app_type,
                            const std::string& app_id,
                            apps::mojom::LaunchContainer container);
 
 // Gets the app type of a given app_id. Checks multiple sources, not just the
 // app registry cache, so can identify apps which aren't registered with app
 // service.
-mojom::AppType GetAppType(Profile* profile, const std::string& app_id);
+AppType GetAppType(Profile* profile, const std::string& app_id);
 
 }  // namespace apps
 
diff --git a/chrome/browser/apps/app_service/notifications_browsertest.cc b/chrome/browser/apps/app_service/notifications_browsertest.cc
index 6d38e56..aaac6da 100644
--- a/chrome/browser/apps/app_service/notifications_browsertest.cc
+++ b/chrome/browser/apps/app_service/notifications_browsertest.cc
@@ -270,7 +270,7 @@
   }
 
   std::string CreateWebApp(const GURL& url, const GURL& scope) const {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->scope = scope;
     std::string app_id = web_app::test::InstallWebApp(browser()->profile(),
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.cc b/chrome/browser/apps/app_service/publishers/app_publisher.cc
index 554b828c..15fc6468 100644
--- a/chrome/browser/apps/app_service/publishers/app_publisher.cc
+++ b/chrome/browser/apps/app_service/publishers/app_publisher.cc
@@ -20,9 +20,6 @@
                                            Readiness readiness,
                                            const std::string& name) {
   std::unique_ptr<App> app = std::make_unique<App>(app_type, app_id);
-
-  app->app_type = app_type;
-  app->app_id = app_id;
   app->readiness = readiness;
   app->name = name;
   app->short_name = name;
diff --git a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
index ff58070..92ba7b08 100644
--- a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
+++ b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
@@ -119,7 +119,7 @@
   std::string CreateWebApp(const std::string& app_name) {
     const GURL kAppUrl("https://example.com/");
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->title = base::UTF8ToUTF16(app_name);
     web_app_info->start_url = kAppUrl;
     web_app_info->scope = kAppUrl;
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc b/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
index ec3c729..d4006b6 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task_unittest.cc
@@ -41,8 +41,8 @@
 constexpr char kTestShareTextParam[] = "share_text";
 const std::u16string kTestAppTitle = u"Test App";
 
-std::unique_ptr<WebApplicationInfo> BuildDefaultWebAppInfo() {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> BuildDefaultWebAppInfo() {
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->scope = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
@@ -265,7 +265,7 @@
 }
 
 TEST_F(WebApkInstallTaskTest, NoIconInManifest) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->scope = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
diff --git a/chrome/browser/apps/app_service/webapk/webapk_manager_unittest.cc b/chrome/browser/apps/app_service/webapk/webapk_manager_unittest.cc
index d4663ac..46556be3 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_manager_unittest.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_manager_unittest.cc
@@ -40,8 +40,8 @@
 constexpr char kTestWebApkPackageName[] = "org.chromium.webapk.some_package";
 const std::u16string kTestAppTitle = u"Test App";
 
-std::unique_ptr<WebApplicationInfo> BuildDefaultWebAppInfo() {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> BuildDefaultWebAppInfo() {
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->scope = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
@@ -153,7 +153,7 @@
 
 // Does not install web apps without a Share Target definition.
 TEST_F(WebApkManagerTest, NoShareTarget) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
   auto app_id = web_app::test::InstallWebApp(profile(), std::move(app_info));
@@ -188,7 +188,7 @@
 }
 
 TEST_F(WebApkManagerTest, RemovesIneligibleWebApkOnStartup) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
   auto app_id = web_app::test::InstallWebApp(profile(), std::move(app_info));
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
index 7a7f6266..fbad0863 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
@@ -410,7 +410,7 @@
         features::kDesktopPWAsAppIconShortcutsMenuUI);
 
     // Install a dummy app with shortcut menu items
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     WebAppShortcutsMenuItemInfo shortcut_info1;
     WebAppShortcutsMenuItemInfo shortcut_info2;
     WebAppShortcutsMenuItemInfo shortcut_info3;
diff --git a/chrome/browser/ash/android_sms/android_sms_app_setup_controller_impl_unittest.cc b/chrome/browser/ash/android_sms/android_sms_app_setup_controller_impl_unittest.cc
index 1825cc71..6448ad5 100644
--- a/chrome/browser/ash/android_sms/android_sms_app_setup_controller_impl_unittest.cc
+++ b/chrome/browser/ash/android_sms/android_sms_app_setup_controller_impl_unittest.cc
@@ -242,7 +242,7 @@
     base::HistogramTester histogram_tester;
 
     SetInstallResultCode(
-        web_app::InstallResultCode::kGetWebApplicationInfoFailed);
+        web_app::InstallResultCode::kGetWebAppInstallInfoFailed);
 
     setup_controller_->SetUpApp(
         app_url, install_url,
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
index 3646b81d..9e4aa50f 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.cc
@@ -214,7 +214,7 @@
 }
 
 void WebKioskAppData::UpdateFromWebAppInfo(
-    std::unique_ptr<WebApplicationInfo> app_info) {
+    std::unique_ptr<WebAppInstallInfo> app_info) {
   DCHECK(app_info);
   name_ = base::UTF16ToUTF8(app_info->title);
   base::FilePath cache_dir;
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
index a2d6174..01614e25 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data.h
@@ -13,7 +13,7 @@
 #include "ui/gfx/image/image_skia.h"
 #include "url/gurl.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace ash {
 
@@ -56,7 +56,7 @@
   // update.
   void SetStatus(Status status, bool notify = true);
 
-  void UpdateFromWebAppInfo(std::unique_ptr<WebApplicationInfo> app_info);
+  void UpdateFromWebAppInfo(std::unique_ptr<WebAppInstallInfo> app_info);
 
   void SetOnLoadedCallbackForTesting(base::OnceClosure callback);
 
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
index edb81d2..9c70b0c 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc
@@ -236,7 +236,7 @@
   EXPECT_EQ(app_data.GetLaunchableUrl(), GURL(kAppUrl));
 
   // `start_url` is treated as launchable URL if the app has been installed.
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kStartUrl);
   app_data.UpdateFromWebAppInfo(std::move(app_info));
   app_data.LoadFromCache();
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
index df795d77..27d4840 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.cc
@@ -64,7 +64,7 @@
       profile_, /*os_integration_manager=*/nullptr,
       /*install_finalizer=*/nullptr, data_retriever_factory_.Run(),
       /*registrar=*/nullptr);
-  install_task_->LoadAndRetrieveWebApplicationInfoWithIcons(
+  install_task_->LoadAndRetrieveWebAppInstallInfoWithIcons(
       WebKioskAppManager::Get()->GetAppByAccountId(account_id_)->install_url(),
       url_loader_.get(),
       base::BindOnce(&WebKioskAppLauncher::OnAppDataObtained,
@@ -79,7 +79,7 @@
 }
 
 void WebKioskAppLauncher::OnAppDataObtained(
-    std::unique_ptr<WebApplicationInfo> app_info) {
+    std::unique_ptr<WebAppInstallInfo> app_info) {
   if (!app_info) {
     // Notify about failed installation, let the controller decide what to do.
     delegate_->OnLaunchFailed(KioskAppLaunchError::Error::kUnableToInstall);
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
index ab35741..3f6b899 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher.h
@@ -75,7 +75,7 @@
 
   // Callback method triggered after web application and its icon are obtained
   // from `WebKioskAppManager`.
-  void OnAppDataObtained(std::unique_ptr<WebApplicationInfo> app_info);
+  void OnAppDataObtained(std::unique_ptr<WebAppInstallInfo> app_info);
 
   // Callback method triggered after the lacros-chrome window is created.
   void OnLacrosWindowCreated(crosapi::mojom::CreationResult result);
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
index 5c41e14..e26eb2ad 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc
@@ -62,10 +62,10 @@
 std::unique_ptr<web_app::WebAppDataRetriever> CreateDataRetrieverWithData(
     const GURL& url) {
   auto data_retriever = std::make_unique<web_app::FakeDataRetriever>();
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = url;
   info->title = kAppTitle;
-  data_retriever->SetRendererWebApplicationInfo(std::move(info));
+  data_retriever->SetRendererWebAppInstallInfo(std::move(info));
   return std::unique_ptr<web_app::WebAppDataRetriever>(
       std::move(data_retriever));
 }
@@ -130,7 +130,7 @@
     app_manager_->AddAppForTesting(account_id_, GURL(kAppInstallUrl));
 
     if (installed) {
-      auto info = std::make_unique<WebApplicationInfo>();
+      auto info = std::make_unique<WebAppInstallInfo>();
       info->start_url = GURL(kAppLaunchUrl);
       info->title = kAppTitle;
       app_manager_->UpdateAppByAccountId(account_id_, std::move(info));
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
index d46a54d..fa2e3f4 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.cc
@@ -93,7 +93,7 @@
 
 void WebKioskAppManager::UpdateAppByAccountId(
     const AccountId& account_id,
-    std::unique_ptr<WebApplicationInfo> app_info) {
+    std::unique_ptr<WebAppInstallInfo> app_info) {
   for (auto& web_app : apps_) {
     if (web_app->account_id() == account_id) {
       web_app->UpdateFromWebAppInfo(std::move(app_info));
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
index 0af8c00..20b83e4 100644
--- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
+++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h
@@ -15,7 +15,7 @@
 class Browser;
 class PrefRegistrySimple;
 class Profile;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace ash {
 
@@ -54,7 +54,7 @@
 
   // Updates app by the data obtained during installation.
   void UpdateAppByAccountId(const AccountId& account_id,
-                            std::unique_ptr<WebApplicationInfo> app_info);
+                            std::unique_ptr<WebAppInstallInfo> app_info);
 
   // Adds fake apps in tests.
   void AddAppForTesting(const AccountId& account_id, const GURL& install_url);
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
index 26304f6..bd5f9f5 100644
--- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -231,7 +231,7 @@
   }
 
   void CreateWebApp() {
-    auto web_application_info = std::make_unique<WebApplicationInfo>();
+    auto web_application_info = std::make_unique<WebAppInstallInfo>();
     web_application_info->start_url = GURL("https://example.org");
     web_app::AppId app_id = web_app::test::InstallWebApp(
         profile(), std::move(web_application_info));
diff --git a/chrome/browser/ash/apps/apk_web_app_installer.cc b/chrome/browser/ash/apps/apk_web_app_installer.cc
index 98fd749..e676f0f 100644
--- a/chrome/browser/ash/apps/apk_web_app_installer.cc
+++ b/chrome/browser/ash/apps/apk_web_app_installer.cc
@@ -78,7 +78,7 @@
   }
 
   DCHECK(!web_app_info_);
-  web_app_info_ = std::make_unique<WebApplicationInfo>();
+  web_app_info_ = std::make_unique<WebAppInstallInfo>();
 
   web_app_info_->title = base::UTF8ToUTF16(web_app_info->title);
 
diff --git a/chrome/browser/ash/apps/apk_web_app_installer.h b/chrome/browser/ash/apps/apk_web_app_installer.h
index 73293f10..1ac313643 100644
--- a/chrome/browser/ash/apps/apk_web_app_installer.h
+++ b/chrome/browser/ash/apps/apk_web_app_installer.h
@@ -79,7 +79,7 @@
   virtual void DoInstall();
 
   bool has_web_app_info() const { return web_app_info_ != nullptr; }
-  const WebApplicationInfo& web_app_info() const { return *web_app_info_; }
+  const WebAppInstallInfo& web_app_info() const { return *web_app_info_; }
 
  private:
   // If |weak_owner_| is ever invalidated while this class is working,
@@ -91,7 +91,7 @@
   InstallFinishCallback callback_;
   base::WeakPtr<Owner> weak_owner_;
 
-  std::unique_ptr<WebApplicationInfo> web_app_info_;
+  std::unique_ptr<WebAppInstallInfo> web_app_info_;
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
index b94be1e..3f49d5f4 100644
--- a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
+++ b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
@@ -62,8 +62,8 @@
   return fake_app_instance->GenerateIconResponse(128, /*app_icon=*/true);
 }
 
-std::unique_ptr<WebApplicationInfo> CreateWebApplicationInfo(const GURL& url) {
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInstallInfo(const GURL& url) {
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   web_application_info->start_url = url;
   web_application_info->title = u"App Title";
   web_application_info->theme_color = SK_ColorBLUE;
@@ -74,13 +74,13 @@
   const std::vector<SquareSizePx> sizes_px{web_app::icon_size::k256,
                                            web_app::icon_size::k512};
   const std::vector<SkColor> colors{SK_ColorRED, SK_ColorYELLOW};
-  web_app::AddIconsToWebApplicationInfo(web_application_info.get(), url,
-                                        {{IconPurpose::ANY, sizes_px, colors}});
+  web_app::AddIconsToWebAppInstallInfo(web_application_info.get(), url,
+                                       {{IconPurpose::ANY, sizes_px, colors}});
 
   return web_application_info;
 }
 
-void ExpectInitialIconInfosFromWebApplicationInfo(
+void ExpectInitialIconInfosFromWebAppInstallInfo(
     const std::vector<apps::IconInfo>& icon_infos,
     const GURL& url) {
   EXPECT_EQ(2u, icon_infos.size());
@@ -94,7 +94,7 @@
   EXPECT_EQ(apps::IconInfo::Purpose::kAny, icon_infos[1].purpose);
 }
 
-void ExpectInitialManifestFieldsFromWebApplicationInfo(
+void ExpectInitialManifestFieldsFromWebAppInstallInfo(
     const web_app::WebAppIconManager& icon_manager,
     const web_app::WebApp* web_app,
     const GURL& url) {
@@ -114,12 +114,11 @@
   EXPECT_EQ(url.Resolve("scope"), web_app->sync_fallback_data().scope);
   {
     SCOPED_TRACE("web_app->manifest_icons()");
-    ExpectInitialIconInfosFromWebApplicationInfo(web_app->manifest_icons(),
-                                                 url);
+    ExpectInitialIconInfosFromWebAppInstallInfo(web_app->manifest_icons(), url);
   }
   {
     SCOPED_TRACE("web_app->sync_fallback_data().icon_infos");
-    ExpectInitialIconInfosFromWebApplicationInfo(
+    ExpectInitialIconInfosFromWebAppInstallInfo(
         web_app->sync_fallback_data().icon_infos, url);
   }
 
@@ -670,8 +669,8 @@
   service->SetArcAppListPrefsForTesting(arc_app_list_prefs_);
 
   // Install the Web App as if the user installs it.
-  std::unique_ptr<WebApplicationInfo> web_application_info =
-      CreateWebApplicationInfo(GURL(kAppUrl));
+  std::unique_ptr<WebAppInstallInfo> web_application_info =
+      CreateWebAppInstallInfo(GURL(kAppUrl));
 
   web_app::AppId app_id = web_app::test::InstallWebApp(
       browser()->profile(), std::move(web_application_info),
@@ -688,8 +687,8 @@
 
   {
     SCOPED_TRACE("Expect initial manifest fields.");
-    ExpectInitialManifestFieldsFromWebApplicationInfo(icon_manager(), web_app,
-                                                      GURL(kAppUrl));
+    ExpectInitialManifestFieldsFromWebAppInstallInfo(icon_manager(), web_app,
+                                                     GURL(kAppUrl));
   }
 
   // Install the Web App from ARC.
@@ -715,8 +714,8 @@
 
   {
     SCOPED_TRACE("Expect same manifest fields, no overwrites.");
-    ExpectInitialManifestFieldsFromWebApplicationInfo(icon_manager(), web_app,
-                                                      GURL(kAppUrl));
+    ExpectInitialManifestFieldsFromWebAppInstallInfo(icon_manager(), web_app,
+                                                     GURL(kAppUrl));
   }
 }
 
@@ -752,8 +751,8 @@
   EXPECT_FALSE(web_app->IsSynced());
 
   // Install the Web App as if the user installs it.
-  std::unique_ptr<WebApplicationInfo> web_application_info =
-      CreateWebApplicationInfo(GURL(kAppUrl));
+  std::unique_ptr<WebAppInstallInfo> web_application_info =
+      CreateWebAppInstallInfo(GURL(kAppUrl));
 
   web_app::AppId web_app_id = web_app::test::InstallWebApp(
       browser()->profile(), std::move(web_application_info),
@@ -772,8 +771,8 @@
     SCOPED_TRACE(
         "Expect online manifest fields, the offline fields from ARC have been "
         "overwritten.");
-    ExpectInitialManifestFieldsFromWebApplicationInfo(icon_manager(), web_app,
-                                                      GURL(kAppUrl));
+    ExpectInitialManifestFieldsFromWebAppInstallInfo(icon_manager(), web_app,
+                                                     GURL(kAppUrl));
   }
 }
 
diff --git a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
index 624ac2ae..2efa5766 100644
--- a/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
+++ b/chrome/browser/ash/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
@@ -178,7 +178,7 @@
 content::WebContents* WebTimeLimitEnforcerThrottleTest::InstallAndLaunchWebApp(
     const GURL& url,
     bool allowlisted_app) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->title = base::UTF8ToUTF16(url.host());
   web_app_info->description = u"Web app";
   web_app_info->start_url = url;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 19bfc08..fd8b23f0 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -257,13 +257,14 @@
     FilesAppBrowserTest,
     ::testing::Values(
         TestCase("fileDisplayDownloads"),
-        TestCase("fileDisplayDownloads").InGuestMode(),
-        TestCase("fileDisplayDownloads").TabletMode(),
         TestCase("fileDisplayDownloads").FilesSwa(),
-        TestCase("fileDisplayDownloads").FilesSwa().InGuestMode(),
-        TestCase("fileDisplayDownloads").FilesSwa().TabletMode(),
-        TestCase("fileDisplayLaunchOnLocalFolder").DontObserveFileTasks(),
+        TestCase("fileDisplayDownloads").InGuestMode(),
+        TestCase("fileDisplayDownloads").InGuestMode().FilesSwa(),
+        TestCase("fileDisplayDownloads").TabletMode(),
+        TestCase("fileDisplayDownloads").TabletMode().FilesSwa(),
         TestCase("fileDisplayLaunchOnDrive").DontObserveFileTasks(),
+        TestCase("fileDisplayLaunchOnDrive").DontObserveFileTasks().FilesSwa(),
+        TestCase("fileDisplayLaunchOnLocalFolder").DontObserveFileTasks(),
         TestCase("fileDisplayLaunchOnLocalFolder")
             .DontObserveFileTasks()
             .FilesSwa(),
@@ -272,7 +273,9 @@
             .DontObserveFileTasks()
             .FilesSwa(),
         TestCase("fileDisplayDrive").TabletMode(),
+        TestCase("fileDisplayDrive").TabletMode().FilesSwa(),
         TestCase("fileDisplayDrive"),
+        TestCase("fileDisplayDrive").FilesSwa(),
         TestCase("fileDisplayDriveOffline").Offline(),
         TestCase("fileDisplayDriveOffline").Offline().FilesSwa(),
         TestCase("fileDisplayDriveOnline"),
@@ -282,13 +285,23 @@
             .DontObserveFileTasks()
             .FilesSwa(),
         TestCase("fileDisplayComputers"),
+        TestCase("fileDisplayComputers").FilesSwa(),
         TestCase("fileDisplayMtp"),
+        TestCase("fileDisplayMtp").FilesSwa(),
         TestCase("fileDisplayUsb"),
+        TestCase("fileDisplayUsb").FilesSwa(),
         TestCase("fileDisplayUsbPartition"),
+        TestCase("fileDisplayUsbPartition").FilesSwa(),
         TestCase("fileDisplayUsbPartition").EnableSinglePartitionFormat(),
+        TestCase("fileDisplayUsbPartition")
+            .EnableSinglePartitionFormat()
+            .FilesSwa(),
         TestCase("fileDisplayUsbPartitionSort"),
+        TestCase("fileDisplayUsbPartitionSort").FilesSwa(),
         TestCase("fileDisplayPartitionFileTable"),
+        TestCase("fileDisplayPartitionFileTable").FilesSwa(),
         TestCase("fileSearch"),
+        TestCase("fileSearch").FilesSwa(),
         TestCase("fileDisplayWithoutDownloadsVolume").DontMountVolumes(),
         TestCase("fileDisplayWithoutDownloadsVolume")
             .DontMountVolumes()
@@ -314,17 +327,29 @@
         TestCase("fileDisplayWithHiddenVolume"),
         TestCase("fileDisplayWithHiddenVolume").FilesSwa(),
         TestCase("fileDisplayMountWithFakeItemSelected"),
+        TestCase("fileDisplayMountWithFakeItemSelected").FilesSwa(),
         TestCase("fileDisplayUnmountDriveWithSharedWithMeSelected"),
+        TestCase("fileDisplayUnmountDriveWithSharedWithMeSelected").FilesSwa(),
         TestCase("fileDisplayUnmountRemovableRoot"),
+        TestCase("fileDisplayUnmountRemovableRoot").FilesSwa(),
         TestCase("fileDisplayUnmountFirstPartition"),
+        TestCase("fileDisplayUnmountFirstPartition").FilesSwa(),
         TestCase("fileDisplayUnmountLastPartition"),
+        TestCase("fileDisplayUnmountLastPartition").FilesSwa(),
         TestCase("fileSearchCaseInsensitive"),
+        TestCase("fileSearchCaseInsensitive").FilesSwa(),
         TestCase("fileSearchNotFound"),
+        TestCase("fileSearchNotFound").FilesSwa(),
         TestCase("fileDisplayDownloadsWithBlockedFileTaskRunner"),
+        TestCase("fileDisplayDownloadsWithBlockedFileTaskRunner").FilesSwa(),
         TestCase("fileDisplayCheckSelectWithFakeItemSelected"),
+        TestCase("fileDisplayCheckSelectWithFakeItemSelected").FilesSwa(),
         TestCase("fileDisplayCheckReadOnlyIconOnFakeDirectory"),
+        TestCase("fileDisplayCheckReadOnlyIconOnFakeDirectory").FilesSwa(),
         TestCase("fileDisplayCheckNoReadOnlyIconOnDownloads"),
+        TestCase("fileDisplayCheckNoReadOnlyIconOnDownloads").FilesSwa(),
         TestCase("fileDisplayCheckNoReadOnlyIconOnLinuxFiles"),
+        TestCase("fileDisplayCheckNoReadOnlyIconOnLinuxFiles").FilesSwa(),
         TestCase("fileDisplayStartupError")));
 
 WRAPPED_INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index 0d2619b..c8641af 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -273,7 +273,7 @@
 
   DCHECK_EQ(task.task_type, TASK_TYPE_ARC_APP);
   apps::RecordAppLaunchMetrics(
-      profile, apps::mojom::AppType::kArc, task.app_id,
+      profile, apps::AppType::kArc, task.app_id,
       apps::mojom::LaunchSource::kFromFileManager,
       apps::mojom::LaunchContainer::kLaunchContainerWindow);
   ExecuteArcTask(profile, task, file_urls, *mime_types, std::move(done));
diff --git a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
index 78bfb87..e451b0f 100644
--- a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
@@ -490,7 +490,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(FileTasksBrowserTest, ExecuteWebApp) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GURL("https://www.example.com/");
   web_app_info->scope = GURL("https://www.example.com/");
   apps::FileHandler handler;
diff --git a/chrome/browser/ash/file_manager/guest_os_file_tasks.cc b/chrome/browser/ash/file_manager/guest_os_file_tasks.cc
index 9cce1df..e27d0ce 100644
--- a/chrome/browser/ash/file_manager/guest_os_file_tasks.cc
+++ b/chrome/browser/ash/file_manager/guest_os_file_tasks.cc
@@ -287,7 +287,7 @@
     case guest_os::GuestOsRegistryService::VmType::
         ApplicationList_VmType_TERMINA:
       apps::RecordAppLaunchMetrics(
-          profile, apps::mojom::AppType::kCrostini, task.app_id,
+          profile, apps::AppType::kCrostini, task.app_id,
           apps::mojom::LaunchSource::kFromFileManager,
           apps::mojom::LaunchContainer::kLaunchContainerWindow);
       crostini::LaunchCrostiniApp(
@@ -312,7 +312,7 @@
     case guest_os::GuestOsRegistryService::VmType::
         ApplicationList_VmType_PLUGIN_VM:
       apps::RecordAppLaunchMetrics(
-          profile, apps::mojom::AppType::kPluginVm, task.app_id,
+          profile, apps::AppType::kPluginVm, task.app_id,
           apps::mojom::LaunchSource::kFromFileManager,
           apps::mojom::LaunchContainer::kLaunchContainerWindow);
       DCHECK(plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile));
diff --git a/chrome/browser/ash/input_method/native_input_method_engine.cc b/chrome/browser/ash/input_method/native_input_method_engine.cc
index 0a19d9f..065cbbf 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine.cc
@@ -1092,7 +1092,9 @@
   }
 
   ui::CandidateWindow::CandidateWindowProperty property;
-  property.cursor_position = window->highlighted_candidate;
+  property.cursor_position = window->highlighted_candidate
+                                 ? window->highlighted_candidate->index
+                                 : window->DEPRECATED_highlighted_candidate;
   property.page_size = window->candidates.size();
   property.is_vertical = true;
   property.is_auxiliary_text_visible =
diff --git a/chrome/browser/ash/login/app_mode/web_kiosk_browsertest.cc b/chrome/browser/ash/login/app_mode/web_kiosk_browsertest.cc
index ac386513..b5c4c09 100644
--- a/chrome/browser/ash/login/app_mode/web_kiosk_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/web_kiosk_browsertest.cc
@@ -88,7 +88,7 @@
   }
 
   void MakeAppAlreadyInstalled() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = GURL(kAppLaunchUrl);
     info->title = kAppTitle;
     WebKioskAppManager::Get()->UpdateAppByAccountId(account_id(),
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc
index 155e11ae..a95d69e 100644
--- a/chrome/browser/ash/note_taking_helper_unittest.cc
+++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -748,7 +748,7 @@
   Init(ENABLE_PALETTE);
 
   {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->start_url = GURL("http://some1.url");
     app_info->scope = GURL("http://some1.url");
     app_info->title = u"Web App 1";
@@ -756,7 +756,7 @@
   }
   std::string app2_id;
   {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->start_url = GURL("http://some2.url");
     app_info->scope = GURL("http://some2.url");
     app_info->title = u"Web App 2";
@@ -833,7 +833,7 @@
   GURL app_url("https://yielding-large-chef.glitch.me/");
   // Install a default-allowed web app corresponding to ID of
   // |NoteTakingHelper::kNoteTakingWebAppIdTest|.
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = app_url;
   app_info->title = u"Default Allowed Web App";
   std::string app_id =
@@ -866,7 +866,7 @@
 
   // Install a web app with a note_taking_new_note_url.
   GURL new_note_url("http://some.url/new-note");
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL("http://some.url");
   app_info->scope = GURL("http://some.url");
   app_info->title = u"Web App 2";
@@ -903,7 +903,7 @@
   {
     // Install a default-allowed web app corresponding to ID of
     // |NoteTakingHelper::kNoteTakingWebAppIdTest|.
-    auto app_info = std::make_unique<WebApplicationInfo>();
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->start_url = GURL("https://yielding-large-chef.glitch.me/");
     app_info->title = u"Default Allowed Web App";
     std::string app_id =
diff --git a/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.cc b/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.cc
index efe58a1..4f109b2 100644
--- a/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.cc
@@ -25,8 +25,8 @@
                                                    32);
 }
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForCameraSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForCameraSystemWebApp() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUICameraAppMainURL);
   info->scope = GURL(ash::kChromeUICameraAppScopeURL);
 
@@ -68,7 +68,7 @@
                {web_app::GetOrigin("chrome-untrusted://camera-app"),
                 {"WebAssemblyDynamicTiering"}}})) {}
 
-std::unique_ptr<WebApplicationInfo> CameraSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> CameraSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForCameraSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.h b/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.h
index 249f178..8d3fcac 100644
--- a/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/camera_app/camera_system_web_app_info.h
@@ -12,21 +12,21 @@
 #include "ui/gfx/geometry/rect.h"
 
 class Browser;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class CameraSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit CameraSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   gfx::Size GetMinimumWindowSize() const override;
   gfx::Rect GetDefaultBounds(Browser* browser) const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForCameraSystemWebApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForCameraSystemWebApp();
 
 // Returns the default bounds.
 gfx::Rect GetDefaultBoundsForCameraApp(Browser*);
diff --git a/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.cc b/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.cc
index 0966382..24b3036 100644
--- a/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.cc
@@ -15,10 +15,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForConnectivityDiagnosticsSystemWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIConnectivityDiagnosticsUrl);
   info->scope = GURL(ash::kChromeUIConnectivityDiagnosticsUrl);
   info->title = l10n_util::GetStringUTF16(IDS_CONNECTIVITY_DIAGNOSTICS_TITLE);
@@ -44,7 +44,7 @@
           GURL(ash::kChromeUIConnectivityDiagnosticsUrl),
           profile) {}
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 ConnectivityDiagnosticsSystemAppDelegate::GetWebAppInfo() const {
   return CreateWebAppInfoForConnectivityDiagnosticsSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.h b/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.h
index 8475677..d44575d 100644
--- a/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/connectivity_diagnostics_system_web_app_info.h
@@ -9,7 +9,7 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class ConnectivityDiagnosticsSystemAppDelegate
     : public web_app::SystemWebAppDelegate {
@@ -17,13 +17,13 @@
   explicit ConnectivityDiagnosticsSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldShowInSearch() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo>
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForConnectivityDiagnosticsSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_CONNECTIVITY_DIAGNOSTICS_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/crosh_system_web_app_info.cc b/chrome/browser/ash/web_applications/crosh_system_web_app_info.cc
index a6908ba..5a49ccd 100644
--- a/chrome/browser/ash/web_applications/crosh_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/crosh_system_web_app_info.cc
@@ -16,8 +16,8 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "url/gurl.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForCroshSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForCroshSystemWebApp() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(chrome::kChromeUIUntrustedCroshURL);
   info->scope = GURL(chrome::kChromeUIUntrustedCroshURL);
   info->title = std::u16string(u"crosh");
@@ -34,7 +34,7 @@
                                     GURL(chrome::kChromeUIUntrustedCroshURL),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> CroshSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> CroshSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForCroshSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/crosh_system_web_app_info.h b/chrome/browser/ash/web_applications/crosh_system_web_app_info.h
index 5d64ed4..8754313 100644
--- a/chrome/browser/ash/web_applications/crosh_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/crosh_system_web_app_info.h
@@ -12,21 +12,21 @@
 #include "chrome/common/webui_url_constants.h"
 #include "ui/gfx/geometry/rect.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class CroshSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit CroshSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldReuseExistingWindow() const override;
   bool ShouldShowInSearch() const override;
   bool ShouldHaveTabStrip() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForCroshSystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForCroshSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_CROSH_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/demo_mode_web_app_info.cc b/chrome/browser/ash/web_applications/demo_mode_web_app_info.cc
index 3e69ae8..e5f6a5b 100644
--- a/chrome/browser/ash/web_applications/demo_mode_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/demo_mode_web_app_info.cc
@@ -11,9 +11,9 @@
 #include "chrome/browser/ash/web_applications/system_web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_application_info.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForDemoModeApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForDemoModeApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIDemoModeAppURL);
   info->scope = GURL(ash::kChromeUIDemoModeAppURL);
   // TODO(b/185608502): Convert the title to a localized string
@@ -36,7 +36,7 @@
                                     GURL("chrome://demo-mode-app"),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> DemoModeSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> DemoModeSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForDemoModeApp();
 }
diff --git a/chrome/browser/ash/web_applications/demo_mode_web_app_info.h b/chrome/browser/ash/web_applications/demo_mode_web_app_info.h
index 480f5dd..7eaff8c 100644
--- a/chrome/browser/ash/web_applications/demo_mode_web_app_info.h
+++ b/chrome/browser/ash/web_applications/demo_mode_web_app_info.h
@@ -8,7 +8,7 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 #if defined(OFFICIAL_BUILD)
 #error Demo Mode should only be included in unofficial builds.
@@ -19,11 +19,11 @@
   explicit DemoModeSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool IsAppEnabled() const override;
 };
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForDemoModeApp();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForDemoModeApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_DEMO_MODE_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.cc b/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.cc
index bbc7ccd..069511d 100644
--- a/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.cc
@@ -15,10 +15,10 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "url/gurl.h"
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForDiagnosticsSystemWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIDiagnosticsAppUrl);
   info->scope = GURL(ash::kChromeUIDiagnosticsAppUrl);
 
@@ -45,8 +45,8 @@
                                     GURL("chrome://diagnostics"),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo>
-DiagnosticsSystemAppDelegate::GetWebAppInfo() const {
+std::unique_ptr<WebAppInstallInfo> DiagnosticsSystemAppDelegate::GetWebAppInfo()
+    const {
   return CreateWebAppInfoForDiagnosticsSystemWebApp();
 }
 
diff --git a/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h b/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h
index 23ceddd..fd47d498 100644
--- a/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/diagnostics_system_web_app_info.h
@@ -11,21 +11,20 @@
 
 #include "ui/gfx/geometry/rect.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class DiagnosticsSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit DiagnosticsSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   gfx::Size GetMinimumWindowSize() const override;
   bool IsAppEnabled() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo>
-CreateWebAppInfoForDiagnosticsSystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForDiagnosticsSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_DIAGNOSTICS_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/eche_app_info.cc b/chrome/browser/ash/web_applications/eche_app_info.cc
index ad325f5b..fd5081c7 100644
--- a/chrome/browser/ash/web_applications/eche_app_info.cc
+++ b/chrome/browser/ash/web_applications/eche_app_info.cc
@@ -16,9 +16,9 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "ui/display/screen.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForEcheApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForEcheApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::eche_app::kChromeUIEcheAppURL);
   info->scope = GURL(ash::eche_app::kChromeUIEcheAppURL);
   // |title| should come from a resource string, but this is the Eche app, and
@@ -59,7 +59,7 @@
                                     GURL("chrome://eche-app"),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> EcheSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> EcheSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForEcheApp();
 }
diff --git a/chrome/browser/ash/web_applications/eche_app_info.h b/chrome/browser/ash/web_applications/eche_app_info.h
index 0f8b5145..949bb616 100644
--- a/chrome/browser/ash/web_applications/eche_app_info.h
+++ b/chrome/browser/ash/web_applications/eche_app_info.h
@@ -10,14 +10,14 @@
 #include "ui/gfx/geometry/rect.h"
 
 class Browser;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class EcheSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit EcheSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldShowInSearch() const override;
@@ -29,8 +29,8 @@
   bool IsAppEnabled() const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForEcheApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForEcheApp();
 
 // Returns the default bounds.
 gfx::Rect GetDefaultBoundsForEche(Browser*);
diff --git a/chrome/browser/ash/web_applications/file_manager_web_app_info.cc b/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
index 4000282..62a7882 100644
--- a/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/file_manager_web_app_info.cc
@@ -29,7 +29,7 @@
 // The handler action has the format: chrome://file-manager/?${ACTION_NAME}
 // This means: For files with the given `file_extensions` or `mime_type` the
 // Files SWA is a candidate app to open/handle such files.
-void AppendFileHandler(WebApplicationInfo& info,
+void AppendFileHandler(WebAppInstallInfo& info,
                        const std::string& action_name,
                        const base::flat_set<std::string>& file_extensions,
                        const std::string& mime_type = "") {
@@ -50,8 +50,8 @@
 
 }  // namespace
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForFileManager() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFileManager() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(kChromeUIFileManagerURL);
   info->scope = GURL(kChromeUIFileManagerURL);
   info->title = l10n_util::GetStringUTF16(IDS_FILEMANAGER_APP_NAME);
@@ -118,8 +118,8 @@
               {{web_app::GetOrigin(kChromeUIFileManagerURL),
                 {"FileHandling"}}})) {}
 
-std::unique_ptr<WebApplicationInfo>
-FileManagerSystemAppDelegate::GetWebAppInfo() const {
+std::unique_ptr<WebAppInstallInfo> FileManagerSystemAppDelegate::GetWebAppInfo()
+    const {
   return CreateWebAppInfoForFileManager();
 }
 
diff --git a/chrome/browser/ash/web_applications/file_manager_web_app_info.h b/chrome/browser/ash/web_applications/file_manager_web_app_info.h
index 0d21e6c..beae4b7b 100644
--- a/chrome/browser/ash/web_applications/file_manager_web_app_info.h
+++ b/chrome/browser/ash/web_applications/file_manager_web_app_info.h
@@ -12,14 +12,14 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 #include "chrome/browser/web_applications/web_app_id.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class FileManagerSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit FileManagerSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldReuseExistingWindow() const override;
   bool ShouldShowNewWindowMenuOption() const override;
@@ -27,7 +27,7 @@
   std::vector<web_app::AppId> GetAppIdsToUninstallAndReplace() const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForFileManager();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForFileManager();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_FILE_MANAGER_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc
index 5fa8a989..31d708c8 100644
--- a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.cc
@@ -18,9 +18,9 @@
 #include "ui/base/ui_base_features.h"
 
 // TODO(michaelcheco): Update to correct icon.
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForFirmwareUpdateSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIFirmwareUpdateAppURL);
   info->scope = GURL(ash::kChromeUIFirmwareUpdateAppURL);
   info->title = l10n_util::GetStringUTF16(IDS_ASH_FIRMWARE_UPDATE_APP_TITLE);
@@ -41,7 +41,7 @@
                                     GURL(ash::kChromeUIFirmwareUpdateAppURL),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 FirmwareUpdateSystemAppDelegate::GetWebAppInfo() const {
   return CreateWebAppInfoForFirmwareUpdateSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.h b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.h
index e80a7fe..be2274b 100644
--- a/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/firmware_update_system_web_app_info.h
@@ -8,19 +8,19 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class FirmwareUpdateSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit FirmwareUpdateSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   gfx::Size GetMinimumWindowSize() const override;
   bool IsAppEnabled() const override;
 };
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo>
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForFirmwareUpdateSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_FIRMWARE_UPDATE_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.cc b/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.cc
index 7e553d3..0c766185 100644
--- a/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.cc
@@ -23,9 +23,9 @@
 constexpr gfx::Size HELP_DEFAULT_SIZE(960, 600);
 }  // namespace
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForHelpWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForHelpWebApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(kChromeUIHelpAppURL);
   info->scope = GURL(kChromeUIHelpAppURL);
 
@@ -86,7 +86,7 @@
   }
 }
 
-std::unique_ptr<WebApplicationInfo> HelpAppSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> HelpAppSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForHelpWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h b/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h
index 385bd2b..a3afa87 100644
--- a/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h
+++ b/chrome/browser/ash/web_applications/help_app/help_app_web_app_info.h
@@ -15,7 +15,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 class Browser;
 
 namespace ash {
@@ -25,7 +25,7 @@
   explicit HelpAppSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   gfx::Rect GetDefaultBounds(Browser*) const override;
   gfx::Size GetMinimumWindowSize() const override;
   std::vector<int> GetAdditionalSearchTerms() const override;
@@ -34,8 +34,8 @@
   bool ShouldCaptureNavigations() const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForHelpWebApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForHelpWebApp();
 
 // Returns the default bounds.
 gfx::Rect GetDefaultBoundsForHelpApp(Browser*);
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
index 1d65ebc5..3ad0f65 100644
--- a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
@@ -86,7 +86,7 @@
 };
 
 // Converts a FileHandlerConfig constexpr into the type needed to populate the
-// WebApplicationInfo's `accept` property.
+// WebAppInstallInfo's `accept` property.
 std::vector<apps::FileHandler::AcceptEntry> MakeFileHandlerAccept(
     base::span<const FileHandlerConfig> config) {
   std::vector<apps::FileHandler::AcceptEntry> result;
@@ -116,9 +116,9 @@
               {{web_app::GetOrigin("chrome://media-app"), {"FileHandling"}}})) {
 }
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForMediaWebApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIMediaAppURL);
   info->scope = GURL(ash::kChromeUIMediaAppURL);
 
@@ -157,7 +157,7 @@
   return info;
 }
 
-std::unique_ptr<WebApplicationInfo> MediaSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> MediaSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForMediaWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.h b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
index 72615c0b..81707e7 100644
--- a/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
+++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.h
@@ -8,14 +8,14 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class MediaSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit MediaSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldShowInSearch() const override;
@@ -26,7 +26,7 @@
       const apps::AppLaunchParams& params) const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForMediaWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_MEDIA_APP_MEDIA_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
index f7d486f..b94a0fd 100644
--- a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
@@ -23,9 +23,8 @@
 constexpr int kFeedbackAppDefaultHeight = 640;
 }  // namespace
 
-std::unique_ptr<WebApplicationInfo>
-CreateWebAppInfoForOSFeedbackSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForOSFeedbackSystemWebApp() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIOSFeedbackUrl);
   info->scope = GURL(ash::kChromeUIOSFeedbackUrl);
   info->title = l10n_util::GetStringUTF16(IDS_FEEDBACK_REPORT_APP_TITLE);
@@ -56,7 +55,7 @@
                                     GURL(ash::kChromeUIOSFeedbackUrl),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> OSFeedbackAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> OSFeedbackAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForOSFeedbackSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.h b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.h
index df2aa0aa..18cde2561 100644
--- a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.h
@@ -13,14 +13,14 @@
 #include "ui/gfx/geometry/rect.h"
 
 class Browser;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class OSFeedbackAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit OSFeedbackAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool IsAppEnabled() const override;
   bool ShouldAllowScriptsToCloseWindows() const override;
   bool ShouldCaptureNavigations() const override;
@@ -29,8 +29,8 @@
   gfx::Rect GetDefaultBounds(Browser*) const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForOSFeedbackSystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForOSFeedbackSystemWebApp();
 
 // Returns the default bounds.
 gfx::Rect GetDefaultBoundsForOSFeedbackApp(Browser*);
diff --git a/chrome/browser/ash/web_applications/os_flags_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_flags_system_web_app_info.cc
index 15f3a2f..3d5f4ef 100644
--- a/chrome/browser/ash/web_applications/os_flags_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_flags_system_web_app_info.cc
@@ -33,9 +33,9 @@
 
 OsFlagsSystemWebAppDelegate::~OsFlagsSystemWebAppDelegate() = default;
 
-std::unique_ptr<WebApplicationInfo> OsFlagsSystemWebAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> OsFlagsSystemWebAppDelegate::GetWebAppInfo()
     const {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(chrome::kChromeUIFlagsURL);
   info->scope = GURL(chrome::kChromeUIFlagsURL);
 
diff --git a/chrome/browser/ash/web_applications/os_flags_system_web_app_info.h b/chrome/browser/ash/web_applications/os_flags_system_web_app_info.h
index 5363453e..40d80752 100644
--- a/chrome/browser/ash/web_applications/os_flags_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/os_flags_system_web_app_info.h
@@ -22,7 +22,7 @@
   ~OsFlagsSystemWebAppDelegate() override;
 
   // web_app::SystemWebAppDelegate:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
 
   // TODO(crbug/1260386) - Add override for GetAdditionalSearchTerms() to allow
   // capturing the os:// search tearms to be used.
diff --git a/chrome/browser/ash/web_applications/os_settings_web_app_info.cc b/chrome/browser/ash/web_applications/os_settings_web_app_info.cc
index 90a8c16..a4373bf 100644
--- a/chrome/browser/ash/web_applications/os_settings_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_settings_web_app_info.cc
@@ -30,10 +30,9 @@
 
 }  // namespace
 
-std::unique_ptr<WebApplicationInfo>
-CreateWebAppInfoForOSSettingsSystemWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForOSSettingsSystemWebApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(chrome::kChromeUIOSSettingsURL);
   info->scope = GURL(chrome::kChromeUIOSSettingsURL);
   info->title = l10n_util::GetStringUTF16(IDS_SETTINGS_SETTINGS);
@@ -59,7 +58,7 @@
                                     GURL(chrome::kChromeUISettingsURL),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> OSSettingsSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> OSSettingsSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForOSSettingsSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/os_settings_web_app_info.h b/chrome/browser/ash/web_applications/os_settings_web_app_info.h
index 890fc44..7d18bd9 100644
--- a/chrome/browser/ash/web_applications/os_settings_web_app_info.h
+++ b/chrome/browser/ash/web_applications/os_settings_web_app_info.h
@@ -13,20 +13,20 @@
 #include "chrome/common/webui_url_constants.h"
 #include "ui/gfx/geometry/rect.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class OSSettingsSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit OSSettingsSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   gfx::Size GetMinimumWindowSize() const override;
   std::vector<web_app::AppId> GetAppIdsToUninstallAndReplace() const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForOSSettingsSystemWebApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForOSSettingsSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_OS_SETTINGS_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
index 54ef592..13a6941 100644
--- a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.cc
@@ -40,9 +40,9 @@
 
 OsUrlHandlerSystemWebAppDelegate::~OsUrlHandlerSystemWebAppDelegate() = default;
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 OsUrlHandlerSystemWebAppDelegate::GetWebAppInfo() const {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(chrome::kChromeUIOsUrlAppURL);
   info->scope = GURL(chrome::kChromeUIOsUrlAppURL);
   info->title = l10n_util::GetStringUTF16(IDS_OS_URL_HANDLER_APP_NAME);
diff --git a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h
index a313bbc0..bc3394c 100644
--- a/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/os_url_handler_system_web_app_info.h
@@ -23,7 +23,7 @@
   ~OsUrlHandlerSystemWebAppDelegate() override;
 
   // web_app::SystemWebAppDelegate:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
 
   // TODO(crbug/1260386) - Add override for GetAdditionalSearchTerms() to allow
   // capturing the os:// search tearms to be used.
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.cc
index bbdaa89..018e0d4 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.cc
@@ -15,9 +15,9 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForPersonalizationApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForPersonalizationApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIPersonalizationAppURL);
   info->scope = GURL(ash::kChromeUIPersonalizationAppURL);
   info->title = l10n_util::GetStringUTF16(IDS_PERSONALIZATION_APP_TITLE);
@@ -38,7 +38,7 @@
                                     GURL(ash::kChromeUIPersonalizationAppURL),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 PersonalizationSystemAppDelegate::GetWebAppInfo() const {
   return CreateWebAppInfoForPersonalizationApp();
 }
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.h
index 98ac704..63a377cad 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.h
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_info.h
@@ -8,20 +8,20 @@
 #include "ash/webui/personalization_app/personalization_app_url_constants.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class PersonalizationSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit PersonalizationSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool IsAppEnabled() const override;
   bool ShouldShowInLauncher() const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForPersonalizationApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForPersonalizationApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_PERSONALIZATION_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/print_management_web_app_info.cc b/chrome/browser/ash/web_applications/print_management_web_app_info.cc
index 13c987b..5658574 100644
--- a/chrome/browser/ash/web_applications/print_management_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/print_management_web_app_info.cc
@@ -14,9 +14,9 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForPrintManagementApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForPrintManagementApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIPrintManagementAppUrl);
   info->scope = GURL(ash::kChromeUIPrintManagementAppUrl);
   info->title = l10n_util::GetStringUTF16(IDS_PRINT_MANAGEMENT_TITLE);
@@ -43,7 +43,7 @@
                                     GURL("chrome://print-management/pwa.html"),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 PrintManagementSystemAppDelegate::GetWebAppInfo() const {
   return CreateWebAppInfoForPrintManagementApp();
 }
diff --git a/chrome/browser/ash/web_applications/print_management_web_app_info.h b/chrome/browser/ash/web_applications/print_management_web_app_info.h
index f42bb2c..3f08e75 100644
--- a/chrome/browser/ash/web_applications/print_management_web_app_info.h
+++ b/chrome/browser/ash/web_applications/print_management_web_app_info.h
@@ -9,19 +9,19 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class PrintManagementSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit PrintManagementSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   gfx::Size GetMinimumWindowSize() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForPrintManagementApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForPrintManagementApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_PRINT_MANAGEMENT_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/projector_system_web_app_info.cc b/chrome/browser/ash/web_applications/projector_system_web_app_info.cc
index 5286135..2016676b 100644
--- a/chrome/browser/ash/web_applications/projector_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/projector_system_web_app_info.cc
@@ -35,9 +35,9 @@
 
 ProjectorSystemWebAppDelegate::~ProjectorSystemWebAppDelegate() = default;
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 ProjectorSystemWebAppDelegate::GetWebAppInfo() const {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUITrustedProjectorAppUrl);
   info->scope = GURL(ash::kChromeUITrustedProjectorAppUrl);
 
diff --git a/chrome/browser/ash/web_applications/projector_system_web_app_info.h b/chrome/browser/ash/web_applications/projector_system_web_app_info.h
index 02f5c902..7b3dff7 100644
--- a/chrome/browser/ash/web_applications/projector_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/projector_system_web_app_info.h
@@ -18,7 +18,7 @@
   ~ProjectorSystemWebAppDelegate() override;
 
   // web_app::SystemWebAppDelegate:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool IsAppEnabled() const override;
 };
diff --git a/chrome/browser/ash/web_applications/sample_system_web_app_info.cc b/chrome/browser/ash/web_applications/sample_system_web_app_info.cc
index 1834314..7f24995 100644
--- a/chrome/browser/ash/web_applications/sample_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/sample_system_web_app_info.cc
@@ -14,9 +14,9 @@
 #include "chrome/browser/web_applications/web_application_info.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForSampleSystemWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForSampleSystemWebApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUISampleSystemWebAppURL);
   info->scope = GURL(ash::kChromeUISampleSystemWebAppURL);
   // |title| should come from a resource string, but this is the sample app, and
@@ -68,7 +68,7 @@
                {web_app::GetOrigin("chrome-untrusted://sample-system-web-app"),
                 {"Frobulate"}}})) {}
 
-std::unique_ptr<WebApplicationInfo> SampleSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> SampleSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForSampleSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/sample_system_web_app_info.h b/chrome/browser/ash/web_applications/sample_system_web_app_info.h
index 482d8148..cda31c0 100644
--- a/chrome/browser/ash/web_applications/sample_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/sample_system_web_app_info.h
@@ -9,7 +9,7 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 #if defined(OFFICIAL_BUILD)
 #error Demo Mode should only be included in unofficial builds.
@@ -20,7 +20,7 @@
   explicit SampleSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldReuseExistingWindow() const override;
   bool ShouldShowNewWindowMenuOption() const override;
@@ -28,7 +28,7 @@
       const override;
 };
 
-// Return a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForSampleSystemWebApp();
+// Return a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForSampleSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_SAMPLE_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/scanning_system_web_app_info.cc b/chrome/browser/ash/web_applications/scanning_system_web_app_info.cc
index d98ad7dd..1486068 100644
--- a/chrome/browser/ash/web_applications/scanning_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/scanning_system_web_app_info.cc
@@ -15,9 +15,9 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForScanningSystemWebApp() {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForScanningSystemWebApp() {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIScanningAppUrl);
   info->scope = GURL(ash::kChromeUIScanningAppUrl);
   info->title = l10n_util::GetStringUTF16(IDS_SCANNING_APP_TITLE);
@@ -51,7 +51,7 @@
                                     GURL("chrome://scanning"),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> ScanningSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> ScanningSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForScanningSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/scanning_system_web_app_info.h b/chrome/browser/ash/web_applications/scanning_system_web_app_info.h
index 4fe10246..9da02b4b 100644
--- a/chrome/browser/ash/web_applications/scanning_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/scanning_system_web_app_info.h
@@ -9,20 +9,20 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class ScanningSystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit ScanningSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldCaptureNavigations() const override;
   gfx::Size GetMinimumWindowSize() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForScanningSystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForScanningSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_SCANNING_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.cc b/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.cc
index 48cd0a2..a1b6126 100644
--- a/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.cc
@@ -15,9 +15,9 @@
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForShimlessRMASystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIShimlessRMAUrl);
   info->scope = GURL(ash::kChromeUIShimlessRMAUrl);
   info->title = l10n_util::GetStringUTF16(IDS_ASH_SHIMLESS_RMA_APP_TITLE);
@@ -39,8 +39,8 @@
                                     GURL(ash::kChromeUIShimlessRMAUrl),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo>
-ShimlessRMASystemAppDelegate::GetWebAppInfo() const {
+std::unique_ptr<WebAppInstallInfo> ShimlessRMASystemAppDelegate::GetWebAppInfo()
+    const {
   return CreateWebAppInfoForShimlessRMASystemWebApp();
 }
 
diff --git a/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.h b/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.h
index 86cc3f4..6add399 100644
--- a/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/shimless_rma_system_web_app_info.h
@@ -10,14 +10,14 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class ShimlessRMASystemAppDelegate : public web_app::SystemWebAppDelegate {
  public:
   explicit ShimlessRMASystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldCaptureNavigations() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldShowInSearch() const override;
@@ -26,8 +26,7 @@
   bool IsAppEnabled() const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo>
-CreateWebAppInfoForShimlessRMASystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForShimlessRMASystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_SHIMLESS_RMA_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.cc b/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.cc
index c5be6c8..8da7552 100644
--- a/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.cc
@@ -16,9 +16,9 @@
 #include "ui/base/ui_base_features.h"
 
 // TODO(jimmyxgong): Update to correct icon and app sizes.
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForShortcutCustomizationSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL(ash::kChromeUIShortcutCustomizationAppURL);
   info->scope = GURL(ash::kChromeUIShortcutCustomizationAppURL);
   info->title =
@@ -48,7 +48,7 @@
           GURL(ash::kChromeUIShortcutCustomizationAppURL),
           profile) {}
 
-std::unique_ptr<WebApplicationInfo>
+std::unique_ptr<WebAppInstallInfo>
 ShortcutCustomizationSystemAppDelegate::GetWebAppInfo() const {
   return CreateWebAppInfoForShortcutCustomizationSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.h b/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.h
index e46e2304..736c1c9a 100644
--- a/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/shortcut_customization_system_web_app_info.h
@@ -10,7 +10,7 @@
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
 #include "ui/gfx/geometry/size.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 class ShortcutCustomizationSystemAppDelegate
     : public web_app::SystemWebAppDelegate {
@@ -18,12 +18,12 @@
   explicit ShortcutCustomizationSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   gfx::Size GetMinimumWindowSize() const override;
   bool IsAppEnabled() const override;
 };
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo>
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo>
 CreateWebAppInfoForShortcutCustomizationSystemWebApp();
 
 #endif  // CHROME_BROWSER_ASH_WEB_APPLICATIONS_SHORTCUT_CUSTOMIZATION_SYSTEM_WEB_APP_INFO_H_
diff --git a/chrome/browser/ash/web_applications/system_web_app_install_utils.cc b/chrome/browser/ash/web_applications/system_web_app_install_utils.cc
index 3d1070c..c2a5ad0 100644
--- a/chrome/browser/ash/web_applications/system_web_app_install_utils.cc
+++ b/chrome/browser/ash/web_applications/system_web_app_install_utils.cc
@@ -15,7 +15,7 @@
 void CreateIconInfoForSystemWebApp(
     const GURL& app_url,
     const std::initializer_list<IconResourceInfo>& manifest_icons,
-    WebApplicationInfo& web_app) {
+    WebAppInstallInfo& web_app) {
   for (const auto& info : manifest_icons) {
     web_app.manifest_icons.emplace_back(app_url.Resolve(info.icon_name),
                                         info.size);
diff --git a/chrome/browser/ash/web_applications/system_web_app_install_utils.h b/chrome/browser/ash/web_applications/system_web_app_install_utils.h
index 4320a4c..6908fd6 100644
--- a/chrome/browser/ash/web_applications/system_web_app_install_utils.h
+++ b/chrome/browser/ash/web_applications/system_web_app_install_utils.h
@@ -26,7 +26,7 @@
 void CreateIconInfoForSystemWebApp(
     const GURL& app_url,
     const std::initializer_list<IconResourceInfo>& manifest_icons,
-    WebApplicationInfo& web_app);
+    WebAppInstallInfo& web_app);
 
 // Get correct ChromeOS background color based on if dark mode is requested and
 // if kSemanticColorsDebugOverride is enabled.
diff --git a/chrome/browser/ash/web_applications/terminal_system_web_app_info.cc b/chrome/browser/ash/web_applications/terminal_system_web_app_info.cc
index d96d608..6160069 100644
--- a/chrome/browser/ash/web_applications/terminal_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/terminal_system_web_app_info.cc
@@ -31,8 +31,8 @@
 constexpr gfx::Size TERMINAL_SETTINGS_DEFAULT_SIZE(768, 512);
 }  // namespace
 
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForTerminalSystemWebApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForTerminalSystemWebApp() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   // URL used for crostini::kCrostiniTerminalSystemAppId.
   const GURL terminal_url("chrome-untrusted://terminal/html/terminal.html");
   info->start_url = terminal_url;
@@ -72,7 +72,7 @@
                                     GURL(chrome::kChromeUIUntrustedTerminalURL),
                                     profile) {}
 
-std::unique_ptr<WebApplicationInfo> TerminalSystemAppDelegate::GetWebAppInfo()
+std::unique_ptr<WebAppInstallInfo> TerminalSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForTerminalSystemWebApp();
 }
diff --git a/chrome/browser/ash/web_applications/terminal_system_web_app_info.h b/chrome/browser/ash/web_applications/terminal_system_web_app_info.h
index 37e7985..cdee2be1 100644
--- a/chrome/browser/ash/web_applications/terminal_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/terminal_system_web_app_info.h
@@ -12,7 +12,7 @@
 #include "chrome/common/webui_url_constants.h"
 #include "ui/gfx/geometry/rect.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 class Browser;
 
 class TerminalSystemAppDelegate : public web_app::SystemWebAppDelegate {
@@ -20,7 +20,7 @@
   explicit TerminalSystemAppDelegate(Profile* profile);
 
   // web_app::SystemWebAppDelegate overrides:
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
   bool ShouldReuseExistingWindow() const override;
   bool ShouldShowNewWindowMenuOption() const override;
   bool ShouldHaveTabStrip() const override;
@@ -33,8 +33,8 @@
                                         int command_id) const override;
 };
 
-// Returns a WebApplicationInfo used to install the app.
-std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForTerminalSystemWebApp();
+// Returns a WebAppInstallInfo used to install the app.
+std::unique_ptr<WebAppInstallInfo> CreateWebAppInfoForTerminalSystemWebApp();
 
 // Returns the default bounds.
 gfx::Rect GetDefaultBoundsForTerminal(Browser* browser);
diff --git a/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
index 7680ed9..086bf1e 100644
--- a/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_origin_identifier_value_map_unittest.cc
@@ -19,14 +19,16 @@
   EXPECT_EQ(nullptr, map.GetValue(GURL("http://www.google.com"),
                                   GURL("http://www.google.com"),
                                   ContentSettingsType::COOKIES));
+
   map.SetValue(ContentSettingsPattern::FromString("[*.]google.com"),
                ContentSettingsPattern::FromString("[*.]google.com"),
                ContentSettingsType::COOKIES, base::Time(), base::Value(1), {});
 
-  std::unique_ptr<base::Value> expected_value(new base::Value(1));
-  EXPECT_TRUE(expected_value->Equals(
+  const base::Value* value =
       map.GetValue(GURL("http://www.google.com"), GURL("http://www.google.com"),
-                   ContentSettingsType::COOKIES)));
+                   ContentSettingsType::COOKIES);
+  ASSERT_TRUE(value);
+  EXPECT_EQ(base::Value(1), *value);
 
   EXPECT_EQ(nullptr, map.GetValue(GURL("http://www.google.com"),
                                   GURL("http://www.youtube.com"),
diff --git a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
index 5db8a0462..a9f6b2cf 100644
--- a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
@@ -193,11 +193,11 @@
       cert_filter_setting.FindKeyOfType("filters", base::Value::Type::LIST);
   ASSERT_TRUE(cert_filters);
   ASSERT_FALSE(cert_filters->GetList().empty());
-  base::DictionaryValue* filter;
-  ASSERT_TRUE(cert_filters->GetList().front().GetAsDictionary(&filter));
-  std::string actual_common_name;
-  ASSERT_TRUE(filter->GetString("ISSUER.CN", &actual_common_name));
-  EXPECT_EQ("issuer name", actual_common_name);
+  auto& filter = cert_filters->GetList().front();
+  ASSERT_TRUE(filter.is_dict());
+  const std::string* actual_common_name = filter.FindStringPath("ISSUER.CN");
+  ASSERT_TRUE(actual_common_name);
+  EXPECT_EQ("issuer name", *actual_common_name);
   provider.ShutdownOnUIThread();
 }
 
diff --git a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
index 8bfa37b..09b8d09b 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
@@ -163,18 +163,15 @@
 
   // Set some pref data. Each content setting type has the following value:
   // {"[*.]example.com": {"setting": 1}}
-  base::DictionaryValue pref_data;
-
-  base::DictionaryValue plugins_data_pref;
-  auto dict = std::make_unique<base::DictionaryValue>();
+  base::Value plugins_data_pref(base::Value::Type::DICTIONARY);
   constexpr char kFlagKey[] = "flashPreviouslyChanged";
   plugins_data_pref.SetKey(kFlagKey,
-                           base::Value::FromUniquePtrValue(std::move(dict)));
+                           base::Value(base::Value::Type::DICTIONARY));
 
-  auto data_for_pattern = std::make_unique<base::DictionaryValue>();
-  data_for_pattern->SetInteger("setting", CONTENT_SETTING_ALLOW);
-  pref_data.SetKey(
-      kPattern, base::Value::FromUniquePtrValue(std::move(data_for_pattern)));
+  base::Value data_for_pattern(base::Value::Type::DICTIONARY);
+  data_for_pattern.SetIntKey("setting", CONTENT_SETTING_ALLOW);
+  base::Value pref_data(base::Value::Type::DICTIONARY);
+  pref_data.SetKey(kPattern, std::move(data_for_pattern));
   prefs->Set(kFullscreenPrefPath, pref_data);
 #if !defined(OS_ANDROID)
   prefs->Set(kMouselockPrefPath, pref_data);
@@ -386,8 +383,9 @@
   DeadlockCheckerObserver observer(&prefs, &provider);
   {
     DictionaryPrefUpdate update(&prefs, info->pref_name());
-    base::DictionaryValue* mutable_settings = update.Get();
-    mutable_settings->SetKey("www.example.com,*", base::DictionaryValue());
+    base::Value* mutable_settings = update.Get();
+    mutable_settings->SetKey("www.example.com,*",
+                             base::Value(base::Value::Type::DICTIONARY));
   }
   EXPECT_TRUE(observer.notification_received());
 
@@ -498,7 +496,7 @@
   ContentSettingsPattern pattern =
       ContentSettingsPattern::FromString("google.com");
   ContentSettingsPattern wildcard = ContentSettingsPattern::FromString("*");
-  std::unique_ptr<base::Value> value(new base::Value(CONTENT_SETTING_ALLOW));
+  base::Value value(CONTENT_SETTING_ALLOW);
 
   PrefProvider provider(&prefs, /*off_the_record=*/false,
                         /*store_last_modified=*/true,
@@ -507,21 +505,20 @@
   // Non-empty pattern, syncable, empty resource identifier.
   provider.SetWebsiteSetting(pattern, wildcard, ContentSettingsType::JAVASCRIPT,
 
-                             value->Clone(), {});
+                             value.Clone(), {});
 
   // Non-empty pattern, non-syncable, empty resource identifier.
   provider.SetWebsiteSetting(
-      pattern, wildcard, ContentSettingsType::GEOLOCATION, value->Clone(), {});
+      pattern, wildcard, ContentSettingsType::GEOLOCATION, value.Clone(), {});
 
   // Non-empty pattern, syncable, empty resource identifier.
   provider.SetWebsiteSetting(pattern, wildcard, ContentSettingsType::COOKIES,
 
-                             value->Clone(), {});
+                             value.Clone(), {});
 
   // Non-empty pattern, non-syncable, empty resource identifier.
-  provider.SetWebsiteSetting(pattern, wildcard,
-                             ContentSettingsType::NOTIFICATIONS, value->Clone(),
-                             {});
+  provider.SetWebsiteSetting(
+      pattern, wildcard, ContentSettingsType::NOTIFICATIONS, value.Clone(), {});
 
   // Test that the preferences for images, geolocation and plugins get cleared.
   WebsiteSettingsRegistry* registry = WebsiteSettingsRegistry::GetInstance();
@@ -533,7 +530,7 @@
   // Expect the prefs are not empty before we trigger clearing them.
   for (const char* pref : cleared_prefs) {
     DictionaryPrefUpdate update(&prefs, pref);
-    const base::DictionaryValue* dictionary = update.Get();
+    const base::Value* dictionary = update.Get();
     ASSERT_FALSE(dictionary->DictEmpty());
   }
 
@@ -543,7 +540,7 @@
   // Ensure they become empty afterwards.
   for (const char* pref : cleared_prefs) {
     DictionaryPrefUpdate update(&prefs, pref);
-    const base::DictionaryValue* dictionary = update.Get();
+    const base::Value* dictionary = update.Get();
     EXPECT_TRUE(dictionary->DictEmpty());
   }
 
@@ -555,7 +552,7 @@
 
   for (const char* pref : nonempty_prefs) {
     DictionaryPrefUpdate update(&prefs, pref);
-    const base::DictionaryValue* dictionary = update.Get();
+    const base::Value* dictionary = update.Get();
     EXPECT_EQ(1u, dictionary->DictSize());
   }
 
diff --git a/chrome/browser/content_settings/content_settings_supervised_provider.cc b/chrome/browser/content_settings/content_settings_supervised_provider.cc
index df82bcf..fe0a4143 100644
--- a/chrome/browser/content_settings/content_settings_supervised_provider.cc
+++ b/chrome/browser/content_settings/content_settings_supervised_provider.cc
@@ -62,8 +62,7 @@
                               base::Unretained(this)));
 }
 
-SupervisedProvider::~SupervisedProvider() {
-}
+SupervisedProvider::~SupervisedProvider() = default;
 
 std::unique_ptr<RuleIterator> SupervisedProvider::GetRuleIterator(
     ContentSettingsType content_type,
@@ -80,7 +79,7 @@
     base::AutoLock auto_lock(lock_);
     for (const auto& entry : kContentSettingsFromSupervisedSettingsMap) {
       ContentSetting new_setting = CONTENT_SETTING_DEFAULT;
-      if (settings && settings->HasKey(entry.setting_name)) {
+      if (settings && settings->FindKey(entry.setting_name)) {
         DCHECK(settings->FindKey(entry.setting_name)->is_bool());
         if (settings->FindBoolKey(entry.setting_name).value_or(false))
           new_setting = entry.content_setting;
diff --git a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
index bdc1a9b..adaf1e3 100644
--- a/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
+++ b/chrome/browser/content_settings/generated_cookie_prefs_unittest.cc
@@ -36,10 +36,9 @@
     CookiePrimarySetting pref_value,
     ContentSetting expected_content_setting,
     CookieControlsMode expected_cookie_controls_mode) {
-  EXPECT_EQ(
-      generated_pref->SetPref(
-          std::make_unique<base::Value>(static_cast<int>(pref_value)).get()),
-      extensions::settings_private::SetPrefResult::SUCCESS);
+  base::Value pref(static_cast<int>(pref_value));
+  EXPECT_EQ(generated_pref->SetPref(&pref),
+            extensions::settings_private::SetPrefResult::SUCCESS);
   EXPECT_EQ(
       map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr),
       expected_content_setting);
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
index 397822a..877cc104 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -1113,15 +1113,17 @@
 TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeAndPunycode) {
   TestingProfile profile;
 
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(
-      "{\"[*.]\\xC4\\x87ira.com,*\":{\"setting\":1}}");
-  profile.GetPrefs()->Set(GetPrefName(ContentSettingsType::COOKIES), *value);
+  base::Value value =
+      base::JSONReader::Read("{\"[*.]\\xC4\\x87ira.com,*\":{\"setting\":1}}")
+          .value();
+  profile.GetPrefs()->Set(GetPrefName(ContentSettingsType::COOKIES), value);
 
   // Set punycode equivalent, with different setting.
-  std::unique_ptr<base::Value> puny_value = base::JSONReader::ReadDeprecated(
-      "{\"[*.]xn--ira-ppa.com,*\":{\"setting\":2}}");
+  base::Value puny_value =
+      base::JSONReader::Read("{\"[*.]xn--ira-ppa.com,*\":{\"setting\":2}}")
+          .value();
   profile.GetPrefs()->Set(GetPrefName(ContentSettingsType::COOKIES),
-                          *puny_value);
+                          puny_value);
 
   // Initialize the content map.
   HostContentSettingsMapFactory::GetForProfile(&profile);
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index 6043813..2f77dbe 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -171,14 +171,13 @@
                                               nullptr)
           : map->GetContentSetting(primary_url, secondary_url, content_type);
 
-  std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+  base::Value result(base::Value::Type::DICTIONARY);
   std::string setting_string =
       content_settings::ContentSettingToString(setting);
   DCHECK(!setting_string.empty());
-  result->SetString(ContentSettingsStore::kContentSettingKey, setting_string);
+  result.SetStringKey(ContentSettingsStore::kContentSettingKey, setting_string);
 
-  return RespondNow(
-      OneArgument(base::Value::FromUniquePtrValue(std::move(result))));
+  return RespondNow(OneArgument(std::move(result)));
 }
 
 ExtensionFunction::ResponseAction
diff --git a/chrome/browser/extensions/api/crash_report_private/crash_report_private_apitest.cc b/chrome/browser/extensions/api/crash_report_private/crash_report_private_apitest.cc
index f6801c4d..a237fe3e 100644
--- a/chrome/browser/extensions/api/crash_report_private/crash_report_private_apitest.cc
+++ b/chrome/browser/extensions/api/crash_report_private/crash_report_private_apitest.cc
@@ -326,7 +326,7 @@
   ASSERT_TRUE(embedded_test_server()->Started());
   // Create and launch a test web app, opens in an app window.
   GURL start_url = embedded_test_server()->GetURL("/test_app.html");
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app::AppId app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index 33eb06db..84a51b8 100644
--- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -261,7 +261,7 @@
     }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->title = base::UTF8ToUTF16(title);
     web_app_info->start_url = launch_url;
     web_app_info->display_mode = web_app::DisplayMode::kBrowser;
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index 6f179d2..6a76b2d 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -184,7 +184,7 @@
   std::unique_ptr<ExtensionSet> all_extensions =
       registry->GenerateInstalledExtensionsSet();
   for (const auto& extension : *all_extensions) {
-    if (extension->from_desprecated_bookmark()) {
+    if (extension->from_deprecated_bookmark()) {
       // Deleting deprecated bookmark apps.
       const std::string& id = extension->id();
       std::u16string error;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 37b9e489..9c54e1d4 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -981,7 +981,7 @@
   {
     "name": "crosh-swa",
     "owners": [ "joelhockey", "benwells" ],
-    "expiry_milestone": 100
+    "expiry_milestone": 110
   },
   {
       "name": "cross-origin-embedder-policy-credentialless",
diff --git a/chrome/browser/lacros/standalone_browser_test_controller.cc b/chrome/browser/lacros/standalone_browser_test_controller.cc
index 8eb15c5..a6e1228 100644
--- a/chrome/browser/lacros/standalone_browser_test_controller.cc
+++ b/chrome/browser/lacros/standalone_browser_test_controller.cc
@@ -41,7 +41,7 @@
     const std::string& start_url,
     apps::mojom::WindowMode window_mode,
     InstallWebAppCallback callback) {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->title = u"Test Web App";
   info->start_url = GURL(start_url);
   info->display_mode = WindowModeToDisplayMode(window_mode);
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
index 9317fb4..69dff44b 100644
--- a/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
+++ b/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc
@@ -403,7 +403,8 @@
   primary_root_window->Init(ui::LAYER_NOT_DRAWN);
   SetPrimaryRootWindow(primary_root_window.get());
 
-  blink::mojom::MediaStreamRequestResult result;
+  blink::mojom::MediaStreamRequestResult result =
+      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
   blink::MediaStreamDevices devices;
 
   ProcessGenerateStreamRequest(/*requested_video_device_id=*/std::string(),
@@ -414,6 +415,39 @@
   EXPECT_EQ(0u, devices.size());
 }
 
+TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpNotRestricted) {
+  // Setup Data Leak Prevention restriction.
+  policy::MockDlpContentManagerAsh mock_dlp_content_manager;
+  policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager(
+      &mock_dlp_content_manager);
+  EXPECT_CALL(mock_dlp_content_manager, IsScreenCaptureRestricted(testing::_))
+      .Times(1)
+      .WillOnce(testing::Return(false));
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      switches::kEnableUserMediaScreenCapturing);
+
+  extensions::ExtensionBuilder extensionBuilder(kComponentExtension);
+  extensionBuilder.SetLocation(extensions::mojom::ManifestLocation::kComponent);
+  auto extension = extensionBuilder.Build();
+
+  std::unique_ptr<aura::Window> primary_root_window =
+      std::make_unique<aura::Window>(/*delegate=*/nullptr);
+  primary_root_window->Init(ui::LAYER_NOT_DRAWN);
+  SetPrimaryRootWindow(primary_root_window.get());
+
+  blink::mojom::MediaStreamRequestResult result =
+      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
+  blink::MediaStreamDevices devices;
+
+  ProcessGenerateStreamRequest(/*requested_video_device_id=*/std::string(),
+                               GURL(kOrigin), extension.get(), &result,
+                               &devices);
+
+  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
+  EXPECT_EQ(1u, devices.size());
+}
+
 TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpRestricted) {
   // Setup Data Leak Prevention restriction.
   policy::MockDlpContentManagerAsh mock_dlp_content_manager;
@@ -443,6 +477,35 @@
   EXPECT_EQ(0u, devices.size());
 }
 
+TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpNotRestricted) {
+  // Setup Data Leak Prevention restriction.
+  policy::MockDlpContentManagerAsh mock_dlp_content_manager;
+  policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager(
+      &mock_dlp_content_manager);
+  EXPECT_CALL(mock_dlp_content_manager, IsScreenCaptureRestricted(testing::_))
+      .Times(1)
+      .WillOnce(testing::Return(false));
+
+  const std::string id =
+      content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
+          web_contents()->GetMainFrame()->GetProcess()->GetID(),
+          web_contents()->GetMainFrame()->GetRoutingID(),
+          url::Origin::Create(GURL(kOrigin)),
+          content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
+                                  content::DesktopMediaID::kFakeId),
+          /*extension_name=*/"",
+          content::DesktopStreamRegistryType::kRegistryStreamTypeDesktop);
+  blink::mojom::MediaStreamRequestResult result =
+      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
+  blink::MediaStreamDevices devices;
+
+  ProcessGenerateStreamRequest(id, GURL(kOrigin), /*extension=*/nullptr,
+                               &result, &devices);
+
+  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
+  EXPECT_EQ(1u, devices.size());
+}
+
 TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpRestricted) {
   // Setup Data Leak Prevention restriction.
   policy::MockDlpContentManagerAsh mock_dlp_content_manager;
@@ -462,4 +525,24 @@
   EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
   EXPECT_EQ(0u, devices.size());
 }
+
+TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpNotRestricted) {
+  // Setup Data Leak Prevention restriction.
+  policy::MockDlpContentManagerAsh mock_dlp_content_manager;
+  policy::ScopedDlpContentManagerAshForTesting scoped_dlp_content_manager(
+      &mock_dlp_content_manager);
+  EXPECT_CALL(mock_dlp_content_manager, IsScreenCaptureRestricted(testing::_))
+      .Times(1)
+      .WillOnce(testing::Return(false));
+
+  blink::mojom::MediaStreamRequestResult result =
+      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
+  blink::MediaStreamDevices devices;
+  ProcessDeviceUpdateRequest(
+      content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
+                              content::DesktopMediaID::kFakeId),
+      &result, &devices, blink::MEDIA_DEVICE_UPDATE, /*request audio=*/false);
+  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
+  EXPECT_EQ(1u, devices.size());
+}
 #endif
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc
index f3dca47b..45281a1 100644
--- a/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc
+++ b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc
@@ -66,7 +66,7 @@
   }
 
   std::string InstallTestPWA() {
-    auto web_application_info = std::make_unique<WebApplicationInfo>();
+    auto web_application_info = std::make_unique<WebAppInstallInfo>();
     web_application_info->start_url = GURL(kUrlString);
     web_application_info->display_mode = blink::mojom::DisplayMode::kMinimalUi;
     Profile* profile = browser()->profile();
diff --git a/chrome/browser/password_manager/account_password_store_factory.cc b/chrome/browser/password_manager/account_password_store_factory.cc
index 2f00009..63af5071 100644
--- a/chrome/browser/password_manager/account_password_store_factory.cc
+++ b/chrome/browser/password_manager/account_password_store_factory.cc
@@ -49,6 +49,7 @@
 
 using password_manager::PasswordStore;
 using password_manager::PasswordStoreInterface;
+using password_manager::UnsyncedCredentialsDeletionNotifier;
 
 #if !defined(OS_ANDROID)
 
@@ -72,7 +73,7 @@
 }
 
 class UnsyncedCredentialsDeletionNotifierImpl
-    : public PasswordStore::UnsyncedCredentialsDeletionNotifier {
+    : public UnsyncedCredentialsDeletionNotifier {
  public:
   explicit UnsyncedCredentialsDeletionNotifierImpl(Profile* profile);
   ~UnsyncedCredentialsDeletionNotifierImpl() override = default;
@@ -107,7 +108,7 @@
   ui_controller->NotifyUnsyncedCredentialsWillBeDeleted(std::move(credentials));
 }
 
-base::WeakPtr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
+base::WeakPtr<UnsyncedCredentialsDeletionNotifier>
 UnsyncedCredentialsDeletionNotifierImpl::GetWeakPtr() {
   return weak_ptr_factory_.GetWeakPtr();
 }
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 8d8dc5d..c9a8418 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -2042,7 +2042,7 @@
   }
 
   Browser* InstallAndLaunchPWA(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.DeprecatedGetOriginAsURL();
     web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/policy/test/system_features_policy_browsertest.cc b/chrome/browser/policy/test/system_features_policy_browsertest.cc
index 85c0a9ca..695f27e 100644
--- a/chrome/browser/policy/test/system_features_policy_browsertest.cc
+++ b/chrome/browser/policy/test/system_features_policy_browsertest.cc
@@ -143,7 +143,7 @@
   }
 
   void InstallPWA(const GURL& app_url, const char* app_id) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url.GetWithoutFilename();
     web_app::AppId installed_app_id = web_app::test::InstallWebApp(
diff --git a/chrome/browser/prefs/pref_metrics_service.cc b/chrome/browser/prefs/pref_metrics_service.cc
index 51bec2b..d4a5d23 100644
--- a/chrome/browser/prefs/pref_metrics_service.cc
+++ b/chrome/browser/prefs/pref_metrics_service.cc
@@ -93,19 +93,6 @@
     }
   }
 #endif
-
-  // Android does not support pinned tabs.
-#if !defined(OS_ANDROID)
-  StartupTabs startup_tabs = PinnedTabCodec::ReadPinnedTabs(profile_);
-  for (size_t i = 0; i < startup_tabs.size(); ++i) {
-    GURL start_url(startup_tabs.at(i).url);
-    if (start_url.is_valid()) {
-      UMA_HISTOGRAM_ENUMERATION("Settings.PinnedTabEngineTypes",
-                                SearchEngineUtils::GetEngineType(start_url),
-                                SEARCH_ENGINE_MAX);
-    }
-  }
-#endif
 }
 
 // static
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc
index f075430..fdb62cc5 100644
--- a/chrome/browser/printing/print_browsertest.cc
+++ b/chrome/browser/printing/print_browsertest.cc
@@ -836,6 +836,36 @@
                          "window.scrollX"));
 }
 
+// https://crbug.com/1285208
+IN_PROC_BROWSER_TEST_F(PrintBrowserTest, LegacyLayoutEngineFallback) {
+  ASSERT_TRUE(embedded_test_server()->Started());
+  GURL url(embedded_test_server()->GetURL(
+      "/printing/legacy-layout-engine-known-bug.html"));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
+  auto* contents = browser()->tab_strip_model()->GetActiveWebContents();
+  const char kExpression[] = "target.offsetHeight";
+
+  // The non-printed document should be laid out with LayoutNG. We're testing
+  // this by looking for a known margin-collapsing / clearance bug in the legacy
+  // engine, not present in LayoutNG. The height should be 0 if the bug isn't
+  // present.
+
+  double old_height = content::EvalJs(contents, kExpression).ExtractDouble();
+  if (old_height != 0) {
+    // LayoutNG seems to be disabled. There's nothing useful to test here then.
+    return;
+  }
+
+  // Entering print preview may trigger legacy engine fallback, but this should
+  // only be temporary.
+  PrintAndWaitUntilPreviewIsReady(/*print_only_selection=*/false);
+
+  // The non-printed document should still be laid out with LayoutNG.
+  double new_height = content::EvalJs(contents, kExpression).ExtractDouble();
+  EXPECT_EQ(new_height, 0);
+}
+
 // Before invoking print preview, page scale is changed to a different value.
 // Test that when print preview is ready, in other words when printing is
 // finished, the page scale factor gets reset to initial scale.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index b3fd3b8e..c13e75b 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -232,7 +232,7 @@
   }
 
   AppId InstallTestWebApp(const GURL& start_url, bool open_as_window = true) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url;
     web_app_info->title = u"Test app 🐐";
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index c4da053..6670482 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -26,7 +26,6 @@
 
       <!-- Hangout Services extension, included in Google Chrome builds only. -->
       <if expr="_google_chrome or enable_hangout_services_extension">
-        <include name="IDR_HANGOUT_SERVICES_BACKGROUND_HTML" file="hangout_services/background.html" type="BINDATA" />
         <include name="IDR_HANGOUT_SERVICES_THUNK_JS" file="hangout_services/thunk.js" type="BINDATA" />
       </if>
       <if expr="not is_android">
diff --git a/chrome/browser/resources/hangout_services/background.html b/chrome/browser/resources/hangout_services/background.html
deleted file mode 100644
index 08424b1..0000000
--- a/chrome/browser/resources/hangout_services/background.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!--
-Copyright 2013 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
-
-We use an HTML page just to have access to the DOM, for URL
-parsing. An alternative would be to include a URL parsing JavaScript
-library with the extension but this approach is likely smaller and
-faster.
--->
-<html>
-<head>
-<script src="thunk.js"></script>
-</head>
-<body>
-</body>
-</html>
diff --git a/chrome/browser/resources/hangout_services/manifest.json b/chrome/browser/resources/hangout_services/manifest.json
index 556c6046..e3300e4b 100644
--- a/chrome/browser/resources/hangout_services/manifest.json
+++ b/chrome/browser/resources/hangout_services/manifest.json
@@ -5,16 +5,15 @@
   "name": "Google Hangouts",
   // Note: Always update the version number when this file is updated. Chrome
   // triggers extension preferences update on the version increase.
-  "version": "1.3.16",
-  "manifest_version": 2,
+  "version": "1.3.17",
+  "manifest_version": 3,
   "externally_connectable": {
     "matches": [
       "https://*.google.com/*"
     ]
   },
   "background": {
-    "page": "background.html",
-    "persistent": false
+    "service_worker": "thunk.js"
   },
   "incognito": "split",
   "permissions": [
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
index 89c1213c..55c746a 100644
--- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
+++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
@@ -18,6 +18,7 @@
 import '../settings_vars_css.js';
 import './passwords_shared_css.js';
 
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
@@ -32,10 +33,16 @@
 
 export interface PasswordEditDialogElement {
   $: {
+    actionButton: CrButtonElement,
+    cancel: CrButtonElement,
     dialog: CrDialogElement,
+    footnote: HTMLElement,
     passwordInput: CrInputElement,
+    storageDetails: HTMLElement,
     storePicker: HTMLSelectElement,
+    title: HTMLElement,
     usernameInput: CrInputElement,
+    viewExistingPasswordLink: HTMLElement,
     websiteInput: CrInputElement,
   };
 }
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index bd34a90..b1f446e 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -3209,7 +3209,7 @@
   }
 
   web_app::AppId InstallPWA(Profile* profile, const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 9bafc48f..6dc3e8d37 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -836,7 +836,7 @@
   }
 
   Browser* InstallAndOpenTestWebApp(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->title = u"Test app";
diff --git a/chrome/browser/sync/test/integration/apps_helper.cc b/chrome/browser/sync/test/integration/apps_helper.cc
index 8d1ca92..2b357874 100644
--- a/chrome/browser/sync/test/integration/apps_helper.cc
+++ b/chrome/browser/sync/test/integration/apps_helper.cc
@@ -222,13 +222,13 @@
   }
 }
 
-web_app::AppId InstallWebApp(Profile* profile, const WebApplicationInfo& info) {
+web_app::AppId InstallWebApp(Profile* profile, const WebAppInstallInfo& info) {
   DCHECK(info.start_url.is_valid());
   base::RunLoop run_loop;
   web_app::AppId app_id;
   auto* provider = web_app::WebAppProvider::GetForTest(profile);
   provider->install_manager().InstallWebAppFromInfo(
-      std::make_unique<WebApplicationInfo>(info),
+      std::make_unique<WebAppInstallInfo>(info),
       /*overwrite_existing_manifest_fields=*/true,
       web_app::ForInstallableSite::kYes,
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
diff --git a/chrome/browser/sync/test/integration/apps_helper.h b/chrome/browser/sync/test/integration/apps_helper.h
index 70fe2a1..8da5454 100644
--- a/chrome/browser/sync/test/integration/apps_helper.h
+++ b/chrome/browser/sync/test/integration/apps_helper.h
@@ -47,9 +47,9 @@
 // verifier), and returns the extension ID of the new app.
 std::string InstallHostedAppForAllProfiles(int index);
 
-// Installs the web app for the given WebApplicationInfo and profile. This does
+// Installs the web app for the given WebAppInstallInfo and profile. This does
 // not download icons or run OS integration installs.
-web_app::AppId InstallWebApp(Profile* profile, const WebApplicationInfo& info);
+web_app::AppId InstallWebApp(Profile* profile, const WebAppInstallInfo& info);
 
 // Uninstalls the app for the given index from |profile|. Assumes that it was
 // previously installed.
diff --git a/chrome/browser/sync/test/integration/retry_verifier.cc b/chrome/browser/sync/test/integration/exponential_backoff_helper.cc
similarity index 76%
rename from chrome/browser/sync/test/integration/retry_verifier.cc
rename to chrome/browser/sync/test/integration/exponential_backoff_helper.cc
index 67091f0..36acaeb 100644
--- a/chrome/browser/sync/test/integration/retry_verifier.cc
+++ b/chrome/browser/sync/test/integration/exponential_backoff_helper.cc
@@ -2,16 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/sync/test/integration/retry_verifier.h"
+#include "chrome/browser/sync/test/integration/exponential_backoff_helper.h"
 
 #include <string.h>
 
 #include <algorithm>
+#include <ostream>
 
 #include "base/logging.h"
 #include "components/sync/engine/cycle/sync_cycle_snapshot.h"
 #include "components/sync/engine/polling_constants.h"
 
+namespace exponential_backoff_helper {
+
 namespace {
 
 // Given the current delay calculate the minimum and maximum wait times for
@@ -69,31 +72,35 @@
   return time_elapsed >= delay_table[retry_count].min_delay;
 }
 
-RetryVerifier::RetryVerifier()
-    : retry_count_(0), success_(false), done_(false) {
+ExponentialBackoffChecker::ExponentialBackoffChecker(
+    syncer::SyncServiceImpl* sync_service)
+    : SingleClientStatusChangeChecker(sync_service) {
   memset(&delay_table_, 0, sizeof(delay_table_));
-}
 
-RetryVerifier::~RetryVerifier() {}
-
-// Initializes the state for verification.
-void RetryVerifier::Initialize(const syncer::SyncCycleSnapshot& snap) {
-  retry_count_ = 0;
+  const syncer::SyncCycleSnapshot& snap =
+      service()->GetLastCycleSnapshotForDebugging();
   last_sync_time_ = snap.sync_start_time();
-  FillDelayTable(delay_table_, kMaxRetry);
-  done_ = false;
-  success_ = false;
+  FillDelayTable(delay_table_, kMaxRetriesToVerify);
 }
 
-void RetryVerifier::VerifyRetryInterval(const syncer::SyncCycleSnapshot& snap) {
-  DCHECK(retry_count_ < kMaxRetry);
+ExponentialBackoffChecker::~ExponentialBackoffChecker() = default;
+
+bool ExponentialBackoffChecker::IsExitConditionSatisfied(std::ostream* os) {
+  DCHECK(retry_count_ < kMaxRetriesToVerify);
+
+  *os << "Verifying backoff intervals (" << retry_count_ << "/"
+      << kMaxRetriesToVerify << ")";
+
+  const syncer::SyncCycleSnapshot& snap =
+      service()->GetLastCycleSnapshotForDebugging();
+
   if (retry_count_ == 0) {
     if (snap.sync_start_time() != last_sync_time_) {
       retry_count_++;
       last_sync_time_ = snap.sync_start_time();
     }
     success_ = true;
-    return;
+    return false;
   }
 
   // Check if the sync start time has changed. If so indicates a new sync
@@ -103,7 +110,10 @@
     success_ = IsRetryOnTime(delay_table_, retry_count_ - 1, delta);
     last_sync_time_ = snap.sync_start_time();
     ++retry_count_;
-    done_ = (retry_count_ >= kMaxRetry);
-    return;
+    done_ = (retry_count_ >= kMaxRetriesToVerify);
   }
+
+  return done_ && success_;
 }
+
+}  // namespace exponential_backoff_helper
diff --git a/chrome/browser/sync/test/integration/exponential_backoff_helper.h b/chrome/browser/sync/test/integration/exponential_backoff_helper.h
new file mode 100644
index 0000000..6fa9ee7
--- /dev/null
+++ b/chrome/browser/sync/test/integration/exponential_backoff_helper.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_EXPONENTIAL_BACKOFF_HELPER_H_
+#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_EXPONENTIAL_BACKOFF_HELPER_H_
+
+#include "base/time/time.h"
+#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+
+namespace exponential_backoff_helper {
+
+// The minimum and maximum wait times for a retry. The actual retry would take
+// place somewhere in this range. The algorithm that calculates the retry wait
+// time uses rand functions.
+struct DelayInfo {
+  base::TimeDelta min_delay;
+  base::TimeDelta max_delay;
+};
+
+// Helper class that checks if a sync client has successfully gone through
+// exponential backoff after it encounters an error.
+class ExponentialBackoffChecker : public SingleClientStatusChangeChecker {
+ public:
+  static constexpr int kMaxRetriesToVerify = 3;
+
+  explicit ExponentialBackoffChecker(syncer::SyncServiceImpl* sync_service);
+  ~ExponentialBackoffChecker() override;
+
+  ExponentialBackoffChecker(const ExponentialBackoffChecker&) = delete;
+  ExponentialBackoffChecker& operator=(const ExponentialBackoffChecker&) =
+      delete;
+
+  // Checks if backoff is complete. Called repeatedly each time SyncServiceImpl
+  // notifies observers of a state change.
+  bool IsExitConditionSatisfied(std::ostream* os) override;
+
+ private:
+  int retry_count_ = 0;
+  base::Time last_sync_time_;
+  DelayInfo delay_table_[kMaxRetriesToVerify];
+  bool success_ = false;
+  bool done_ = false;
+};
+
+}  // namespace exponential_backoff_helper
+
+#endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_EXPONENTIAL_BACKOFF_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/retry_verifier.h b/chrome/browser/sync/test/integration/retry_verifier.h
deleted file mode 100644
index bb0a934c..0000000
--- a/chrome/browser/sync/test/integration/retry_verifier.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_RETRY_VERIFIER_H_
-#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_RETRY_VERIFIER_H_
-
-#include <stdint.h>
-
-#include "base/time/time.h"
-
-namespace syncer {
-class SyncCycleSnapshot;
-}  // namespace syncer
-
-// The minimum and maximum wait times for a retry. The actual retry would take
-// place somewhere in this range. The algorithm that calculates the retry wait
-// time uses rand functions.
-struct DelayInfo {
-  base::TimeDelta min_delay;
-  base::TimeDelta max_delay;
-};
-
-// Class to verify retries take place using the exponential backoff algorithm.
-class RetryVerifier {
- public:
-  static const int kMaxRetry = 3;
-  RetryVerifier();
-
-  RetryVerifier(const RetryVerifier&) = delete;
-  RetryVerifier& operator=(const RetryVerifier&) = delete;
-
-  ~RetryVerifier();
-  int retry_count() const { return retry_count_; }
-
-  // Initialize with the current sync session snapshot. Using the snapshot
-  // we will figure out when the first retry sync happened.
-  void Initialize(const syncer::SyncCycleSnapshot& snap);
-  void VerifyRetryInterval(const syncer::SyncCycleSnapshot& snap);
-  bool done() const { return done_; }
-  bool Succeeded() const { return done() && success_; }
-
- private:
-  int retry_count_;
-  base::Time last_sync_time_;
-  DelayInfo delay_table_[kMaxRetry];
-  bool success_;
-  bool done_;
-};
-
-#endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_RETRY_VERIFIER_H_
diff --git a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
index 420d9019..8789d22 100644
--- a/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_web_apps_sync_test.cc
@@ -192,7 +192,7 @@
 IN_PROC_BROWSER_TEST_F(SingleClientWebAppsSyncTest,
                        AppInstallDoNotSyncBookmarkApp) {
   ASSERT_TRUE(SetupSync());
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   std::string name = "Test name";
   info.title = base::UTF8ToUTF16(name);
   info.description = u"Test description";
@@ -237,7 +237,7 @@
 
   EXPECT_TRUE(web_app_registrar.IsInstalled(app_id));
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   std::string name = "Test name";
   info.title = base::UTF8ToUTF16(app_id);
   info.description = u"Test description";
@@ -267,7 +267,7 @@
 
   EXPECT_TRUE(web_app_registrar.IsInstalled(app_id));
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   std::string name = "Test name";
   info.title = base::UTF8ToUTF16(app_id);
   info.description = u"Test description";
diff --git a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
index 4298e3c..116cc43 100644
--- a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
+++ b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
@@ -5,8 +5,7 @@
 #include "base/bind.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
-#include "chrome/browser/sync/test/integration/retry_verifier.h"
-#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/exponential_backoff_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "components/sync/driver/sync_service_impl.h"
@@ -19,7 +18,7 @@
 
 using bookmarks_helper::AddFolder;
 using bookmarks_helper::ServerBookmarksEqualityChecker;
-using syncer::SyncCycleSnapshot;
+using exponential_backoff_helper::ExponentialBackoffChecker;
 
 class SyncExponentialBackoffTest : public SyncTest {
  public:
@@ -38,39 +37,6 @@
   }
 };
 
-// Helper class that checks if a sync client has successfully gone through
-// exponential backoff after it encounters an error.
-class ExponentialBackoffChecker : public SingleClientStatusChangeChecker {
- public:
-  explicit ExponentialBackoffChecker(syncer::SyncServiceImpl* sync_service)
-      : SingleClientStatusChangeChecker(sync_service) {
-    const SyncCycleSnapshot& snap =
-        service()->GetLastCycleSnapshotForDebugging();
-    retry_verifier_.Initialize(snap);
-  }
-
-  ExponentialBackoffChecker(const ExponentialBackoffChecker&) = delete;
-  ExponentialBackoffChecker& operator=(const ExponentialBackoffChecker&) =
-      delete;
-
-  // Checks if backoff is complete. Called repeatedly each time SyncServiceImpl
-  // notifies observers of a state change.
-  bool IsExitConditionSatisfied(std::ostream* os) override {
-    *os << "Verifying backoff intervals (" << retry_verifier_.retry_count()
-        << "/" << RetryVerifier::kMaxRetry << ")";
-
-    const SyncCycleSnapshot& snap =
-        service()->GetLastCycleSnapshotForDebugging();
-    retry_verifier_.VerifyRetryInterval(snap);
-    return (retry_verifier_.done() && retry_verifier_.Succeeded());
-  }
-
- private:
-  // Keeps track of the number of attempts at exponential backoff and its
-  // related bookkeeping information for verification.
-  RetryVerifier retry_verifier_;
-};
-
 // Flaky on ChromeOS, crbug.com/1170609
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #define MAYBE_OfflineToOnline DISABLED_OfflineToOnline
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
index e59b662..f23f003 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
@@ -77,7 +77,7 @@
   AppId InstallDummyAppAndWaitForSync(const GURL& url,
                                       Profile* profile1,
                                       Profile* profile2) {
-    WebApplicationInfo info = WebApplicationInfo();
+    WebAppInstallInfo info = WebAppInstallInfo();
     info.title = base::UTF8ToUTF16(url.spec());
     info.start_url = url;
     AppId dummy_app_id = InstallApp(info, profile1);
@@ -123,12 +123,12 @@
     return app_id;
   }
 
-  AppId InstallApp(const WebApplicationInfo& info, Profile* profile) {
+  AppId InstallApp(const WebAppInstallInfo& info, Profile* profile) {
     return InstallApp(info, profile,
                       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
   }
 
-  AppId InstallApp(const WebApplicationInfo& info,
+  AppId InstallApp(const WebAppInstallInfo& info,
                    Profile* profile,
                    webapps::WebappInstallSource source) {
     DCHECK(info.start_url.is_valid());
@@ -139,7 +139,7 @@
     WebAppProvider::GetForTest(profile)
         ->install_manager()
         .InstallWebAppFromInfo(
-            std::make_unique<WebApplicationInfo>(info),
+            std::make_unique<WebAppInstallInfo>(info),
             /*overwrite_existing_manifest_fields=*/true,
             ForInstallableSite::kYes, source,
             base::BindLambdaForTesting(
@@ -215,7 +215,7 @@
 IN_PROC_BROWSER_TEST_F(TwoClientWebAppsBMOSyncTest,
                        SyncDoubleInstallationDifferentNames) {
   ASSERT_TRUE(SetupClients());
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/path");
 
@@ -256,7 +256,7 @@
   ASSERT_TRUE(SetupClients());
   ASSERT_TRUE(AllProfilesHaveSameWebAppIds());
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/path");
   info.user_display_mode = DisplayMode::kStandalone;
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
index 20fff268..6b9f12d 100644
--- a/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_web_apps_sync_test.cc
@@ -92,7 +92,7 @@
   WebAppTestInstallObserver install_observer(GetProfile(1));
   install_observer.BeginListening();
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.description = u"Test description";
   info.start_url = GURL("http://www.chromium.org/path");
@@ -112,7 +112,7 @@
   WebAppTestInstallObserver install_observer(GetProfile(1));
   install_observer.BeginListening();
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
   AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
@@ -129,7 +129,7 @@
   WebAppTestInstallObserver install_observer(GetProfile(1));
   install_observer.BeginListening();
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
   info.theme_color = SK_ColorBLUE;
@@ -150,7 +150,7 @@
   WebAppTestInstallObserver install_observer(GetProfile(1));
   install_observer.BeginListening();
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.start_url = GURL("http://www.chromium.org/");
   AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
@@ -168,7 +168,7 @@
   const WebAppRegistrar& registrar0 = GetRegistrar(GetProfile(0));
   const WebAppRegistrar& registrar1 = GetRegistrar(GetProfile(1));
 
-  WebApplicationInfo info_a;
+  WebAppInstallInfo info_a;
   info_a.title = u"Test name A";
   info_a.description = u"Description A";
   info_a.start_url = GURL("http://www.chromium.org/path/to/start_url");
@@ -188,7 +188,7 @@
 
   // Reinstall same app in Profile 0 with a different metadata aside from the
   // name and start_url.
-  WebApplicationInfo info_b;
+  WebAppInstallInfo info_b;
   info_b.title = u"Test name B";
   info_b.description = u"Description B";
   info_b.start_url = GURL("http://www.chromium.org/path/to/start_url");
@@ -205,7 +205,7 @@
 
   // Install a separate app just to have something to await on to ensure the
   // sync has propagated to the other profile.
-  WebApplicationInfo infoC;
+  WebAppInstallInfo infoC;
   infoC.title = u"Different test name";
   infoC.start_url = GURL("http://www.notchromium.org/");
   AppId app_id_c = apps_helper::InstallWebApp(GetProfile(0), infoC);
@@ -277,7 +277,7 @@
   dest_install_observer.BeginListening();
 
   // Install app with name.
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test app";
   info.start_url =
       embedded_test_server()->GetURL("/web_apps/different_start_url.html");
@@ -307,7 +307,7 @@
   dest_install_observer.BeginListening();
 
   // Install app with name.
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Correct App Name";
   info.start_url =
       embedded_test_server()->GetURL("/web_apps/bad_title_only.html");
@@ -334,7 +334,7 @@
   dest_install_observer.BeginListening();
 
   // Install app with name.
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Incorrect App Name";
   info.start_url = embedded_test_server()->GetURL("/web_apps/basic.html");
   AppId app_id = apps_helper::InstallWebApp(GetProfile(0), info);
@@ -358,7 +358,7 @@
   dest_install_observer.BeginListening();
 
   // Install app with name.
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Blue icon";
   info.start_url = GURL("https://does-not-exist.org");
   info.theme_color = SK_ColorBLUE;
@@ -400,7 +400,7 @@
   WebAppTestInstallObserver install_observer(GetProfile(1));
   install_observer.BeginListening();
 
-  WebApplicationInfo info;
+  WebAppInstallInfo info;
   info.title = u"Test name";
   info.description = u"Test description";
   info.start_url = GURL("http://www.chromium.org/path");
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
index 2660806..33db989d 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -337,7 +337,7 @@
   std::string CreateWebApp(const std::string& app_name) {
     const GURL kAppUrl("https://example.com/");
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->title = base::UTF8ToUTF16(app_name);
     web_app_info->start_url = kAppUrl;
     web_app_info->scope = kAppUrl;
diff --git a/chrome/browser/ui/app_list/search/ranking/types.cc b/chrome/browser/ui/app_list/search/ranking/types.cc
index 4dd3c6d..a5bacc0f 100644
--- a/chrome/browser/ui/app_list/search/ranking/types.cc
+++ b/chrome/browser/ui/app_list/search/ranking/types.cc
@@ -34,15 +34,14 @@
 }
 
 CategoriesList CreateAllCategories() {
-  CategoriesList res(
-      {{.category = Category::kApps, .score = 0.0},
-       {.category = Category::kAppShortcuts, .score = 0.0},
-       {.category = Category::kWeb, .score = 0.0},
-       {.category = Category::kFiles, .score = 0.0},
-       {.category = Category::kSettings, .score = 0.0},
-       {.category = Category::kHelp, .score = 0.0},
-       {.category = Category::kPlayStore, .score = 0.0},
-       {.category = Category::kSearchAndAssistant, .score = 0.0}});
+  CategoriesList res({{.category = Category::kApps},
+                      {.category = Category::kAppShortcuts},
+                      {.category = Category::kWeb},
+                      {.category = Category::kFiles},
+                      {.category = Category::kSettings},
+                      {.category = Category::kHelp},
+                      {.category = Category::kPlayStore},
+                      {.category = Category::kSearchAndAssistant}});
   DCHECK_EQ(res.size(), static_cast<size_t>(Category::kMaxValue));
   return res;
 }
diff --git a/chrome/browser/ui/app_list/search/ranking/types.h b/chrome/browser/ui/app_list/search/ranking/types.h
index 2160632..f1ec6e1 100644
--- a/chrome/browser/ui/app_list/search/ranking/types.h
+++ b/chrome/browser/ui/app_list/search/ranking/types.h
@@ -56,6 +56,12 @@
 struct CategoryMetadata {
   Category category = Category::kUnknown;
   double score = 0.0;
+
+  // Same purpose, meaning, and incrementing rules as the burnin_iteration
+  // member of the Scoring struct above, except this member is for categories
+  // rather than individual results. Additionally, -1 signifies that the
+  // category has not yet been seen in the current search.
+  int burnin_iteration = -1;
 };
 
 using CategoriesList = std::vector<CategoryMetadata>;
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
index c92a45a5..8857b00 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/app_list/search/common/string_util.h"
 #include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
 #include "chrome/browser/ui/app_list/search/ranking/ranker_delegate.h"
+#include "chrome/browser/ui/app_list/search/ranking/util.h"
 #include "chrome/browser/ui/app_list/search/search_features.h"
 #include "chrome/browser/ui/app_list/search/search_metrics_observer.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
@@ -231,6 +232,16 @@
   if (is_post_burnin)
     ++burnin_iteration_counter_;
 
+  // Record the burn-in iteration number for categories we are seeing for the
+  // first time in this search.
+  for (auto& category : categories_) {
+    if (category.category == ResultTypeToCategory(provider->ResultType()) &&
+        category.burnin_iteration == -1) {
+      category.burnin_iteration = burnin_iteration_counter_;
+    }
+  }
+
+  // Record-keeping for the burn-in iteration number of individual results.
   const auto it = results_.find(provider->ResultType());
   DCHECK(it != results_.end());
 
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new.h b/chrome/browser/ui/app_list/search/search_controller_impl_new.h
index 8afd37e..e29e296 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new.h
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new.h
@@ -153,14 +153,15 @@
   // Counter for burn-in iterations. Useful for query search only.
   //
   // Zero signifies pre-burn-in state. After burn-in period has elapsed, counter
-  // is incremented by one each time SetResults() is called. This information is
-  // useful because:
+  // is incremented by one each time SetResults() is called. This burn-in
+  // iteration number is used for individual results as well as overall
+  // categories.
   //
-  // (1) It allows post-burn-in results to be ranked by different rules to
-  // pre-burn-in results, for normal categories as well as special categories
-  // such as Best Match.
-  // (2) It allows for sorting stability across multiple post-burn-in result
-  // updates.
+  // This information is useful because it allows for:
+  //
+  // (1) Results and categories to be ranked by different rules depending on
+  // whether the information arrived pre- or post-burn-in.
+  // (2) Sorting stability across multiple post-burn-in updates.
   int burnin_iteration_counter_ = 0;
 
   // Store the ID of each result we encounter in a given query, along with the
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc b/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
index 2ee62ce..6763a14 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_new_unittest.cc
@@ -203,6 +203,27 @@
     EXPECT_THAT(actual_ids, ElementsAreArray(expected_ids));
   }
 
+  // Compares expected category burn-in iteration numbers to those recorded
+  // within the search controller. The expected list should not include
+  // categories for which burn-in number is unset (i.e. = -1).
+  void ExpectCategoriesToBurnInIterations(
+      std::vector<std::pair<Category, int>>
+          expected_categories_to_burnin_iteration) {
+    const auto& actual_categories_list = search_controller_->categories_;
+    std::vector<std::pair<Category, int>> actual_categories_to_burnin_iteration;
+
+    for (const auto& category : actual_categories_list) {
+      if (category.burnin_iteration != -1) {
+        actual_categories_to_burnin_iteration.push_back(
+            {category.category, category.burnin_iteration});
+      }
+    }
+
+    EXPECT_THAT(
+        actual_categories_to_burnin_iteration,
+        UnorderedElementsAreArray(expected_categories_to_burnin_iteration));
+  }
+
   void ExpectIdsToBurnInIterations(std::vector<std::pair<std::string, int>>
                                        expected_ids_to_burnin_iteration) {
     const auto& actual_ids_to_burnin_iteration =
@@ -278,10 +299,10 @@
 }
 
 TEST_F(SearchControllerImplNewTest,
-       BurnInIterationNumbersTrackedInQuerySearch) {
-  // This test focuses on the book-keeping of burn-in iteration numbers, and
-  // ignores the effect that these numbers can have on final sorting of the
-  // results list.
+       BurnInIterationNumbersTrackedInQuerySearch_Results) {
+  // This test focuses on the book-keeping of burn-in iteration numbers for
+  // individual results, and ignores the effect that these numbers can have on
+  // final sorting of the categories or results lists.
 
   ranker_delegate_->SetCategoryRanks({{Category::kFiles, 0.1}});
 
@@ -324,6 +345,64 @@
 }
 
 TEST_F(SearchControllerImplNewTest,
+       BurnInIterationNumbersTrackedInQuerySearch_Categories) {
+  // This test focuses on the book-keeping of burn-in iteration numbers for
+  // categories, and ignores the effect that these numbers can have on final
+  // sorting of the categories or results lists.
+
+  ranker_delegate_->SetCategoryRanks({{Category::kFiles, 0.1}});
+
+  // Set up some results from four different providers. Only their categories
+  // are relevant, and individual result scores are not.
+  auto file_results = MakeResults({"a"}, {Category::kFiles}, {false}, {0.9});
+  auto app_results = MakeResults({"b"}, {Category::kApps}, {false}, {0.1});
+  // This provider will first return one set of results, then later return an
+  // updated set of results.
+  auto web_results_first_arrival = MakeResults(
+      {"c", "d"}, {Category::kWeb, Category::kWeb}, {false, false}, {0.2, 0.1});
+  auto web_results_second_arrival = MakeResults(
+      {"c", "d", "e"}, {Category::kWeb, Category::kWeb, Category::kWeb},
+      {false, false, false}, {0.2, 0.1, 0.4});
+  auto settings_results =
+      MakeResults({"f"}, {Category::kSettings}, {false}, {0.8});
+
+  // Simulate starting a search.
+  search_controller_->StartSearch(u"abc");
+
+  // Simulate providers returning results within the burn-in period.
+  search_controller_->SetResults(SimpleProvider(Result::kFileSearch),
+                                 std::move(file_results));
+  ExpectCategoriesToBurnInIterations({{Category::kFiles, 0}});
+
+  search_controller_->SetResults(SimpleProvider(Result::kInstalledApp),
+                                 std::move(app_results));
+  ExpectCategoriesToBurnInIterations(
+      {{Category::kFiles, 0}, {Category::kApps, 0}});
+
+  // Simulate a third provider returning results after the burn-in period.
+  ElapseBurnInPeriod();
+  search_controller_->SetResults(SimpleProvider(Result::kOmnibox),
+                                 std::move(web_results_first_arrival));
+  ExpectCategoriesToBurnInIterations(
+      {{Category::kFiles, 0}, {Category::kApps, 0}, {Category::kWeb, 1}});
+
+  // Simulate the third provider returning for a second time. The burn-in
+  // iteration number for that category is not updated.
+  search_controller_->SetResults(SimpleProvider(Result::kOmnibox),
+                                 std::move(web_results_second_arrival));
+  ExpectCategoriesToBurnInIterations(
+      {{Category::kFiles, 0}, {Category::kApps, 0}, {Category::kWeb, 1}});
+
+  // Simulate a fourth provider returning for the first time.
+  search_controller_->SetResults(SimpleProvider(Result::kOsSettings),
+                                 std::move(settings_results));
+  ExpectCategoriesToBurnInIterations({{Category::kFiles, 0},
+                                      {Category::kApps, 0},
+                                      {Category::kWeb, 1},
+                                      {Category::kSettings, 3}});
+}
+
+TEST_F(SearchControllerImplNewTest,
        SetResultsPreAndPostBurnIn_OneProviderReturnPerCategory) {
   // When there is only a single provider return per final category, we do not
   // expect there to be any effect from sorting by burn-in iteration number.
diff --git a/chrome/browser/ui/app_list/search/search_metrics_observer.cc b/chrome/browser/ui/app_list/search/search_metrics_observer.cc
index c1050e1..be2376d 100644
--- a/chrome/browser/ui/app_list/search/search_metrics_observer.cc
+++ b/chrome/browser/ui/app_list/search/search_metrics_observer.cc
@@ -151,7 +151,7 @@
     }
   }
   const std::string histogram_name = base::StrCat(
-      {kHistogramPrefix, GetViewString(location, query), ".Index"});
+      {kHistogramPrefix, GetViewString(location, query), ".LaunchIndex"});
   base::UmaHistogramExactLinear(histogram_name, launched_index, 50);
 }
 
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc
index 5ae16c7b..acda2f7 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker.cc
@@ -279,9 +279,13 @@
     Mixer::SortData* result,
     RankingItemType type,
     base::flat_map<RankingItemType, int>* type_counts) const {
-  DCHECK(type == RankingItemType::kOmniboxGeneric ||
-         type == RankingItemType::kZeroStateFile ||
-         type == RankingItemType::kDriveQuickAccess);
+  if (type != RankingItemType::kOmniboxGeneric &&
+      type != RankingItemType::kZeroStateFile &&
+      type != RankingItemType::kDriveQuickAccess) {
+    // Sometimes search results are scored as zero-state results due to timing
+    // issues. Early-exit if that is the case. See crbug.com/1282329.
+    return;
+  }
 
   const float item_score =
       1.0f -
diff --git a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
index 0d24342..8d164af 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client_browsertest.cc
@@ -252,7 +252,7 @@
   const GURL app_url = https_server().GetURL(GetAppUrlHost(), GetAppUrlPath());
 
   // InstallTestWebApp() but with a ShareTarget definition added.
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope =
       https_server().GetURL(GetAppUrlHost(), GetAppScopePath());
diff --git a/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
index bbd335a..d327344 100644
--- a/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
+++ b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
@@ -279,7 +279,7 @@
   }
 
   Browser* InstallAndLaunchPWA(const GURL& start_url, bool launch_in_browser) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     if (!launch_in_browser)
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
index 632f47e..6d3e437d 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
@@ -523,7 +523,7 @@
   // |SetUpWebApp()| must be called after |SetUpOnMainThread()| to make sure
   // the Network Service process has been setup properly.
   std::string CreateWebApp() const {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetAppURL();
     web_app_info->scope = GetAppURL().GetWithoutFilename();
 
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
index 6e5eb072..1f5e6bae 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu_browsertest.cc
@@ -80,7 +80,7 @@
   Profile* profile = browser()->profile();
   base::UserActionTester user_action_tester;
 
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   web_application_info->start_url = GURL("https://example.org");
   web_application_info->display_mode = blink::mojom::DisplayMode::kMinimalUi;
   web_app::AppId app_id =
@@ -113,7 +113,7 @@
   Profile* profile = browser()->profile();
   base::UserActionTester user_action_tester;
 
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   web_application_info->start_url = GURL("https://example.org");
   web_application_info->display_mode = blink::mojom::DisplayMode::kMinimalUi;
   web_app::AppId app_id =
@@ -145,7 +145,7 @@
   Profile* profile = browser()->profile();
   base::UserActionTester user_action_tester;
 
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   web_application_info->start_url = GURL("https://example.org");
   web_app::AppId app_id =
       web_app::test::InstallWebApp(profile, std::move(web_application_info));
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
index 947b9e6..4d3e03e7 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
@@ -466,7 +466,7 @@
   }
 
   web_app::AppId InstallWebApp(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     return web_app::test::InstallWebApp(browser()->profile(),
@@ -2617,7 +2617,7 @@
 IN_PROC_BROWSER_TEST_F(ShelfWebAppBrowserTest, WebAppPolicyUpdate) {
   // Install web app.
   GURL app_url = GURL("https://example.org/");
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url;
   web_app_info->title = u"Example";
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
index 8f01eafb..b9dd7073 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -1069,7 +1069,7 @@
   }
 
   void AddWebApp(const char* web_app_id) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     if (web_app_id == web_app::kGmailAppId) {
       web_app_info->start_url =
           GURL("https://mail.google.com/mail/?usp=installed_webapp");
@@ -3073,7 +3073,7 @@
   // *   the primary user has a test app pinned to shelf, and
   // *   secondary user has a tab with the URL associated with the app open (but
   //      does not have the app installed).
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GURL(kWebAppUrl);
   web_app::AppId installed_app_id =
       web_app::test::InstallWebApp(profile(), std::move(web_app_info));
@@ -4875,7 +4875,7 @@
   }
 
   web_app::AppId InstallExternalWebApp(std::string start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL(start_url);
     web_app::AppId web_app_id =
         web_app::test::InstallWebApp(profile(), std::move(web_app_info));
diff --git a/chrome/browser/ui/blocked_content/framebust_block_tab_helper.cc b/chrome/browser/ui/blocked_content/framebust_block_tab_helper.cc
index 4e3e312..731c02ba 100644
--- a/chrome/browser/ui/blocked_content/framebust_block_tab_helper.cc
+++ b/chrome/browser/ui/blocked_content/framebust_block_tab_helper.cc
@@ -6,7 +6,6 @@
 
 #include "base/check_op.h"
 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
-#include "content/public/browser/navigation_handle.h"
 
 FramebustBlockTabHelper::~FramebustBlockTabHelper() = default;
 
@@ -40,16 +39,7 @@
     : content::WebContentsObserver(web_contents),
       content::WebContentsUserData<FramebustBlockTabHelper>(*web_contents) {}
 
-void FramebustBlockTabHelper::DidFinishNavigation(
-    content::NavigationHandle* navigation_handle) {
-  // TODO(https://crbug.com/1218946): With MPArch there may be multiple main
-  // frames. This caller was converted automatically to the primary main frame
-  // to preserve its semantics. Follow up to confirm correctness.
-  if (!navigation_handle->IsInPrimaryMainFrame() ||
-      !navigation_handle->HasCommitted() ||
-      navigation_handle->IsSameDocument()) {
-    return;
-  }
+void FramebustBlockTabHelper::PrimaryPageChanged(content::Page& page) {
   blocked_urls_.clear();
   callbacks_.clear();
 
diff --git a/chrome/browser/ui/blocked_content/framebust_block_tab_helper.h b/chrome/browser/ui/blocked_content/framebust_block_tab_helper.h
index aad00b6..11fce59 100644
--- a/chrome/browser/ui/blocked_content/framebust_block_tab_helper.h
+++ b/chrome/browser/ui/blocked_content/framebust_block_tab_helper.h
@@ -13,10 +13,6 @@
 #include "content/public/browser/web_contents_user_data.h"
 #include "url/gurl.h"
 
-namespace content {
-class NavigationHandle;
-}
-
 // A tab helper that keeps track of blocked Framebusts that happened on each
 // page. Only used for the desktop version of the blocked Framebust UI.
 class FramebustBlockTabHelper
@@ -55,8 +51,7 @@
   explicit FramebustBlockTabHelper(content::WebContents* web_contents);
 
   // content::WebContentsObserver:
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override;
+  void PrimaryPageChanged(content::Page& page) override;
 
   blocked_content::UrlListManager manager_;
 
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h
index 02023579..22035d08 100644
--- a/chrome/browser/ui/browser_dialogs.h
+++ b/chrome/browser/ui/browser_dialogs.h
@@ -35,7 +35,7 @@
 class GURL;
 class LoginHandler;
 class Profile;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 class SettingsOverriddenDialogController;
@@ -148,18 +148,18 @@
 
 // Callback used to indicate whether a user has accepted the installation of a
 // web app. The boolean parameter is true when the user accepts the dialog. The
-// WebApplicationInfo parameter contains the information about the app,
+// WebAppInstallInfo parameter contains the information about the app,
 // possibly modified by the user.
 using AppInstallationAcceptanceCallback =
-    base::OnceCallback<void(bool, std::unique_ptr<WebApplicationInfo>)>;
+    base::OnceCallback<void(bool, std::unique_ptr<WebAppInstallInfo>)>;
 
 // Shows the Web App install bubble.
 //
-// |web_app_info| is the WebApplicationInfo being converted into an app.
+// |web_app_info| is the WebAppInstallInfo being converted into an app.
 // |web_app_info.app_url| should contain a start url from a web app manifest
 // (for a Desktop PWA), or the current url (when creating a shortcut app).
 void ShowWebAppInstallDialog(content::WebContents* web_contents,
-                             std::unique_ptr<WebApplicationInfo> web_app_info,
+                             std::unique_ptr<WebAppInstallInfo> web_app_info,
                              AppInstallationAcceptanceCallback callback);
 
 // When an app changes its icon or name, that is considered an app identity
@@ -245,13 +245,13 @@
 // Shows the PWA installation confirmation bubble anchored off the PWA install
 // icon in the omnibox.
 //
-// |web_app_info| is the WebApplicationInfo to be installed.
+// |web_app_info| is the WebAppInstallInfo to be installed.
 // |callback| is called when install bubble closed.
 // |iph_state| records whether PWA install iph is shown before Install bubble is
 // shown.
 void ShowPWAInstallBubble(
     content::WebContents* web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     AppInstallationAcceptanceCallback callback,
     PwaInProductHelpState iph_state = PwaInProductHelpState::kNotShown);
 
diff --git a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
index c35099e..bc20e3b 100644
--- a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
+++ b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
@@ -33,6 +33,8 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/fenced_frame_test_util.h"
+#include "content/public/test/prerender_test_util.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -110,6 +112,33 @@
     return result;
   }
 
+  bool ExecuteAndCheckBlockedRedirection() {
+    EXPECT_TRUE(ui_test_utils::NavigateToURL(
+        browser(), embedded_test_server()->GetURL("/iframe.html")));
+
+    const GURL child_url =
+        embedded_test_server()->GetURL("a.com", "/title1.html");
+    NavigateIframeToUrlWithoutGesture(GetWebContents(), "test", child_url);
+
+    content::RenderFrameHost* child =
+        content::ChildFrameAt(GetWebContents()->GetMainFrame(), 0);
+    EXPECT_EQ(child_url, child->GetLastCommittedURL());
+
+    const GURL redirect_url =
+        embedded_test_server()->GetURL("b.com", "/title1.html");
+
+    base::RunLoop block_waiter;
+    blocked_url_added_closure_ = block_waiter.QuitClosure();
+    child->ExecuteJavaScriptForTests(
+        base::ASCIIToUTF16(base::StringPrintf("window.top.location = '%s';",
+                                              redirect_url.spec().c_str())),
+        base::NullCallback());
+    block_waiter.Run();
+
+    return base::Contains(GetFramebustTabHelper()->blocked_urls(),
+                          redirect_url);
+  }
+
  protected:
   absl::optional<GURL> clicked_url_;
   absl::optional<size_t> clicked_index_;
@@ -255,27 +284,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(FramebustBlockBrowserTest, SimpleFramebust_Blocked) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL("/iframe.html")));
-
-  GURL child_url = embedded_test_server()->GetURL("a.com", "/title1.html");
-  NavigateIframeToUrlWithoutGesture(GetWebContents(), "test", child_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(GetWebContents()->GetMainFrame(), 0);
-  EXPECT_EQ(child_url, child->GetLastCommittedURL());
-
-  GURL redirect_url = embedded_test_server()->GetURL("b.com", "/title1.html");
-
-  base::RunLoop block_waiter;
-  blocked_url_added_closure_ = block_waiter.QuitClosure();
-  child->ExecuteJavaScriptForTests(
-      base::ASCIIToUTF16(base::StringPrintf("window.top.location = '%s';",
-                                            redirect_url.spec().c_str())),
-      base::NullCallback());
-  block_waiter.Run();
-  EXPECT_TRUE(
-      base::Contains(GetFramebustTabHelper()->blocked_urls(), redirect_url));
+  EXPECT_TRUE(ExecuteAndCheckBlockedRedirection());
 }
 
 IN_PROC_BROWSER_TEST_F(FramebustBlockBrowserTest,
@@ -345,27 +354,7 @@
 // persist on subsequent navigations.
 IN_PROC_BROWSER_TEST_F(FramebustBlockBrowserTest,
                        FramebustBlocked_SubsequentNavigation_NoUI) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL("/iframe.html")));
-
-  GURL child_url = embedded_test_server()->GetURL("a.com", "/title1.html");
-  NavigateIframeToUrlWithoutGesture(GetWebContents(), "test", child_url);
-
-  content::RenderFrameHost* child =
-      content::ChildFrameAt(GetWebContents()->GetMainFrame(), 0);
-  EXPECT_EQ(child_url, child->GetLastCommittedURL());
-
-  GURL redirect_url = embedded_test_server()->GetURL("b.com", "/title1.html");
-
-  base::RunLoop block_waiter;
-  blocked_url_added_closure_ = block_waiter.QuitClosure();
-  child->ExecuteJavaScriptForTests(
-      base::ASCIIToUTF16(base::StringPrintf("window.top.location = '%s';",
-                                            redirect_url.spec().c_str())),
-      base::NullCallback());
-  block_waiter.Run();
-  EXPECT_TRUE(
-      base::Contains(GetFramebustTabHelper()->blocked_urls(), redirect_url));
+  EXPECT_TRUE(ExecuteAndCheckBlockedRedirection());
 
   // Now, navigate away and check that the UI went away.
   ASSERT_TRUE(ui_test_utils::NavigateToURL(
@@ -375,3 +364,65 @@
   // look at the internal state of the framebust tab helper.
   EXPECT_FALSE(GetFramebustTabHelper()->HasBlockedUrls());
 }
+
+class FramebustBlockPrerenderTest : public FramebustBlockBrowserTest {
+ public:
+  FramebustBlockPrerenderTest()
+      : prerender_helper_(
+            base::BindRepeating(&FramebustBlockPrerenderTest::GetWebContents,
+                                base::Unretained(this))) {}
+  ~FramebustBlockPrerenderTest() override = default;
+
+  void SetUpOnMainThread() override {
+    prerender_helper_.SetUp(embedded_test_server());
+    FramebustBlockBrowserTest::SetUpOnMainThread();
+  }
+
+ protected:
+  content::test::PrerenderTestHelper prerender_helper_;
+};
+
+IN_PROC_BROWSER_TEST_F(FramebustBlockPrerenderTest,
+                       FramebustBlocked_PrerenderNavigation) {
+  EXPECT_TRUE(ExecuteAndCheckBlockedRedirection());
+
+  // Start a prerender and ensure that the framebust UI persists on the
+  // prerender navigation.
+  const GURL prerender_url =
+      embedded_test_server()->GetURL("/title1.html?prerender");
+  prerender_helper_.AddPrerender(prerender_url);
+  EXPECT_TRUE(GetFramebustTabHelper()->HasBlockedUrls());
+
+  // Activate a prerendered page.
+  prerender_helper_.NavigatePrimaryPage(prerender_url);
+  EXPECT_FALSE(GetFramebustTabHelper()->HasBlockedUrls());
+}
+
+class FramebustBlockFencedFrameTest : public FramebustBlockBrowserTest {
+ public:
+  FramebustBlockFencedFrameTest() = default;
+  ~FramebustBlockFencedFrameTest() override = default;
+
+  content::RenderFrameHost* primary_main_frame_host() {
+    return GetWebContents()->GetMainFrame();
+  }
+
+ protected:
+  content::test::FencedFrameTestHelper fenced_frame_helper_;
+};
+
+IN_PROC_BROWSER_TEST_F(FramebustBlockFencedFrameTest,
+                       FramebustBlocked_FencedFrameNavigation) {
+  EXPECT_TRUE(ExecuteAndCheckBlockedRedirection());
+
+  // Create a fenced frame in the primary main page and ensure that the
+  // framebust UI persists on fenced frame navigation.
+  const GURL fenced_frame_url =
+      embedded_test_server()->GetURL("/fenced_frames/title1.html");
+  content::RenderFrameHost* fenced_frame_rfh =
+      fenced_frame_helper_.CreateFencedFrame(primary_main_frame_host(),
+                                             fenced_frame_url);
+  ASSERT_NE(nullptr, fenced_frame_rfh);
+
+  EXPECT_TRUE(GetFramebustTabHelper()->HasBlockedUrls());
+}
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index fc9e02a..6deda814d 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -211,7 +211,7 @@
           base::StringPrintf(kAppDotComManifest, start_url.spec().c_str()));
       SetupApp(test_app_dir.UnpackedPath());
     } else {
-      auto web_app_info = std::make_unique<WebApplicationInfo>();
+      auto web_app_info = std::make_unique<WebAppInstallInfo>();
       web_app_info->start_url = start_url;
       web_app_info->scope = start_url.GetWithoutFilename();
       web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/hats/trust_safety_sentiment_service.cc b/chrome/browser/ui/hats/trust_safety_sentiment_service.cc
index 8c98fec..48988cb1 100644
--- a/chrome/browser/ui/hats/trust_safety_sentiment_service.cc
+++ b/chrome/browser/ui/hats/trust_safety_sentiment_service.cc
@@ -134,7 +134,7 @@
         content_settings::WebsiteSettingsRegistry::GetInstance()
             ->Get(content_setting_type)
             ->initial_default_value()
-            ->GetInt());
+            .GetInt());
 
     if (current_value != default_value && user_controlled) {
       has_non_default_content_setting = true;
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 16c28d9..4f16686 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1623,7 +1623,7 @@
 web_app::AppId InstallPWAWithName(Profile* profile,
                                   const GURL& start_url,
                                   const std::string& app_name) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
   web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -1856,7 +1856,7 @@
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)
 web_app::AppId InstallPWA(Profile* profile, const GURL& start_url) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
   web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -2097,7 +2097,7 @@
   // Install web app set to open as a tab.
   {
     base::RunLoop run_loop;
-    WebApplicationInfo info;
+    WebAppInstallInfo info;
     info.start_url = GURL(kStartUrl);
     info.title = kAppName;
     info.user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -2725,8 +2725,8 @@
   web_app::AppId InstallWebAppWithProtocolHandlers(
       const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers,
       const std::vector<apps::FileHandler>& file_handlers = {}) {
-    std::unique_ptr<WebApplicationInfo> info =
-        std::make_unique<WebApplicationInfo>();
+    std::unique_ptr<WebAppInstallInfo> info =
+        std::make_unique<WebAppInstallInfo>();
     info->start_url = GURL(kStartUrl);
     info->title = kAppName;
     info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc
index 6ad2448..c5c4752 100644
--- a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view_browsertest.cc
@@ -169,7 +169,7 @@
   }
 
   void CreateApp() {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetAppURL();
     web_app_info->scope = GetAppURL().GetWithoutFilename();
 
diff --git a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
index cf12f80..1132e5a 100644
--- a/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_uninstall_dialog_view_browsertest.cc
@@ -194,7 +194,7 @@
       ->AddExtension(extension.get());
 
   const GURL start_url = GURL("https://test.com/");
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url;
   web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/frame/browser_frame_browsertest.cc b/chrome/browser/ui/views/frame/browser_frame_browsertest.cc
index 99a47c41a..cd75755 100644
--- a/chrome/browser/ui/views/frame/browser_frame_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_browsertest.cc
@@ -48,7 +48,7 @@
 
 // Verifies that the web app is loaded with initial bounds.
 IN_PROC_BROWSER_TEST_F(BrowserFrameTest, WebAppsHasBoundsOnOpen) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GURL("http://example.org/");
   web_app::AppId app_id = web_app::test::InstallWebApp(browser()->profile(),
                                                        std::move(web_app_info));
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
index adc5edc..a6465142 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -68,7 +68,7 @@
       manifest.theme_color = *app_theme_color_;
     }
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     GURL manifest_url = embedded_test_server()->GetURL("/manifest");
     web_app::UpdateWebAppInfoFromManifest(manifest, manifest_url,
                                           web_app_info.get());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
index a1dbba6..225351d5 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos_browsertest.cc
@@ -192,7 +192,7 @@
       CHECK(test_server_->Start());
     }
     const GURL app_url = test_server_->GetURL("app.com", "/ssl/google.html");
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url.GetWithoutFilename();
     web_app_info->theme_color = SK_ColorBLUE;
@@ -596,7 +596,7 @@
   // |SetUpWebApp()| must be called after |SetUpOnMainThread()| to make sure
   // the Network Service process has been setup properly.
   void SetUpWebApp() {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetAppURL();
     web_app_info->scope = GetAppURL().GetWithoutFilename();
     web_app_info->display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
index 060c697..5c6dba32 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view_browsertest_win.cc
@@ -57,7 +57,7 @@
   // TODO(https://crbug.com/863278): Force Aero glass on Windows 7 for this
   // test.
   bool InstallAndLaunchWebApp() {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetStartURL();
     web_app_info->scope = GetStartURL().GetWithoutFilename();
     if (theme_color_)
@@ -196,7 +196,7 @@
 
     std::vector<blink::mojom::DisplayMode> display_overrides = {
         blink::mojom::DisplayMode::kWindowControlsOverlay};
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc
index 9be8bfac..2e899f0 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos_browsertest.cc
@@ -56,7 +56,7 @@
     ASSERT_TRUE(https_server_.Start());
 
     const GURL app_url = GetAppUrl();
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url.GetWithoutFilename();
     web_app_info->theme_color = SK_ColorBLUE;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
index 5cfaff6..c132b0e 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
@@ -54,7 +54,7 @@
 
   bool InstallAndLaunchWebApp(
       absl::optional<SkColor> theme_color = absl::nullopt) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetAppURL();
     web_app_info->scope = GetAppURL().GetWithoutFilename();
     web_app_info->theme_color = theme_color;
@@ -309,7 +309,7 @@
                          .LoadWindowControlsOverlayTestPageWithDataAndGetURL(
                              embedded_test_server(), &temp_dir_);
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
index 3e41c417..b033050 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
@@ -182,7 +182,7 @@
   }
 
   std::string InstallWebApp(const std::string& app_name, const GURL& url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->title = base::UTF8ToUTF16(app_name);
     web_app_info->start_url = url;
     web_app_info->scope = url;
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
index f77abb4b..d343775 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -208,7 +208,7 @@
   }
 
   void InstallPWA(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -216,7 +216,7 @@
   }
 
   void InstallBookmark(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.DeprecatedGetOriginAsURL();
     web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -230,7 +230,7 @@
   raw_ptr<web_app::AppBrowserController> app_controller_ = nullptr;
 
  private:
-  void Install(std::unique_ptr<WebApplicationInfo> web_app_info) {
+  void Install(std::unique_ptr<WebAppInstallInfo> web_app_info) {
     const GURL start_url = web_app_info->start_url;
     web_app::AppId app_id = InstallWebApp(std::move(web_app_info));
 
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
index 25856b5c..7670c031e 100644
--- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
@@ -69,7 +69,7 @@
 
   void InstallTestWebApp() {
     const GURL example_url = GURL(kStartUrl);
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->title = u"Test app";
     web_app_info->start_url = example_url;
     web_app_info->scope = example_url;
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
index ef08ab9..c560e04 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc
@@ -448,7 +448,7 @@
     std::vector<blink::mojom::DisplayMode> display_overrides;
     display_overrides.emplace_back(
         web_app::DisplayMode::kWindowControlsOverlay);
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->title = u"A window-controls-overlay app";
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
index f510ec97..23d4602 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.cc
@@ -34,7 +34,7 @@
 web_app::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchWebApp(
     Browser* browser,
     const GURL& start_url) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
   web_app_info->title = u"A minimal-ui app";
@@ -61,7 +61,7 @@
 
 web_app::AppId WebAppFrameToolbarTestHelper::InstallAndLaunchCustomWebApp(
     Browser* browser,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     const GURL& start_url) {
   web_app::AppId app_id =
       web_app::test::InstallWebApp(browser->profile(), std::move(web_app_info));
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
index 0d1333e..d276889 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_helper.h
@@ -11,7 +11,7 @@
 #include "chrome/browser/web_applications/web_app_id.h"
 #include "content/public/browser/web_contents.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 class Browser;
 class BrowserNonClientFrameView;
 class BrowserView;
@@ -42,7 +42,7 @@
                                         const GURL& start_url);
   web_app::AppId InstallAndLaunchCustomWebApp(
       Browser* browser,
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       const GURL& start_url);
 
   GURL LoadWindowControlsOverlayTestPageWithDataAndGetURL(
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
index e29879c5..8dd7d2d2 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_test_mixin.cc
@@ -25,7 +25,7 @@
 void WebAppFrameToolbarTestMixin::InstallAndLaunchWebApp(
     Browser* browser,
     const GURL& start_url) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
   web_app_info->title = u"A minimal-ui app";
diff --git a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
index 3247d08..a644292 100644
--- a/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
+++ b/chrome/browser/ui/views/web_apps/frame_toolbar/web_app_minimal_ui_test.cc
@@ -20,7 +20,7 @@
   WebAppMinimalUITest& operator=(const WebAppMinimalUITest&) = delete;
 
   BrowserView* CreateBrowserView(blink::mojom::DisplayMode display_mode) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL("https://example.org");
     web_app_info->display_mode = display_mode;
     web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
index e3745078..1fd45db 100644
--- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
+++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.cc
@@ -48,7 +48,7 @@
 
 // Returns an ImageView containing the app icon.
 std::unique_ptr<views::ImageView> CreateIconView(
-    const WebApplicationInfo& web_app_info) {
+    const WebAppInstallInfo& web_app_info) {
   constexpr int kIconSize = 48;
   gfx::ImageSkia image(std::make_unique<WebAppInfoImageSource>(
                            kIconSize, web_app_info.icon_bitmaps.any),
@@ -101,7 +101,7 @@
 PWAConfirmationBubbleView::PWAConfirmationBubbleView(
     views::View* anchor_view,
     views::Button* highlight_button,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     chrome::AppInstallationAcceptanceCallback callback,
     chrome::PwaInProductHelpState iph_state,
     PrefService* prefs,
@@ -223,7 +223,7 @@
 namespace chrome {
 
 void ShowPWAInstallBubble(content::WebContents* web_contents,
-                          std::unique_ptr<WebApplicationInfo> web_app_info,
+                          std::unique_ptr<WebAppInstallInfo> web_app_info,
                           AppInstallationAcceptanceCallback callback,
                           PwaInProductHelpState iph_state) {
   if (g_bubble_)
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h
index b318c4a..8d9b32a 100644
--- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h
+++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view.h
@@ -31,7 +31,7 @@
 
   PWAConfirmationBubbleView(views::View* anchor_view,
                             views::Button* highlight_button,
-                            std::unique_ptr<WebApplicationInfo> web_app_info,
+                            std::unique_ptr<WebAppInstallInfo> web_app_info,
                             chrome::AppInstallationAcceptanceCallback callback,
                             chrome::PwaInProductHelpState iph_state,
                             PrefService* prefs,
@@ -50,7 +50,7 @@
   bool Accept() override;
 
  private:
-  std::unique_ptr<WebApplicationInfo> web_app_info_;
+  std::unique_ptr<WebAppInstallInfo> web_app_info_;
   chrome::AppInstallationAcceptanceCallback callback_;
 
   // Checkbox to launch window with tab strip.
diff --git a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
index 3103f0b..0dd107a 100644
--- a/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/pwa_confirmation_bubble_view_browsertest.cc
@@ -32,8 +32,8 @@
   }
   ~PWAConfirmationBubbleViewBrowserTest() override = default;
 
-  std::unique_ptr<WebApplicationInfo> GetAppInfo() {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+  std::unique_ptr<WebAppInstallInfo> GetAppInfo() {
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->title = u"Test app 2";
     app_info->start_url = GURL("https://example2.com");
     app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -46,7 +46,7 @@
 
 IN_PROC_BROWSER_TEST_F(PWAConfirmationBubbleViewBrowserTest,
                        ShowBubbleInPWAWindow) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->title = u"Test app";
   app_info->start_url = GURL("https://example.com");
   Profile* profile = browser()->profile();
@@ -62,7 +62,7 @@
 
   // Tests that we don't crash when attempting to show bubble when it's already
   // shown.
-  app_info = std::make_unique<WebApplicationInfo>();
+  app_info = std::make_unique<WebAppInstallInfo>();
   app_info->title = u"Test app 3";
   app_info->start_url = GURL("https://example3.com");
   app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
@@ -80,7 +80,7 @@
       browser()->tab_strip_model()->GetActiveWebContents(), std::move(app_info),
       base::BindLambdaForTesting(
           [&](bool accepted,
-              std::unique_ptr<WebApplicationInfo> app_info_callback) {
+              std::unique_ptr<WebAppInstallInfo> app_info_callback) {
             loop.Quit();
           }));
 
@@ -106,7 +106,7 @@
       browser()->tab_strip_model()->GetActiveWebContents(), std::move(app_info),
       base::BindLambdaForTesting(
           [&](bool accepted,
-              std::unique_ptr<WebApplicationInfo> app_info_callback) {
+              std::unique_ptr<WebAppInstallInfo> app_info_callback) {
             loop.Quit();
           }),
       chrome::PwaInProductHelpState::kShown);
@@ -164,7 +164,7 @@
       browser()->tab_strip_model()->GetActiveWebContents(), std::move(app_info),
       base::BindLambdaForTesting(
           [&](bool accepted,
-              std::unique_ptr<WebApplicationInfo> app_info_callback) {
+              std::unique_ptr<WebAppInstallInfo> app_info_callback) {
             loop.Quit();
           }),
       chrome::PwaInProductHelpState::kShown);
diff --git a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
index 45770c3..dd66d3a 100644
--- a/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_ash_interactive_ui_test.cc
@@ -29,7 +29,7 @@
 
   // InProcessBrowserTest override:
   void SetUpOnMainThread() override {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL("https://test.org");
     web_app::AppId app_id = InstallWebApp(std::move(web_app_info));
 
diff --git a/chrome/browser/ui/views/web_apps/web_app_confirmation_view.cc b/chrome/browser/ui/views/web_apps/web_app_confirmation_view.cc
index 046766a..5acc8dd 100644
--- a/chrome/browser/ui/views/web_apps/web_app_confirmation_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_confirmation_view.cc
@@ -76,7 +76,7 @@
 WebAppConfirmationView::~WebAppConfirmationView() {}
 
 WebAppConfirmationView::WebAppConfirmationView(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     chrome::AppInstallationAcceptanceCallback callback)
     : web_app_info_(std::move(web_app_info)), callback_(std::move(callback)) {
   DCHECK(web_app_info_);
@@ -241,7 +241,7 @@
 namespace chrome {
 
 void ShowWebAppInstallDialog(content::WebContents* web_contents,
-                             std::unique_ptr<WebApplicationInfo> web_app_info,
+                             std::unique_ptr<WebAppInstallInfo> web_app_info,
                              AppInstallationAcceptanceCallback callback) {
   auto* dialog =
       new WebAppConfirmationView(std::move(web_app_info), std::move(callback));
diff --git a/chrome/browser/ui/views/web_apps/web_app_confirmation_view.h b/chrome/browser/ui/views/web_apps/web_app_confirmation_view.h
index 3fb2675..443b13f 100644
--- a/chrome/browser/ui/views/web_apps/web_app_confirmation_view.h
+++ b/chrome/browser/ui/views/web_apps/web_app_confirmation_view.h
@@ -26,7 +26,7 @@
                                public views::TextfieldController {
  public:
   METADATA_HEADER(WebAppConfirmationView);
-  WebAppConfirmationView(std::unique_ptr<WebApplicationInfo> web_app_info,
+  WebAppConfirmationView(std::unique_ptr<WebAppInstallInfo> web_app_info,
                          chrome::AppInstallationAcceptanceCallback callback);
   WebAppConfirmationView(const WebAppConfirmationView&) = delete;
   WebAppConfirmationView& operator=(const WebAppConfirmationView&) = delete;
@@ -49,9 +49,9 @@
   // Get the trimmed contents of the title text field.
   std::u16string GetTrimmedTitle() const;
 
-  // The WebApplicationInfo that the user is editing.
+  // The WebAppInstallInfo that the user is editing.
   // Cleared when the dialog completes (Accept/WindowClosing).
-  std::unique_ptr<WebApplicationInfo> web_app_info_;
+  std::unique_ptr<WebAppInstallInfo> web_app_info_;
 
   // The callback to be invoked when the dialog is completed.
   chrome::AppInstallationAcceptanceCallback callback_;
diff --git a/chrome/browser/ui/views/web_apps/web_app_confirmation_view_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_confirmation_view_browsertest.cc
index b748458..281e317 100644
--- a/chrome/browser/ui/views/web_apps/web_app_confirmation_view_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_confirmation_view_browsertest.cc
@@ -25,11 +25,11 @@
 
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->title = u"Test app";
     app_info->start_url = GURL("https://example.com");
 
-    auto callback = [](bool result, std::unique_ptr<WebApplicationInfo>) {};
+    auto callback = [](bool result, std::unique_ptr<WebAppInstallInfo>) {};
 
     chrome::ShowWebAppInstallDialog(
         browser()->tab_strip_model()->GetActiveWebContents(),
@@ -54,7 +54,7 @@
 };
 
 IN_PROC_BROWSER_TEST_P(WebAppConfirmViewBrowserTest, ShowWebAppInstallDialog) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->title = u"Test app";
   app_info->start_url = GURL("https://example.com");
 
@@ -62,7 +62,7 @@
                                               /*auto_open_in_window=*/true);
   bool is_accepted = false;
   auto callback = [&is_accepted](bool result,
-                                 std::unique_ptr<WebApplicationInfo>) {
+                                 std::unique_ptr<WebAppInstallInfo>) {
     is_accepted = result;
   };
 
@@ -90,14 +90,14 @@
   };
 
   for (const TestCases& test_case : test_cases) {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->title = test_case.input;
     app_info->start_url = GURL("https://example.com");
 
     bool is_accepted = false;
     std::u16string title;
     auto callback = [&is_accepted, &title](
-                        bool result, std::unique_ptr<WebApplicationInfo> info) {
+                        bool result, std::unique_ptr<WebAppInstallInfo> info) {
       is_accepted = result;
       title = info->title;
     };
diff --git a/chrome/browser/ui/views/web_apps/web_app_info_image_source.h b/chrome/browser/ui/views/web_apps/web_app_info_image_source.h
index 736f8a3..195a926 100644
--- a/chrome/browser/ui/views/web_apps/web_app_info_image_source.h
+++ b/chrome/browser/ui/views/web_apps/web_app_info_image_source.h
@@ -11,7 +11,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image_skia_source.h"
 
-// An image source which draws from a WebApplicationInfo icons list.
+// An image source which draws from a WebAppInstallInfo icons list.
 class WebAppInfoImageSource : public gfx::ImageSkiaSource {
  public:
   WebAppInfoImageSource(int dip_size,
diff --git a/chrome/browser/ui/views/web_apps/web_app_protocol_handler_intent_picker_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_protocol_handler_intent_picker_dialog_browsertest.cc
index 036d78f..61625e4 100644
--- a/chrome/browser/ui/views/web_apps/web_app_protocol_handler_intent_picker_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_protocol_handler_intent_picker_dialog_browsertest.cc
@@ -28,7 +28,7 @@
 
 AppId InstallTestWebApp(Profile* profile) {
   const GURL example_url = GURL("http://example.org/");
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->title = u"Test app";
   app_info->start_url = example_url;
   app_info->scope = example_url;
diff --git a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
index 90afc8d..df7db80 100644
--- a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
@@ -66,7 +66,7 @@
     Profile* profile = browser()->profile();
     GURL start_url = embedded_test_server()->GetURL(kAppPath);
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->title = u"Test app";
@@ -151,7 +151,7 @@
         /*dialog_callback=*/
         base::BindLambdaForTesting(
             [](content::WebContents*,
-               std::unique_ptr<WebApplicationInfo> web_app_info,
+               std::unique_ptr<WebAppInstallInfo> web_app_info,
                ForInstallableSite,
                WebAppInstallationAcceptanceCallback acceptance_callback) {
               web_app_info->user_display_mode = DisplayMode::kTabbed;
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
index 019951c..a9a94a2a 100644
--- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_browsertest.cc
@@ -37,7 +37,7 @@
 AppId InstallTestWebApp(Profile* profile) {
   const GURL example_url = GURL("http://example.org/");
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = example_url;
   web_app_info->scope = example_url;
   web_app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/views/web_apps/web_app_url_handler_intent_picker_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_url_handler_intent_picker_dialog_browsertest.cc
index 99f05b23..de08bfc5 100644
--- a/chrome/browser/ui/views/web_apps/web_app_url_handler_intent_picker_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_url_handler_intent_picker_dialog_browsertest.cc
@@ -59,7 +59,7 @@
 }
 
 web_app::AppId InstallTestWebApp(Profile* profile) {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kStartUrl);
   app_info->title = kAppName;
   app_info->user_display_mode = blink::mojom::DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.h b/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
index 3f302b6..c4b0966 100644
--- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
+++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.h
@@ -42,7 +42,7 @@
   ~SystemAppLaunchParams();
 
   // If provided launches System Apps into |url|, instead of its start_url (as
-  // specified its WebApplicationInfo). Mutually exclusive with non-empty
+  // specified its WebAppInstallInfo). Mutually exclusive with non-empty
   // |launch_paths|.
   absl::optional<GURL> url;
 
@@ -52,7 +52,7 @@
 
   // If non-empty, specifies files passed to Web File Handling. Apps need to
   // have "FileHandling" origin trial in its SystemAppInfo, and file handlers
-  // in its WebApplicationInfo. Mutually exclusive with |url|.
+  // in its WebAppInstallInfo. Mutually exclusive with |url|.
   std::vector<base::FilePath> launch_paths;
 };
 
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
index b8e20f7..546756df8 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -71,7 +71,7 @@
 
 void AutoAcceptDialogCallback(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback) {
   web_app_info->user_display_mode = DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
index f013d72..15fb17f 100644
--- a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
@@ -230,7 +230,7 @@
     CHECK(https_server_.Start());
   }
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = https_server_.GetURL(app_host, GetAppUrlPath());
   web_app_info->scope = https_server_.GetURL(app_host, app_scope);
   web_app_info->title = base::UTF8ToUTF16(GetAppName());
diff --git a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
index 7119055..30fe2f2 100644
--- a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
@@ -48,7 +48,7 @@
     main_app_id_ = InstallPWA(start_url);
 
     GURL sub_start_url = https_server()->GetURL("/web_app_badging/blank.html");
-    auto sub_app_info = std::make_unique<WebApplicationInfo>();
+    auto sub_app_info = std::make_unique<WebAppInstallInfo>();
     sub_app_info->start_url = sub_start_url;
     sub_app_info->scope = sub_start_url;
     sub_app_info->user_display_mode = DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 2d36656..877f940 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -185,7 +185,7 @@
     base::HistogramTester tester;
     const GURL app_url = https_server()->GetURL(
         base::StringPrintf("/web_apps/basic.html?index=%d", index++));
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url;
     web_app_info->display_mode = display_mode;
@@ -264,7 +264,7 @@
     manifest.scope = GURL(kExampleURL);
     manifest.has_theme_color = true;
     manifest.theme_color = theme_color;
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app::UpdateWebAppInfoFromManifest(manifest, GURL(kExampleManifestURL),
                                           web_app_info.get());
 
@@ -276,7 +276,7 @@
               app_browser->app_controller()->GetThemeColor());
   }
   {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL("http://example.org/2");
     web_app_info->scope = GURL("http://example.org/");
     web_app_info->theme_color = absl::optional<SkColor>();
@@ -294,7 +294,7 @@
   manifest.scope = GURL(kExampleURL);
   manifest.has_background_color = true;
   manifest.background_color = SkColorSetA(SK_ColorBLUE, 0xF0);
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app::UpdateWebAppInfoFromManifest(manifest, GURL(kExampleManifestURL),
                                         web_app_info.get());
   AppId app_id = InstallWebApp(std::move(web_app_info));
@@ -333,7 +333,7 @@
                                                   web_app::SystemAppType::HELP);
     } else {
       const GURL app_url = GetSecureAppURL();
-      auto web_app_info = std::make_unique<WebApplicationInfo>();
+      auto web_app_info = std::make_unique<WebAppInstallInfo>();
       web_app_info->start_url = app_url;
       web_app_info->scope = app_url.GetWithoutFilename();
       web_app_info->theme_color = SK_ColorBLUE;
@@ -418,7 +418,7 @@
   ThemeServiceFactory::GetForProfile(browser()->profile())
       ->BuildAutogeneratedThemeFromColor(SK_ColorBLUE);
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GURL(kExampleURL);
   AppId app_id = InstallWebApp(std::move(web_app_info));
 
@@ -1354,7 +1354,7 @@
 // app window.
 IN_PROC_BROWSER_TEST_F(WebAppBrowserTest, ReparentDisplayBrowserApp) {
   const GURL app_url = GetSecureAppURL();
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->display_mode = DisplayMode::kBrowser;
@@ -1438,7 +1438,7 @@
       https_server()->GetURL("app.com", "/web_apps/title_appname_prefix.html");
   const std::u16string app_title = u"A Web App";
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
@@ -1462,7 +1462,7 @@
   // empty or simple title.
   const GURL app_url = https_server()->GetURL("app.site.test", "/empty.html");
   const std::u16string app_title = u"A Web App";
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
@@ -1494,7 +1494,7 @@
   const GURL app_url = GetSecureAppURL();
   const std::u16string app_title = u"A Web App";
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->title = app_title;
@@ -1531,7 +1531,7 @@
       embedded_test_server()->GetURL("app.site.test", "/simple.html");
   const std::u16string app_title = u"A Web App";
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->title = app_title;
   const AppId app_id = InstallWebApp(std::move(web_app_info));
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
index 88a6337..a7ea720 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.cc
@@ -61,7 +61,7 @@
 }
 
 AppId WebAppControllerBrowserTest::InstallPWA(const GURL& start_url) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url.GetWithoutFilename();
   web_app_info->user_display_mode = DisplayMode::kStandalone;
@@ -70,7 +70,7 @@
 }
 
 AppId WebAppControllerBrowserTest::InstallWebApp(
-    std::unique_ptr<WebApplicationInfo> web_app_info) {
+    std::unique_ptr<WebAppInstallInfo> web_app_info) {
   return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
 }
 
diff --git a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
index 57c0a0b..3ed45766 100644
--- a/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
+++ b/chrome/browser/ui/web_applications/web_app_controller_browsertest.h
@@ -43,7 +43,7 @@
 
   AppId InstallPWA(const GURL& app_url);
 
-  AppId InstallWebApp(std::unique_ptr<WebApplicationInfo> web_app_info);
+  AppId InstallWebApp(std::unique_ptr<WebAppInstallInfo> web_app_info);
 
   // Launches the app as a window and returns the browser.
   Browser* LaunchWebAppBrowser(const AppId&);
diff --git a/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc b/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
index 894021e7..e5c0f8b 100644
--- a/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_dark_mode_browsertest.cc
@@ -34,7 +34,7 @@
   ~WebAppDarkModeBrowserTest() override = default;
 
   AppId InstallWebAppFromInfo() {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     // We want to hang so WebContents does not update the background color.
     web_app_info->start_url = https_server()->GetURL("/hung");
     web_app_info->title = u"A Web App";
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 f5c50af..313b7a5 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_utils.cc
@@ -36,7 +36,7 @@
     webapps::WebappInstallSource install_source,
     chrome::PwaInProductHelpState iph_state,
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback web_app_acceptance_callback) {
   DCHECK(web_app_info);
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
index f9563707..e30c2d7 100644
--- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -209,7 +209,7 @@
   }
 
   AppId InstallWebAppAndCountApps(
-      std::unique_ptr<WebApplicationInfo> web_app_info) {
+      std::unique_ptr<WebAppInstallInfo> web_app_info) {
     AppId app_id = InstallWebApp(std::move(web_app_info));
     CountUserInstalledApps();
     return app_id;
@@ -229,7 +229,7 @@
 
   const GURL example_url = GURL("http://example.org/");
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = example_url;
   web_app_info->scope = example_url;
   web_app_info->user_display_mode = DisplayMode::kStandalone;
@@ -255,7 +255,7 @@
 
   const GURL example_url = GURL("http://example.org/");
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = example_url;
   web_app_info->scope = example_url;
   web_app_info->user_display_mode = DisplayMode::kBrowser;
@@ -280,7 +280,7 @@
 
   const GURL example_url = GURL("http://example.org/");
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = example_url;
   // If app has no scope then UrlHandlers::GetUrlHandlers are empty. Therefore,
   // the app is counted as installed via the Create Shortcut button.
@@ -314,13 +314,13 @@
 
   // Install two apps.
   {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = example_url1;
     web_app_info->scope = example_url1;
     app_id1 = InstallWebAppAndCountApps(std::move(web_app_info));
   }
   {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = example_url2;
     web_app_info->scope = example_url2;
     app_id2 = InstallWebAppAndCountApps(std::move(web_app_info));
@@ -365,7 +365,7 @@
   for (int i = 0; i < num_user_apps; ++i) {
     const GURL url = GetUrlForSuffix(base_url, i);
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->scope = url;
     AppId app_id = InstallWebAppAndCountApps(std::move(web_app_info));
@@ -425,7 +425,7 @@
   const GURL start_url = GURL("http://example.org/app/");
   const GURL outer_url = GURL("http://example.org/");
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = start_url;
   web_app_info->user_display_mode = DisplayMode::kBrowser;
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
index 6d1cf9f..3032376 100644
--- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -94,7 +94,7 @@
   void InstallFileHandlingPWA() {
     GURL url = GetSecureAppURL();
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->scope = url.GetWithoutFilename();
     web_app_info->title = u"A Hosted App";
@@ -130,7 +130,7 @@
   }
 
   AppId InstallAnotherFileHandlingPwa(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->scope = start_url.GetWithoutFilename();
     web_app_info->title = u"A second app";
@@ -345,7 +345,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest,
                        LaunchQueueSetOnRedirect) {
   // Install an app where the file handling action page redirects.
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url =
       https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
   web_app_info->scope = web_app_info->start_url.GetWithoutFilename();
@@ -381,7 +381,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebAppFileHandlingBrowserTest, LaunchQueueSetOnReload) {
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url =
       https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
   web_app_info->scope = web_app_info->start_url.GetWithoutFilename();
@@ -418,7 +418,7 @@
                        LaunchQueueNotSetOnCrossOriginRedirect) {
   // Install an app where the file handling action page redirects to a page on a
   // different origin.
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url =
       https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
   web_app_info->scope = web_app_info->start_url.GetWithoutFilename();
@@ -457,7 +457,7 @@
                        LaunchQueueNotSetOnNavigate) {
   GURL start_url =
       https_server()->GetURL("app.com", "/web_app_file_handling/index.html");
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = start_url;
   web_app_info->scope = web_app_info->start_url.GetWithoutFilename();
   web_app_info->title = u"An app that will be navigated";
diff --git a/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc b/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
index 07862d5e..abb323fb 100644
--- a/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_metrics_browsertest.cc
@@ -51,7 +51,7 @@
   }
 
   AppId InstallWebApp() {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GetInstallableAppURL();
     web_app_info->title = u"A Web App";
     web_app_info->display_mode = DisplayMode::kStandalone;
@@ -108,7 +108,7 @@
                        InstalledWebAppInTab_RecordsDailyInteraction) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GetInstallableAppURL();
   web_app_info->title = u"A Web App";
   web_app_info->display_mode = DisplayMode::kStandalone;
@@ -151,7 +151,7 @@
     InstalledWebAppInWindow_RecordsDailyInteractionWithSessionDurations) {
   ukm::TestAutoSetUkmRecorder ukm_recorder;
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GetInstallableAppURL();
   web_app_info->title = u"A Web App";
   web_app_info->display_mode = DisplayMode::kStandalone;
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
index c01cea5a..47c3d19 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
@@ -56,7 +56,7 @@
   Profile* profile() { return browser()->profile(); }
 
   const AppId InstallWebApp(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = start_url;
     web_app_info->user_display_mode = DisplayMode::kStandalone;
     return web_app::test::InstallWebApp(profile(), std::move(web_app_info));
diff --git a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
index b130075a..8b92f43d 100644
--- a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
@@ -184,7 +184,7 @@
 IN_PROC_BROWSER_TEST_F(WebAppUninstallBrowserTest, PrefsRemovedAfterUninstall) {
   const GURL app_url = GetSecureAppURL();
   const url::Origin origin = url::Origin::Create(app_url);
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = app_url;
   web_app_info->scope = app_url.GetWithoutFilename();
   web_app_info->is_storage_isolated = true;
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 1e2fb6f..386d144 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -1170,7 +1170,7 @@
 void AppLauncherHandler::OnFaviconForAppInstallFromLink(
     std::unique_ptr<AppInstallInfo> install_info,
     const favicon_base::FaviconImageResult& image_result) {
-  auto web_app = std::make_unique<WebApplicationInfo>();
+  auto web_app = std::make_unique<WebAppInstallInfo>();
   web_app->title = install_info->title;
   web_app->start_url = install_info->app_url;
 
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
index 7e66364..f02cb50 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler_unittest.cc
@@ -64,8 +64,8 @@
   }
 };
 
-std::unique_ptr<WebApplicationInfo> BuildWebAppInfo() {
-  auto app_info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> BuildWebAppInfo() {
+  auto app_info = std::make_unique<WebAppInstallInfo>();
   app_info->start_url = GURL(kTestAppUrl);
   app_info->scope = GURL(kTestAppUrl);
   app_info->title = kTestAppTitle;
diff --git a/chrome/browser/web_applications/app_service/link_capturing_migration_manager_browsertest.cc b/chrome/browser/web_applications/app_service/link_capturing_migration_manager_browsertest.cc
index 2355eb0..d0bad75 100644
--- a/chrome/browser/web_applications/app_service/link_capturing_migration_manager_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/link_capturing_migration_manager_browsertest.cc
@@ -36,7 +36,7 @@
   Profile* profile = browser()->profile();
   auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->title = u"Test app";
   web_app_info->start_url = GURL("https://example.org");
   web_app_info->capture_links =
diff --git a/chrome/browser/web_applications/app_service/web_apps_publisher_host_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_publisher_host_browsertest.cc
index fe5dafc..ad4bc80a 100644
--- a/chrome/browser/web_applications/app_service/web_apps_publisher_host_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_publisher_host_browsertest.cc
@@ -216,7 +216,7 @@
   AppId app_id;
   {
     const std::u16string original_description = u"Original Web App";
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url;
     web_app_info->title = original_description;
@@ -230,7 +230,7 @@
 
   {
     const std::u16string updated_description = u"Updated Web App";
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url;
     web_app_info->title = updated_description;
@@ -259,7 +259,7 @@
   AppId app_id;
   {
     const std::u16string description = u"Web App";
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = app_url;
     web_app_info->scope = app_url;
     web_app_info->title = description;
@@ -325,7 +325,7 @@
 
   // Install an additional app from a different host.
   {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = GURL("https://example.com:8080/");
     web_app_info->scope = web_app_info->start_url;
     web_app_info->title = u"Unrelated Web App";
@@ -647,7 +647,7 @@
   AppId app2_id;
   {
     const std::u16string description = u"Uninstalled Web App";
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url =
         embedded_test_server()->GetURL("app.site.com", "/simple.html");
     web_app_info->scope = web_app_info->start_url.GetWithoutFilename();
diff --git a/chrome/browser/web_applications/docs/manifest_representations.md b/chrome/browser/web_applications/docs/manifest_representations.md
index 2993bcc..db024f61 100644
--- a/chrome/browser/web_applications/docs/manifest_representations.md
+++ b/chrome/browser/web_applications/docs/manifest_representations.md
@@ -10,7 +10,7 @@
  - [blink::Manifest](../../../../third_party/blink/public/common/manifest/manifest.h)\
    Pre blink.mojom.Manifest representation that is getting cleaned up: https://crbug.com/1233362
 
- - [WebApplicationInfo](../web_application_info.h)\
+ - [WebAppInstallInfo](../web_application_info.h)\
    Used for installation and updates.
 
  - [web_app::WebApp](../web_app.h)\
@@ -26,7 +26,7 @@
    Manifest data provided by an HTML document.
 
  - [web_app::ParseOfflineManifest()](../preinstalled_web_app_utils.cc)\
-   Custom JSON + PNG format for bundling WebApplicationInfo data on disk for offline default web app installation.
+   Custom JSON + PNG format for bundling WebAppInstallInfo data on disk for offline default web app installation.
 
  - [WebApkInfo](../../android/webapk/webapk_info.h)\
    Web app installation data that was packaged in an APK.
diff --git a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
index 11ed93b..76d4aeff 100644
--- a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
@@ -136,7 +136,7 @@
         GetAppIdForUrl(app_url), uninstalled};
   }
 
-  const std::vector<WebApplicationInfo>& web_app_info_list() {
+  const std::vector<WebAppInstallInfo>& web_app_info_list() {
     return web_app_info_list_;
   }
 
@@ -151,7 +151,7 @@
   size_t num_reparent_tab_calls() { return num_reparent_tab_calls_; }
 
   // WebAppInstallFinalizer
-  void FinalizeInstall(const WebApplicationInfo& web_app_info,
+  void FinalizeInstall(const WebAppInstallInfo& web_app_info,
                        const FinalizeOptions& options,
                        InstallFinalizedCallback callback) override {
     DCHECK(
@@ -183,7 +183,7 @@
     NOTREACHED();
   }
 
-  void FinalizeUpdate(const WebApplicationInfo& web_app_info,
+  void FinalizeUpdate(const WebAppInstallInfo& web_app_info,
                       InstallFinalizedCallback callback) override {
     NOTREACHED();
   }
@@ -261,7 +261,7 @@
  private:
   raw_ptr<WebAppRegistrarMutable> registrar_ = nullptr;
 
-  std::vector<WebApplicationInfo> web_app_info_list_;
+  std::vector<WebAppInstallInfo> web_app_info_list_;
   std::vector<FinalizeOptions> finalize_options_list_;
   std::vector<GURL> uninstall_external_web_app_urls_;
 
@@ -342,7 +342,7 @@
 
   FakeDataRetriever* data_retriever() { return data_retriever_; }
 
-  const WebApplicationInfo& web_app_info() {
+  const WebAppInstallInfo& web_app_info() {
     DCHECK_EQ(1u, install_finalizer_->web_app_info_list().size());
     return install_finalizer_->web_app_info_list().at(0);
   }
@@ -363,8 +363,8 @@
     manifest->start_url = options.install_url;
     manifest->name = u"Manifest Name";
 
-    data_retriever_->SetRendererWebApplicationInfo(
-        std::make_unique<WebApplicationInfo>());
+    data_retriever_->SetRendererWebAppInstallInfo(
+        std::make_unique<WebAppInstallInfo>());
 
     data_retriever_->SetManifest(std::move(manifest), /*is_installable=*/true);
 
@@ -455,7 +455,7 @@
   auto task = GetInstallationTaskWithTestMocks(
       {kWebAppUrl, DisplayMode::kStandalone,
        ExternalInstallSource::kInternalDefault});
-  data_retriever()->SetRendererWebApplicationInfo(nullptr);
+  data_retriever()->SetRendererWebAppInstallInfo(nullptr);
   url_loader().SetPrepareForLoadResultLoaded();
   url_loader().SetNextLoadUrlResult(kWebAppUrl,
                                     WebAppUrlLoader::Result::kUrlLoaded);
@@ -469,7 +469,7 @@
                           ExternallyInstalledWebAppPrefs(profile()->GetPrefs())
                               .LookupAppId(kWebAppUrl);
 
-                      EXPECT_EQ(InstallResultCode::kGetWebApplicationInfoFailed,
+                      EXPECT_EQ(InstallResultCode::kGetWebAppInstallInfoFailed,
                                 result.code);
                       EXPECT_FALSE(result.app_id.has_value());
 
@@ -710,7 +710,7 @@
             EXPECT_EQ(1u, finalizer()->finalize_options_list().size());
             EXPECT_EQ(webapps::WebappInstallSource::EXTERNAL_POLICY,
                       finalize_options().install_source);
-            const WebApplicationInfo& web_app_info =
+            const WebAppInstallInfo& web_app_info =
                 finalizer()->web_app_info_list().at(0);
 
             EXPECT_EQ(base::UTF8ToUTF16(kWebAppUrl.spec()), web_app_info.title);
@@ -749,7 +749,7 @@
             EXPECT_EQ(1u, finalizer()->finalize_options_list().size());
             EXPECT_EQ(webapps::WebappInstallSource::EXTERNAL_DEFAULT,
                       finalize_options().install_source);
-            const WebApplicationInfo& web_app_info =
+            const WebAppInstallInfo& web_app_info =
                 finalizer()->web_app_info_list().at(0);
 
             EXPECT_EQ(base::UTF8ToUTF16(kWebAppUrl.spec()), web_app_info.title);
@@ -792,7 +792,7 @@
             EXPECT_EQ(1u, finalizer()->finalize_options_list().size());
             EXPECT_EQ(webapps::WebappInstallSource::EXTERNAL_POLICY,
                       finalize_options().install_source);
-            const WebApplicationInfo& web_app_info =
+            const WebAppInstallInfo& web_app_info =
                 finalizer()->web_app_info_list().at(0);
 
             EXPECT_EQ(base::UTF8ToUTF16(kWebAppUrl.spec()), web_app_info.title);
@@ -1090,7 +1090,7 @@
                                  ExternalInstallSource::kSystemInstalled);
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindLambdaForTesting([&kWebAppUrl]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = kWebAppUrl;
     info->scope = kWebAppUrl.GetWithoutFilename();
     info->title = u"Foo Web App";
@@ -1141,7 +1141,7 @@
                                  ExternalInstallSource::kSystemInstalled);
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindLambdaForTesting([&kWebAppUrl]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = kWebAppUrl;
     info->scope = kWebAppUrl.GetWithoutFilename();
     info->title = u"Foo Web App";
diff --git a/chrome/browser/web_applications/external_install_options.h b/chrome/browser/web_applications/external_install_options.h
index 45a21d9ba..5ee60b9e 100644
--- a/chrome/browser/web_applications/external_install_options.h
+++ b/chrome/browser/web_applications/external_install_options.h
@@ -19,8 +19,8 @@
 
 namespace web_app {
 
-using WebApplicationInfoFactory =
-    base::RepeatingCallback<std::unique_ptr<WebApplicationInfo>()>;
+using WebAppInstallInfoFactory =
+    base::RepeatingCallback<std::unique_ptr<WebAppInstallInfo>()>;
 
 enum class ExternalInstallSource;
 
@@ -176,9 +176,9 @@
   // |service_worker_registration_url| will not be loaded.
   bool only_use_app_info_factory = false;
 
-  // A factory callback that returns a unique_ptr<WebApplicationInfo> to be used
+  // A factory callback that returns a unique_ptr<WebAppInstallInfo> to be used
   // as the app's installation metadata.
-  WebApplicationInfoFactory app_info_factory;
+  WebAppInstallInfoFactory app_info_factory;
 
   // The type of SystemWebApp, if this app is a System Web App.
   absl::optional<SystemAppType> system_app_type = absl::nullopt;
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.cc b/chrome/browser/web_applications/externally_managed_app_install_task.cc
index 3e699e5..25b92aa0 100644
--- a/chrome/browser/web_applications/externally_managed_app_install_task.cc
+++ b/chrome/browser/web_applications/externally_managed_app_install_task.cc
@@ -234,7 +234,7 @@
     return;
   }
 
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title =
       install_options_.placeholder_name
           ? base::UTF8ToUTF16(install_options_.placeholder_name.value())
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.h b/chrome/browser/web_applications/externally_managed_app_install_task.h
index 60bb620..fb9eb88 100644
--- a/chrome/browser/web_applications/externally_managed_app_install_task.h
+++ b/chrome/browser/web_applications/externally_managed_app_install_task.h
@@ -71,7 +71,7 @@
   const ExternalInstallOptions& install_options() { return install_options_; }
 
  private:
-  // Install directly from a fully specified WebApplicationInfo struct. Used
+  // Install directly from a fully specified WebAppInstallInfo struct. Used
   // by system apps.
   void InstallFromInfo(ResultCallback result_callback);
 
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
index 6d9a6d86..1e1ceb4 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
@@ -60,9 +60,9 @@
   return options;
 }
 
-std::unique_ptr<WebApplicationInfo> GetWebApplicationInfo(const GURL& url) {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> GetWebAppInstallInfo(const GURL& url) {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = url;
   info->scope = url.GetWithoutFilename();
   info->title = u"Foo Web App";
@@ -78,8 +78,8 @@
   options.only_use_app_info_factory = true;
   // Static to ensure re-use across multiple function calls for
   // ExternalInstallOptions equality checking.
-  static WebApplicationInfoFactory app_info_factory =
-      base::BindRepeating(&GetWebApplicationInfo, url);
+  static WebAppInstallInfoFactory app_info_factory =
+      base::BindRepeating(&GetWebAppInstallInfo, url);
   options.app_info_factory = app_info_factory;
 
   if (override_previous_user_uninstall.has_value())
diff --git a/chrome/browser/web_applications/manifest_update_task.h b/chrome/browser/web_applications/manifest_update_task.h
index 54e1f138..555447d9 100644
--- a/chrome/browser/web_applications/manifest_update_task.h
+++ b/chrome/browser/web_applications/manifest_update_task.h
@@ -237,7 +237,7 @@
   raw_ptr<WebAppSyncBridge> sync_bridge_ = nullptr;
 
   Stage stage_;
-  absl::optional<WebApplicationInfo> web_application_info_;
+  absl::optional<WebAppInstallInfo> web_application_info_;
   absl::optional<WebAppIconDownloader> icon_downloader_;
 
   // Two KeepAlive objects, to make sure in progress manifest updates survive
diff --git a/chrome/browser/web_applications/os_integration_manager.cc b/chrome/browser/web_applications/os_integration_manager.cc
index 32f4667..754742e 100644
--- a/chrome/browser/web_applications/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration_manager.cc
@@ -158,7 +158,7 @@
 void OsIntegrationManager::InstallOsHooks(
     const AppId& app_id,
     InstallOsHooksCallback callback,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options) {
   if (g_suppress_os_hooks_for_testing_) {
     OsHooksErrors os_hooks_errors;
@@ -272,7 +272,7 @@
     const AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     UpdateOsHooksCallback callback) {
   if (g_suppress_os_hooks_for_testing_) {
     OsHooksErrors os_hooks_errors;
@@ -603,7 +603,7 @@
 
 void OsIntegrationManager::UpdateShortcutsMenu(
     const AppId& app_id,
-    const WebApplicationInfo& web_app_info) {
+    const WebAppInstallInfo& web_app_info) {
   DCHECK(shortcut_manager_);
   if (web_app_info.shortcuts_menu_item_infos.empty()) {
     shortcut_manager_->UnregisterShortcutsMenuWithOs(app_id);
@@ -750,7 +750,7 @@
 
 void OsIntegrationManager::OnShortcutsCreated(
     const AppId& app_id,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options,
     scoped_refptr<OsHooksBarrier> barrier,
     bool shortcuts_created) {
diff --git a/chrome/browser/web_applications/os_integration_manager.h b/chrome/browser/web_applications/os_integration_manager.h
index ba35364a5..7654a8c 100644
--- a/chrome/browser/web_applications/os_integration_manager.h
+++ b/chrome/browser/web_applications/os_integration_manager.h
@@ -112,7 +112,7 @@
   // virtual for testing
   virtual void InstallOsHooks(const AppId& app_id,
                               InstallOsHooksCallback callback,
-                              std::unique_ptr<WebApplicationInfo> web_app_info,
+                              std::unique_ptr<WebAppInstallInfo> web_app_info,
                               InstallOsHooksOptions options);
 
   // Uninstall specific OS hooks for the web app.
@@ -136,7 +136,7 @@
       const AppId& app_id,
       base::StringPiece old_name,
       FileHandlerUpdateAction file_handlers_need_os_update,
-      const WebApplicationInfo& web_app_info,
+      const WebAppInstallInfo& web_app_info,
       UpdateOsHooksCallback callback);
 
   // Proxy calls for WebAppShortcutManager.
@@ -274,7 +274,7 @@
                                base::StringPiece old_name,
                                base::OnceClosure callback);
   virtual void UpdateShortcutsMenu(const AppId& app_id,
-                                   const WebApplicationInfo& web_app_info);
+                                   const WebAppInstallInfo& web_app_info);
 
   // Utility methods:
   virtual std::unique_ptr<ShortcutInfo> BuildShortcutInfo(const AppId& app_id);
@@ -283,7 +283,7 @@
   class OsHooksBarrier;
 
   void OnShortcutsCreated(const AppId& app_id,
-                          std::unique_ptr<WebApplicationInfo> web_app_info,
+                          std::unique_ptr<WebAppInstallInfo> web_app_info,
                           InstallOsHooksOptions options,
                           scoped_refptr<OsHooksBarrier> barrier,
                           bool shortcuts_created);
diff --git a/chrome/browser/web_applications/os_integration_manager_unittest.cc b/chrome/browser/web_applications/os_integration_manager_unittest.cc
index e4df46b..d546939 100644
--- a/chrome/browser/web_applications/os_integration_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration_manager_unittest.cc
@@ -193,7 +193,7 @@
   const AppId app_id = "test";
   testing::StrictMock<MockOsIntegrationManager> manager;
 
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   base::StringPiece old_name = "test-name";
 
   EXPECT_CALL(
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
index 1acea4f..2b6d0c45 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -994,7 +994,7 @@
       GenerateAppId(/*manifest_id=*/absl::nullopt, preinstalled_app_start_url);
 
   // Install user app.
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   web_application_info->start_url = user_app_start_url;
   web_application_info->title = u"Test user app";
   AppId user_app_id =
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc
index 70a4e54..b29fde17 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc
@@ -240,7 +240,7 @@
   options.uninstall_and_replace = {kExtensionId};
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating(
-      []() { return std::make_unique<WebApplicationInfo>(); });
+      []() { return std::make_unique<WebAppInstallInfo>(); });
   preinstalled_web_app_override_.apps.push_back(std::move(options));
 
   auto expect_present = [&]() {
diff --git a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
index 84b2b46..945c0cca 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_migration_browsertest.cc
@@ -648,7 +648,7 @@
   options.uninstall_and_replace.push_back(kExtensionId);
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindLambdaForTesting([&]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->start_url = GetWebAppUrl();
     info->title = u"Test app";
     return info;
diff --git a/chrome/browser/web_applications/preinstalled_web_app_utils.cc b/chrome/browser/web_applications/preinstalled_web_app_utils.cc
index badabea0..921499a 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_utils.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_utils.cc
@@ -382,14 +382,14 @@
   // offline_manifest
   value = app_config.FindDictKey(kOfflineManifest);
   if (value) {
-    WebApplicationInfoFactoryOrError offline_manifest_result =
+    WebAppInstallInfoFactoryOrError offline_manifest_result =
         ParseOfflineManifest(file_utils, dir, file, *value);
     if (std::string* error =
             absl::get_if<std::string>(&offline_manifest_result)) {
       return std::move(*error);
     }
-    options.app_info_factory = std::move(
-        absl::get<WebApplicationInfoFactory>(offline_manifest_result));
+    options.app_info_factory =
+        std::move(absl::get<WebAppInstallInfoFactory>(offline_manifest_result));
   }
 
   if (options.only_use_app_info_factory && !options.app_info_factory) {
@@ -430,12 +430,12 @@
   return options;
 }
 
-WebApplicationInfoFactoryOrError ParseOfflineManifest(
+WebAppInstallInfoFactoryOrError ParseOfflineManifest(
     FileUtilsWrapper& file_utils,
     const base::FilePath& dir,
     const base::FilePath& file,
     const base::Value& offline_manifest) {
-  WebApplicationInfo app_info;
+  WebAppInstallInfo app_info;
 
   // name
   const std::string* name_string =
@@ -562,7 +562,7 @@
   }
 
   return base::BindRepeating(
-      &std::make_unique<WebApplicationInfo, const WebApplicationInfo&>,
+      &std::make_unique<WebAppInstallInfo, const WebAppInstallInfo&>,
       std::move(app_info));
 }
 
diff --git a/chrome/browser/web_applications/preinstalled_web_app_utils.h b/chrome/browser/web_applications/preinstalled_web_app_utils.h
index 3d4eb3b7..236372f 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_utils.h
+++ b/chrome/browser/web_applications/preinstalled_web_app_utils.h
@@ -29,10 +29,10 @@
                            const base::FilePath& file,
                            const base::Value& app_config);
 
-using WebApplicationInfoFactoryOrError =
-    absl::variant<WebApplicationInfoFactory, std::string>;
+using WebAppInstallInfoFactoryOrError =
+    absl::variant<WebAppInstallInfoFactory, std::string>;
 
-WebApplicationInfoFactoryOrError ParseOfflineManifest(
+WebAppInstallInfoFactoryOrError ParseOfflineManifest(
     FileUtilsWrapper& file_utils,
     const base::FilePath& dir,
     const base::FilePath& file,
diff --git a/chrome/browser/web_applications/preinstalled_web_app_utils_unittest.cc b/chrome/browser/web_applications/preinstalled_web_app_utils_unittest.cc
index 4adefd6..fbb37ad0 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_utils_unittest.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_utils_unittest.cc
@@ -57,17 +57,17 @@
     return absl::nullopt;
   }
 
-  absl::optional<WebApplicationInfoFactory> ParseOfflineManifest(
+  absl::optional<WebAppInstallInfoFactory> ParseOfflineManifest(
       const char* offline_manifest_string) {
     absl::optional<base::Value> offline_manifest =
         base::JSONReader::Read(offline_manifest_string);
     DCHECK(offline_manifest);
-    WebApplicationInfoFactoryOrError result = ::web_app::ParseOfflineManifest(
+    WebAppInstallInfoFactoryOrError result = ::web_app::ParseOfflineManifest(
         *file_utils_, base::FilePath(FILE_PATH_LITERAL("test_dir")),
         base::FilePath(FILE_PATH_LITERAL("test_dir/test.json")),
         *offline_manifest);
-    if (WebApplicationInfoFactory* factory =
-            absl::get_if<WebApplicationInfoFactory>(&result)) {
+    if (WebAppInstallInfoFactory* factory =
+            absl::get_if<WebAppInstallInfoFactory>(&result)) {
       return std::move(*factory);
     }
     return absl::nullopt;
@@ -186,7 +186,7 @@
 #define MAYBE_OfflineManifestValid OfflineManifestValid
 #endif
 TEST_F(PreinstalledWebAppUtilsTest, MAYBE_OfflineManifestValid) {
-  std::unique_ptr<WebApplicationInfo> app_info = ParseOfflineManifest(R"(
+  std::unique_ptr<WebAppInstallInfo> app_info = ParseOfflineManifest(R"(
     {
       "name": "Test App",
       "start_url": "https://test.org/start.html",
@@ -196,8 +196,8 @@
       "theme_color_argb_hex": "AABBCCDD"
     }
   )")
-                                                     .value()
-                                                     .Run();
+                                                    .value()
+                                                    .Run();
   EXPECT_TRUE(app_info);
   EXPECT_EQ(app_info->title, u"Test App");
   EXPECT_EQ(app_info->start_url, GURL("https://test.org/start.html"));
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc b/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
index 0fbde90e..3cf0477e 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
@@ -31,7 +31,7 @@
   options.load_and_await_service_worker_registration = false;
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title = u"Gmail";
     info->start_url =
         GURL("https://mail.google.com/mail/?usp=installed_webapp");
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
index f50c31f..cfc8460 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
@@ -116,7 +116,7 @@
 
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title = base::UTF8ToUTF16(
         GetTranslatedName("Google Calendar", kNameTranslations));
     info->start_url = GURL("https://calendar.google.com/calendar/r");
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_docs.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_docs.cc
index 501b14a..18ae159 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_docs.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_docs.cc
@@ -110,7 +110,7 @@
   options.load_and_await_service_worker_registration = false;
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title =
         base::UTF8ToUTF16(GetTranslatedName("Docs", kNameTranslations));
     info->start_url =
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
index 077a311..d92e62c8 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
@@ -115,7 +115,7 @@
 
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title =
         base::UTF8ToUTF16(GetTranslatedName("Google Drive", kNameTranslations));
     info->start_url = GURL("https://drive.google.com/?lfhs=2");
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_sheets.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_sheets.cc
index caf8007c8..22b5bcccb 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_sheets.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_sheets.cc
@@ -108,7 +108,7 @@
   options.load_and_await_service_worker_registration = false;
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title =
         base::UTF8ToUTF16(GetTranslatedName("Sheets", kNameTranslations));
 
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_slides.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_slides.cc
index d82732e..dd13475 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_slides.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_slides.cc
@@ -108,7 +108,7 @@
   options.load_and_await_service_worker_registration = false;
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title =
         base::UTF8ToUTF16(GetTranslatedName("Slides", kNameTranslations));
     info->start_url =
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/youtube.cc b/chrome/browser/web_applications/preinstalled_web_apps/youtube.cc
index b5583db..149bc1d 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/youtube.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/youtube.cc
@@ -32,7 +32,7 @@
   options.load_and_await_service_worker_registration = false;
   options.only_use_app_info_factory = true;
   options.app_info_factory = base::BindRepeating([]() {
-    auto info = std::make_unique<WebApplicationInfo>();
+    auto info = std::make_unique<WebAppInstallInfo>();
     info->title = u"YouTube";
     info->start_url = GURL("https://www.youtube.com/?feature=ytca");
     info->scope = GURL("https://www.youtube.com/");
diff --git a/chrome/browser/web_applications/system_web_apps/README.md b/chrome/browser/web_applications/system_web_apps/README.md
index 5212f52..53d9eb7 100644
--- a/chrome/browser/web_applications/system_web_apps/README.md
+++ b/chrome/browser/web_applications/system_web_apps/README.md
@@ -19,7 +19,7 @@
 
 ## Installation
 System Web Apps are installed on startup using the Web Apps installation pipeline. The key differences are:
-* SWAs don’t use the html->manifest path at all. They are installed directly by creating a WebApplicationInfo object directly in C++ code, and skipping much of the installation process.
+* SWAs don’t use the html->manifest path at all. They are installed directly by creating a WebAppInstallInfo object directly in C++ code, and skipping much of the installation process.
 * The SWAs are checked for installation or upgrade on boot, and re-installed up to the current version of ChromeOS.
 
 ## Serving Resources
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h b/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h
index 5d603ab..fa10b87 100644
--- a/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h
+++ b/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h
@@ -42,7 +42,7 @@
 // their application, overriding GetWebAppInfo(), and other methods as needed.
 class SystemWebAppDelegate {
  public:
-  // When installing via a WebApplicationInfo, the url is never loaded. It's
+  // When installing via a WebAppInstallInfo, the url is never loaded. It's
   // needed only for various legacy reasons, maps for tracking state, and
   // generating the AppId and things of that nature.
   SystemWebAppDelegate(
@@ -67,8 +67,8 @@
   // The URL that the System App will be installed from.
   const GURL& GetInstallUrl() const { return install_url_; }
 
-  // Returns a WebApplicationInfo struct to complete installation.
-  virtual std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const = 0;
+  // Returns a WebAppInstallInfo struct to complete installation.
+  virtual std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const = 0;
 
   // If specified, the apps in |uninstall_and_replace| will have their data
   // migrated to this System App.
diff --git a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_unittest.cc b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_unittest.cc
index fb0026d..a6f182d 100644
--- a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_unittest.cc
@@ -71,24 +71,24 @@
   return GURL(content::GetWebUIURL("system-app2"));
 }
 
-std::unique_ptr<WebApplicationInfo> GetWebApplicationInfo(const GURL& url) {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> GetWebAppInstallInfo(const GURL& url) {
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = url;
   info->scope = url.GetWithoutFilename();
   info->title = u"Web App";
   return info;
 }
 
-WebApplicationInfoFactory GetApp1WebAppInfoFactory() {
+WebAppInstallInfoFactory GetApp1WebAppInfoFactory() {
   // "static" so that ExternalInstallOptions comparisons in tests work.
-  static auto factory = base::BindRepeating(&GetWebApplicationInfo, AppUrl1());
+  static auto factory = base::BindRepeating(&GetWebAppInstallInfo, AppUrl1());
   return factory;
 }
 
-WebApplicationInfoFactory GetApp2WebAppInfoFactory() {
+WebAppInstallInfoFactory GetApp2WebAppInfoFactory() {
   // "static" so that ExternalInstallOptions comparisons in tests work.
-  static auto factory = base::BindRepeating(&GetWebApplicationInfo, AppUrl2());
+  static auto factory = base::BindRepeating(&GetWebAppInstallInfo, AppUrl2());
   return factory;
 }
 
@@ -459,7 +459,7 @@
         SystemAppType::SETTINGS,
         std::make_unique<UnittestingSystemAppDelegate>(
             SystemAppType::SETTINGS, kSettingsAppInternalName, kAppUrl3,
-            base::BindRepeating(&GetWebApplicationInfo, kAppUrl3)));
+            base::BindRepeating(&GetWebAppInstallInfo, kAppUrl3)));
 
     system_apps.emplace(SystemAppType::CAMERA,
                         std::make_unique<UnittestingSystemAppDelegate>(
@@ -1046,7 +1046,7 @@
   TimerSystemAppDelegate(SystemAppType type,
                          const std::string& name,
                          const GURL& url,
-                         WebApplicationInfoFactory info_factory,
+                         WebAppInstallInfoFactory info_factory,
                          absl::optional<base::TimeDelta> period,
                          bool open_immediately)
       : UnittestingSystemAppDelegate(type, name, url, info_factory),
@@ -1363,7 +1363,7 @@
       SystemAppType::SETTINGS,
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
-          base::BindRepeating(&GetWebApplicationInfo, AppUrl1())));
+          base::BindRepeating(&GetWebAppInstallInfo, AppUrl1())));
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   base::RunLoop run_loop;
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
index 1ec28f3ac..a1946e2 100644
--- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
+++ b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
@@ -90,14 +90,14 @@
     SystemAppType type,
     const std::string& name,
     const GURL& url,
-    WebApplicationInfoFactory info_factory)
+    WebAppInstallInfoFactory info_factory)
     : web_app::SystemWebAppDelegate(type, name, url, nullptr),
       info_factory_(info_factory) {}
 
 UnittestingSystemAppDelegate::~UnittestingSystemAppDelegate() = default;
 
-std::unique_ptr<WebApplicationInfo>
-UnittestingSystemAppDelegate::GetWebAppInfo() const {
+std::unique_ptr<WebAppInstallInfo> UnittestingSystemAppDelegate::GetWebAppInfo()
+    const {
   return info_factory_.Run();
 }
 
@@ -276,8 +276,8 @@
 
 TestSystemWebAppInstallation::~TestSystemWebAppInstallation() = default;
 
-std::unique_ptr<WebApplicationInfo> GenerateWebApplicationInfoForTestApp() {
-  auto info = std::make_unique<WebApplicationInfo>();
+std::unique_ptr<WebAppInstallInfo> GenerateWebAppInstallInfoForTestApp() {
+  auto info = std::make_unique<WebAppInstallInfo>();
   // the pwa.html is arguably wrong, but the manifest version uses it
   // incorrectly as well, and it's a lot of work to fix it. App ids are
   // generated from this, and it's important to keep it stable across the
@@ -291,9 +291,9 @@
   return info;
 }
 
-std::unique_ptr<WebApplicationInfo>
-GenerateWebApplicationInfoForTestAppUntrusted() {
-  auto info = GenerateWebApplicationInfoForTestApp();
+std::unique_ptr<WebAppInstallInfo>
+GenerateWebAppInstallInfoForTestAppUntrusted() {
+  auto info = GenerateWebAppInstallInfoForTestApp();
   info->start_url = GURL("chrome-untrusted://test-system-app/pwa.html");
   info->scope = GURL("chrome-untrusted://test-system-app/");
   return info;
@@ -312,7 +312,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::TERMINAL, "Terminal",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldReuseExistingWindow(false);
   delegate->SetShouldHaveTabStrip(true);
 
@@ -327,7 +327,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::SETTINGS, "OSSettings",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetUrlInSystemAppScope(GURL("http://example.com/in-scope"));
 
   return base::WrapUnique(
@@ -342,7 +342,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Media",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
   if (include_launch_directory == IncludeLaunchDirectory::kYes) {
     delegate->SetShouldIncludeLaunchDirectory(true);
@@ -365,7 +365,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Media",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
   delegate->SetEnabledOriginTrials(origin_to_trials);
   return base::WrapUnique(
@@ -379,7 +379,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
   delegate->SetShouldShowInLauncher(false);
 
@@ -394,7 +394,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldShowInSearch(false);
 
   return base::WrapUnique(
@@ -408,7 +408,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldHandleFileOpenIntents(true);
 
   return base::WrapUnique(
@@ -422,7 +422,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetAdditionalSearchTerms({IDS_SETTINGS_SECURITY});
 
   return base::WrapUnique(
@@ -436,7 +436,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::HELP, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldCaptureNavigations(true);
 
   auto* installation = new TestSystemWebAppInstallation(std::move(delegate));
@@ -448,7 +448,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::SETTINGS, "Initiating App", kInitiatingAppUrl,
           base::BindLambdaForTesting([]() {
-            auto info = std::make_unique<WebApplicationInfo>();
+            auto info = std::make_unique<WebAppInstallInfo>();
             // the pwa.html is arguably wrong, but the manifest
             // version uses it incorrectly as well, and it's a lot of
             // work to fix it. App ids are generated from this, and
@@ -476,8 +476,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::SETTINGS, "Test",
           GURL("chrome-untrusted://test-system-app/pwa.html"),
-          base::BindRepeating(
-              &GenerateWebApplicationInfoForTestAppUntrusted))));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestAppUntrusted))));
 }
 
 // static
@@ -487,7 +486,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldAllowResize(false);
   delegate->SetShouldAllowMaximize(false);
 
@@ -502,7 +501,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
 
   SystemAppBackgroundTaskInfo background_task(
       base::Days(1), GURL("chrome://test-system-app/page2.html"), true);
@@ -520,7 +519,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   /* The default value of allow_scripts_to_close_windows is false. */
   if (value) {
     delegate->SetShouldAllowScriptsToCloseWindows(value);
@@ -536,7 +535,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldHaveTabStrip(has_tab_strip);
 
   return base::WrapUnique(
@@ -551,7 +550,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::MEDIA, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetDefaultBounds(
       base::BindLambdaForTesting([&](Browser*) { return default_bounds; }));
 
@@ -566,7 +565,7 @@
       std::make_unique<UnittestingSystemAppDelegate>(
           SystemAppType::FILE_MANAGER, "Test",
           GURL("chrome://test-system-app/pwa.html"),
-          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+          base::BindRepeating(&GenerateWebAppInstallInfoForTestApp));
   delegate->SetShouldShowNewWindowMenuOption(true);
   delegate->SetShouldReuseExistingWindow(false);
 
@@ -582,8 +581,8 @@
           SystemAppType::SHORTCUT_CUSTOMIZATION, "Shortcuts",
           GURL("chrome://test-system-app/pwa.html"),
           base::BindLambdaForTesting([]() {
-            std::unique_ptr<WebApplicationInfo> info =
-                GenerateWebApplicationInfoForTestApp();
+            std::unique_ptr<WebAppInstallInfo> info =
+                GenerateWebAppInstallInfoForTestApp();
             info->title = u"Shortcuts";
             {
               WebAppShortcutsMenuItemInfo menu_item;
@@ -619,7 +618,7 @@
     SystemWebAppWindowConfig window_config) {
   auto* delegate = new UnittestingSystemAppDelegate(
       type, "Test App", app_url, base::BindLambdaForTesting([=]() {
-        auto info = std::make_unique<WebApplicationInfo>();
+        auto info = std::make_unique<WebAppInstallInfo>();
         info->start_url = app_url;
         info->scope = app_url.DeprecatedGetOriginAsURL();
         info->title = u"Test System App";
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h
index 4d573c7c..db9a37c 100644
--- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h
+++ b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h
@@ -23,13 +23,13 @@
   UnittestingSystemAppDelegate(SystemAppType type,
                                const std::string& name,
                                const GURL& url,
-                               WebApplicationInfoFactory info_factory);
+                               WebAppInstallInfoFactory info_factory);
   UnittestingSystemAppDelegate(const UnittestingSystemAppDelegate&) = delete;
   UnittestingSystemAppDelegate& operator=(const UnittestingSystemAppDelegate&) =
       delete;
   ~UnittestingSystemAppDelegate() override;
 
-  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+  std::unique_ptr<WebAppInstallInfo> GetWebAppInfo() const override;
 
   std::vector<AppId> GetAppIdsToUninstallAndReplace() const override;
   gfx::Size GetMinimumWindowSize() const override;
@@ -73,7 +73,7 @@
   void SetUrlInSystemAppScope(const GURL& url);
 
  private:
-  WebApplicationInfoFactory info_factory_;
+  WebAppInstallInfoFactory info_factory_;
 
   std::vector<AppId> uninstall_and_replace_;
   gfx::Size minimum_window_size_;
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.cc b/chrome/browser/web_applications/test/fake_data_retriever.cc
index 18f0e59c..8e5d1b2 100644
--- a/chrome/browser/web_applications/test/fake_data_retriever.cc
+++ b/chrome/browser/web_applications/test/fake_data_retriever.cc
@@ -20,9 +20,9 @@
     std::move(destruction_callback_).Run();
 }
 
-void FakeDataRetriever::GetWebApplicationInfo(
+void FakeDataRetriever::GetWebAppInstallInfo(
     content::WebContents* web_contents,
-    GetWebApplicationInfoCallback callback) {
+    GetWebAppInstallInfoCallback callback) {
   DCHECK(web_contents);
 
   completion_callback_ =
@@ -58,13 +58,13 @@
   icons_http_results_.clear();
 }
 
-void FakeDataRetriever::SetRendererWebApplicationInfo(
-    std::unique_ptr<WebApplicationInfo> web_app_info) {
+void FakeDataRetriever::SetRendererWebAppInstallInfo(
+    std::unique_ptr<WebAppInstallInfo> web_app_info) {
   web_app_info_ = std::move(web_app_info);
 }
 
-void FakeDataRetriever::SetEmptyRendererWebApplicationInfo() {
-  SetRendererWebApplicationInfo(std::make_unique<WebApplicationInfo>());
+void FakeDataRetriever::SetEmptyRendererWebAppInstallInfo() {
+  SetRendererWebAppInstallInfo(std::make_unique<WebAppInstallInfo>());
 }
 
 void FakeDataRetriever::SetManifest(blink::mojom::ManifestPtr manifest,
@@ -101,7 +101,7 @@
 
 void FakeDataRetriever::BuildDefaultDataToRetrieve(const GURL& url,
                                                    const GURL& scope) {
-  SetEmptyRendererWebApplicationInfo();
+  SetEmptyRendererWebAppInstallInfo();
 
   auto manifest = blink::mojom::Manifest::New();
   manifest->start_url = url;
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.h b/chrome/browser/web_applications/test/fake_data_retriever.h
index b903e3d..cab1eaf 100644
--- a/chrome/browser/web_applications/test/fake_data_retriever.h
+++ b/chrome/browser/web_applications/test/fake_data_retriever.h
@@ -28,8 +28,8 @@
   ~FakeDataRetriever() override;
 
   // WebAppDataRetriever:
-  void GetWebApplicationInfo(content::WebContents* web_contents,
-                             GetWebApplicationInfoCallback callback) override;
+  void GetWebAppInstallInfo(content::WebContents* web_contents,
+                            GetWebAppInstallInfoCallback callback) override;
   void CheckInstallabilityAndRetrieveManifest(
       content::WebContents* web_contents,
       bool bypass_service_worker_check,
@@ -39,10 +39,10 @@
                 bool skip_page_favicons,
                 GetIconsCallback callback) override;
 
-  // Set info to respond on |GetWebApplicationInfo|.
-  void SetRendererWebApplicationInfo(
-      std::unique_ptr<WebApplicationInfo> web_app_info);
-  void SetEmptyRendererWebApplicationInfo();
+  // Set info to respond on |GetWebAppInstallInfo|.
+  void SetRendererWebAppInstallInfo(
+      std::unique_ptr<WebAppInstallInfo> web_app_info);
+  void SetEmptyRendererWebAppInstallInfo();
   // Set arguments to respond on |CheckInstallabilityAndRetrieveManifest|.
   void SetManifest(blink::mojom::ManifestPtr manifest,
                    bool is_installable,
@@ -63,7 +63,7 @@
 
   void SetDestructionCallback(base::OnceClosure callback);
 
-  WebApplicationInfo& web_app_info() { return *web_app_info_; }
+  WebAppInstallInfo& web_app_info() { return *web_app_info_; }
 
   // Builds minimal data for install to succeed. Data includes: empty renderer
   // info, manifest with |url| and |scope|, installability checked as |true|,
@@ -75,7 +75,7 @@
   void CallCompletionCallback();
 
   base::OnceClosure completion_callback_;
-  std::unique_ptr<WebApplicationInfo> web_app_info_;
+  std::unique_ptr<WebAppInstallInfo> web_app_info_;
 
   blink::mojom::ManifestPtr manifest_;
   GURL manifest_url_;
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.cc b/chrome/browser/web_applications/test/fake_install_finalizer.cc
index 707fe6c..d536b3b 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.cc
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.cc
@@ -32,7 +32,7 @@
 FakeInstallFinalizer::~FakeInstallFinalizer() = default;
 
 void FakeInstallFinalizer::FinalizeInstall(
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     const FinalizeOptions& options,
     InstallFinalizedCallback callback) {
   finalize_options_list_.push_back(options);
@@ -40,9 +40,8 @@
            std::move(callback));
 }
 
-void FakeInstallFinalizer::FinalizeUpdate(
-    const WebApplicationInfo& web_app_info,
-    InstallFinalizedCallback callback) {
+void FakeInstallFinalizer::FinalizeUpdate(const WebAppInstallInfo& web_app_info,
+                                          InstallFinalizedCallback callback) {
   Finalize(web_app_info, InstallResultCode::kSuccessAlreadyInstalled,
            std::move(callback));
 }
@@ -136,7 +135,7 @@
   user_uninstalled_external_apps_.insert(app_id);
 }
 
-void FakeInstallFinalizer::Finalize(const WebApplicationInfo& web_app_info,
+void FakeInstallFinalizer::Finalize(const WebAppInstallInfo& web_app_info,
                                     InstallResultCode code,
                                     InstallFinalizedCallback callback) {
   AppId app_id = GetAppIdForUrl(web_app_info.start_url);
@@ -151,7 +150,7 @@
   }
 
   // Store input data copies for inspecting in tests.
-  web_app_info_copy_ = std::make_unique<WebApplicationInfo>(web_app_info);
+  web_app_info_copy_ = std::make_unique<WebAppInstallInfo>(web_app_info);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), app_id, code));
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.h b/chrome/browser/web_applications/test/fake_install_finalizer.h
index f9d88d20..48ecf76 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.h
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace web_app {
 
@@ -27,10 +27,10 @@
   ~FakeInstallFinalizer() override;
 
   // WebAppInstallFinalizer:
-  void FinalizeInstall(const WebApplicationInfo& web_app_info,
+  void FinalizeInstall(const WebAppInstallInfo& web_app_info,
                        const FinalizeOptions& options,
                        InstallFinalizedCallback callback) override;
-  void FinalizeUpdate(const WebApplicationInfo& web_app_info,
+  void FinalizeUpdate(const WebAppInstallInfo& web_app_info,
                       InstallFinalizedCallback callback) override;
   void UninstallExternalWebApp(
       const AppId& app_id,
@@ -68,7 +68,7 @@
   // simulate that the app was uninstalled previously.
   void SimulateExternalAppUninstalledByUser(const AppId& app_id);
 
-  std::unique_ptr<WebApplicationInfo> web_app_info() {
+  std::unique_ptr<WebAppInstallInfo> web_app_info() {
     return std::move(web_app_info_copy_);
   }
 
@@ -83,11 +83,11 @@
   int num_reparent_tab_calls() { return num_reparent_tab_calls_; }
 
  private:
-  void Finalize(const WebApplicationInfo& web_app_info,
+  void Finalize(const WebAppInstallInfo& web_app_info,
                 InstallResultCode code,
                 InstallFinalizedCallback callback);
 
-  std::unique_ptr<WebApplicationInfo> web_app_info_copy_;
+  std::unique_ptr<WebAppInstallInfo> web_app_info_copy_;
   std::vector<FinalizeOptions> finalize_options_list_;
   std::vector<GURL> uninstall_external_web_app_urls_;
 
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.cc b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
index f964bf26..b25dc8d 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.cc
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
@@ -56,7 +56,7 @@
 void FakeOsIntegrationManager::InstallOsHooks(
     const AppId& app_id,
     InstallOsHooksCallback callback,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     InstallOsHooksOptions options) {
   OsHooksErrors os_hooks_errors;
 
@@ -117,7 +117,7 @@
     const AppId& app_id,
     base::StringPiece old_name,
     FileHandlerUpdateAction file_handlers_need_os_update,
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     UninstallOsHooksCallback callback) {
   if (file_handlers_need_os_update != FileHandlerUpdateAction::kNoUpdate)
     ++num_update_file_handlers_calls_;
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.h b/chrome/browser/web_applications/test/fake_os_integration_manager.h
index 02360b9..e591607 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.h
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.h
@@ -31,7 +31,7 @@
   // OsIntegrationManager:
   void InstallOsHooks(const AppId& app_id,
                       InstallOsHooksCallback callback,
-                      std::unique_ptr<WebApplicationInfo> web_app_info,
+                      std::unique_ptr<WebAppInstallInfo> web_app_info,
                       InstallOsHooksOptions options) override;
   void UninstallOsHooks(const AppId& app_id,
                         const OsHooksOptions& os_hooks,
@@ -41,7 +41,7 @@
   void UpdateOsHooks(const AppId& app_id,
                      base::StringPiece old_name,
                      FileHandlerUpdateAction file_handlers_need_os_update,
-                     const WebApplicationInfo& web_app_info,
+                     const WebAppInstallInfo& web_app_info,
                      UpdateOsHooksCallback callback) override;
 
   size_t num_create_shortcuts_calls() const {
diff --git a/chrome/browser/web_applications/test/mock_os_integration_manager.h b/chrome/browser/web_applications/test/mock_os_integration_manager.h
index 4ee8b98..d66da836 100644
--- a/chrome/browser/web_applications/test/mock_os_integration_manager.h
+++ b/chrome/browser/web_applications/test/mock_os_integration_manager.h
@@ -123,7 +123,7 @@
               (override));
   MOCK_METHOD(void,
               UpdateShortcutsMenu,
-              (const AppId& app_id, const WebApplicationInfo& web_app_info),
+              (const AppId& app_id, const WebAppInstallInfo& web_app_info),
               (override));
   MOCK_METHOD(void,
               UpdateUrlHandlers,
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
index a76515b..5142e9f 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.cc
@@ -218,8 +218,8 @@
   return apps_icon_info;
 }
 
-void AddIconsToWebApplicationInfo(
-    WebApplicationInfo* web_application_info,
+void AddIconsToWebAppInstallInfo(
+    WebAppInstallInfo* web_application_info,
     const GURL& icons_base_url,
     const std::vector<GeneratedIconsInfo>& icons_info) {
   for (const GeneratedIconsInfo& info : icons_info) {
diff --git a/chrome/browser/web_applications/test/web_app_icon_test_utils.h b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
index ec62732..03cdaee6 100644
--- a/chrome/browser/web_applications/test/web_app_icon_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_icon_test_utils.h
@@ -94,8 +94,8 @@
                               IconPurpose purpose,
                               SquareSizePx size_px);
 
-void AddIconsToWebApplicationInfo(
-    WebApplicationInfo* web_application_info,
+void AddIconsToWebAppInstallInfo(
+    WebAppInstallInfo* web_application_info,
     const GURL& icons_base_url,
     const std::vector<GeneratedIconsInfo>& icons_info);
 
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.cc b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
index 3d452d5..25bef7fb 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
@@ -60,7 +60,7 @@
                          const std::string& app_name,
                          const GURL& start_url) {
   const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   web_app_info.start_url = start_url;
   web_app_info.scope = start_url;
@@ -90,12 +90,12 @@
 }
 
 AppId InstallWebApp(Profile* profile,
-                    std::unique_ptr<WebApplicationInfo> web_app_info,
+                    std::unique_ptr<WebAppInstallInfo> web_app_info,
                     bool overwrite_existing_manifest_fields,
                     webapps::WebappInstallSource install_source) {
   // The sync system requires that sync entity name is never empty.
   if (web_app_info->title.empty())
-    web_app_info->title = u"WebApplicationInfo App Name";
+    web_app_info->title = u"WebAppInstallInfo App Name";
 
   AppId app_id;
   base::RunLoop run_loop;
@@ -125,8 +125,8 @@
     const GURL& start_url,
     const std::u16string& app_name,
     const std::vector<apps::UrlHandlerInfo>& url_handlers) {
-  std::unique_ptr<WebApplicationInfo> info =
-      std::make_unique<WebApplicationInfo>();
+  std::unique_ptr<WebAppInstallInfo> info =
+      std::make_unique<WebAppInstallInfo>();
   info->start_url = start_url;
   info->title = app_name;
   info->user_display_mode = DisplayMode::kStandalone;
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.h b/chrome/browser/web_applications/test/web_app_install_test_utils.h
index 8296a7c9..d1cddec 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.h
@@ -45,7 +45,7 @@
 // Synchronous version of WebAppInstallManager::InstallWebAppFromInfo. May be
 // used in unit tests and browser tests.
 AppId InstallWebApp(Profile* profile,
-                    std::unique_ptr<WebApplicationInfo> web_app_info,
+                    std::unique_ptr<WebAppInstallInfo> web_app_info,
                     bool overwrite_existing_manifest_fields = false,
                     webapps::WebappInstallSource install_source =
                         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON);
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc
index 4d796c3..4f102a2 100644
--- a/chrome/browser/web_applications/test/web_app_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -447,7 +447,7 @@
 
 void TestAcceptDialogCallback(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -457,7 +457,7 @@
 
 void TestDeclineDialogCallback(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.h b/chrome/browser/web_applications/test/web_app_test_utils.h
index 9c414281..c62934844 100644
--- a/chrome/browser/web_applications/test/web_app_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_test_utils.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "content/public/browser/service_worker_context.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 class Browser;
 class GURL;
 
@@ -33,13 +33,13 @@
 
 void TestAcceptDialogCallback(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback);
 
 void TestDeclineDialogCallback(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback);
 
diff --git a/chrome/browser/web_applications/web_app_constants.cc b/chrome/browser/web_applications/web_app_constants.cc
index e31e1c6..1efe5b4 100644
--- a/chrome/browser/web_applications/web_app_constants.cc
+++ b/chrome/browser/web_applications/web_app_constants.cc
@@ -87,8 +87,8 @@
       return os << "kSuccessNewInstall";
     case InstallResultCode::kSuccessAlreadyInstalled:
       return os << "kSuccessAlreadyInstalled";
-    case InstallResultCode::kGetWebApplicationInfoFailed:
-      return os << "kGetWebApplicationInfoFailed";
+    case InstallResultCode::kGetWebAppInstallInfoFailed:
+      return os << "kGetWebAppInstallInfoFailed";
     case InstallResultCode::kPreviouslyUninstalled:
       return os << "kPreviouslyUninstalled";
     case InstallResultCode::kWebContentsDestroyed:
diff --git a/chrome/browser/web_applications/web_app_constants.h b/chrome/browser/web_applications/web_app_constants.h
index c7a844f4..642e296 100644
--- a/chrome/browser/web_applications/web_app_constants.h
+++ b/chrome/browser/web_applications/web_app_constants.h
@@ -72,7 +72,7 @@
 
   // Failure category:
   // An inter-process request to blink renderer failed.
-  kGetWebApplicationInfoFailed = 3,
+  kGetWebAppInstallInfoFailed = 3,
   // A user previously uninstalled the app, user doesn't want to see it again.
   kPreviouslyUninstalled = 4,
   // The blink renderer used to install the app was destroyed.
diff --git a/chrome/browser/web_applications/web_app_data_retriever.cc b/chrome/browser/web_applications/web_app_data_retriever.cc
index e681876..48ca382 100644
--- a/chrome/browser/web_applications/web_app_data_retriever.cc
+++ b/chrome/browser/web_applications/web_app_data_retriever.cc
@@ -35,9 +35,9 @@
 
 WebAppDataRetriever::~WebAppDataRetriever() = default;
 
-void WebAppDataRetriever::GetWebApplicationInfo(
+void WebAppDataRetriever::GetWebAppInstallInfo(
     content::WebContents* web_contents,
-    GetWebApplicationInfoCallback callback) {
+    GetWebAppInstallInfoCallback callback) {
   Observe(web_contents);
 
   // Concurrent calls are not allowed.
@@ -55,7 +55,7 @@
 
   // Makes a copy of WebContents fields right after Commit but before a mojo
   // request to the renderer process.
-  preinstalled_web_application_info_ = std::make_unique<WebApplicationInfo>();
+  preinstalled_web_application_info_ = std::make_unique<WebAppInstallInfo>();
   preinstalled_web_application_info_->start_url =
       web_contents->GetLastCommittedURL();
   preinstalled_web_application_info_->title = web_contents->GetTitle();
@@ -154,14 +154,14 @@
   content::WebContents* contents = web_contents();
   Observe(nullptr);
 
-  std::unique_ptr<WebApplicationInfo> info;
+  std::unique_ptr<WebAppInstallInfo> info;
 
   content::NavigationEntry* entry =
       contents->GetController().GetLastCommittedEntry();
 
   if (!entry->IsInitialEntry()) {
     if (entry->GetUniqueID() == last_committed_nav_entry_unique_id) {
-      info = std::make_unique<WebApplicationInfo>(*web_page_metadata);
+      info = std::make_unique<WebAppInstallInfo>(*web_page_metadata);
       if (info->start_url.is_empty())
         info->start_url =
             std::move(preinstalled_web_application_info_->start_url);
diff --git a/chrome/browser/web_applications/web_app_data_retriever.h b/chrome/browser/web_applications/web_app_data_retriever.h
index df3f8d4..1907fb51 100644
--- a/chrome/browser/web_applications/web_app_data_retriever.h
+++ b/chrome/browser/web_applications/web_app_data_retriever.h
@@ -21,7 +21,7 @@
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 
 class GURL;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace content {
 class WebContents;
@@ -39,9 +39,9 @@
 // install an app. Should only be called from the UI thread.
 class WebAppDataRetriever : content::WebContentsObserver {
  public:
-  // Returns nullptr for WebApplicationInfo if error.
-  using GetWebApplicationInfoCallback =
-      base::OnceCallback<void(std::unique_ptr<WebApplicationInfo>)>;
+  // Returns nullptr for WebAppInstallInfo if error.
+  using GetWebAppInstallInfoCallback =
+      base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)>;
   // |is_installable| represents installability check result.
   // If |is_installable| then |valid_manifest_for_web_app| is true.
   // If manifest is present then it is non-empty.
@@ -59,10 +59,10 @@
   WebAppDataRetriever& operator=(const WebAppDataRetriever&) = delete;
   ~WebAppDataRetriever() override;
 
-  // Runs |callback| with the result of retrieving the WebApplicationInfo from
+  // Runs |callback| with the result of retrieving the WebAppInstallInfo from
   // |web_contents|.
-  virtual void GetWebApplicationInfo(content::WebContents* web_contents,
-                                     GetWebApplicationInfoCallback callback);
+  virtual void GetWebAppInstallInfo(content::WebContents* web_contents,
+                                    GetWebAppInstallInfoCallback callback);
 
   // Performs installability check and invokes |callback| with manifest.
   virtual void CheckInstallabilityAndRetrieveManifest(
@@ -96,8 +96,8 @@
   void CallCallbackOnError();
   bool ShouldStopRetrieval() const;
 
-  std::unique_ptr<WebApplicationInfo> preinstalled_web_application_info_;
-  GetWebApplicationInfoCallback get_web_app_info_callback_;
+  std::unique_ptr<WebAppInstallInfo> preinstalled_web_application_info_;
+  GetWebAppInstallInfoCallback get_web_app_info_callback_;
 
   CheckInstallabilityCallback check_installability_callback_;
   GetIconsCallback get_icons_callback_;
diff --git a/chrome/browser/web_applications/web_app_data_retriever_unittest.cc b/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
index ea3a254c..e4c62f1c 100644
--- a/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
+++ b/chrome/browser/web_applications/web_app_data_retriever_unittest.cc
@@ -57,8 +57,8 @@
         std::move(handle)));
   }
 
-  // Set |web_app_info| to respond on |GetWebApplicationInfo|.
-  void SetWebApplicationInfo(const WebApplicationInfo& web_app_info) {
+  // Set |web_app_info| to respond on |GetWebAppInstallInfo|.
+  void SetWebAppInstallInfo(const WebAppInstallInfo& web_app_info) {
     web_app_info_ = web_app_info;
   }
 
@@ -72,13 +72,13 @@
     // Convert more fields as needed.
     DCHECK(web_app_info_.manifest_icons.empty());
     DCHECK(web_app_info_.mobile_capable ==
-           WebApplicationInfo::MOBILE_CAPABLE_UNSPECIFIED);
+           WebAppInstallInfo::MOBILE_CAPABLE_UNSPECIFIED);
 
     std::move(callback).Run(std::move(web_page_metadata));
   }
 
  private:
-  WebApplicationInfo web_app_info_;
+  WebAppInstallInfo web_app_info_;
 
   mojo::AssociatedReceiver<webapps::mojom::WebPageMetadataAgent> receiver_{
       this};
@@ -113,13 +113,13 @@
         web_contents()->GetMainFrame());
   }
 
-  void SetRendererWebApplicationInfo(const WebApplicationInfo& web_app_info) {
-    fake_chrome_render_frame_.SetWebApplicationInfo(web_app_info);
+  void SetRendererWebAppInstallInfo(const WebAppInstallInfo& web_app_info) {
+    fake_chrome_render_frame_.SetWebAppInstallInfo(web_app_info);
   }
 
-  void GetWebApplicationInfoCallback(
+  void GetWebAppInstallInfoCallback(
       base::OnceClosure quit_closure,
-      std::unique_ptr<WebApplicationInfo> web_app_info) {
+      std::unique_ptr<WebAppInstallInfo> web_app_info) {
     web_app_info_ = std::move(web_app_info);
     std::move(quit_closure).Run();
   }
@@ -135,7 +135,7 @@
     return content::WebContentsTester::For(web_contents());
   }
 
-  const std::unique_ptr<WebApplicationInfo>& web_app_info() {
+  const std::unique_ptr<WebAppInstallInfo>& web_app_info() {
     return web_app_info_.value();
   }
 
@@ -143,147 +143,147 @@
 
  private:
   FakeWebPageMetadataAgent fake_chrome_render_frame_;
-  absl::optional<std::unique_ptr<WebApplicationInfo>> web_app_info_;
+  absl::optional<std::unique_ptr<WebAppInstallInfo>> web_app_info_;
   std::vector<apps::IconInfo> icons_;
 };
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_NoEntry) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_NoEntry) {
   SetFakeWebPageMetadataAgent();
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
   EXPECT_EQ(nullptr, web_app_info());
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_AppUrlAbsent) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_AppUrlAbsent) {
   SetFakeWebPageMetadataAgent();
 
   const GURL kFooUrl("https://foo.example");
   web_contents_tester()->NavigateAndCommit(kFooUrl);
 
-  WebApplicationInfo original_web_app_info;
+  WebAppInstallInfo original_web_app_info;
   original_web_app_info.start_url = GURL();
 
-  SetRendererWebApplicationInfo(original_web_app_info);
+  SetRendererWebAppInstallInfo(original_web_app_info);
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
-  // If the WebApplicationInfo has no URL, we fallback to the last committed
+  // If the WebAppInstallInfo has no URL, we fallback to the last committed
   // URL.
   EXPECT_EQ(kFooUrl, web_app_info()->start_url);
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_AppUrlPresent) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_AppUrlPresent) {
   SetFakeWebPageMetadataAgent();
 
   web_contents_tester()->NavigateAndCommit(GURL("https://foo.example"));
 
-  WebApplicationInfo original_web_app_info;
+  WebAppInstallInfo original_web_app_info;
   original_web_app_info.start_url = GURL("https://bar.example");
 
-  SetRendererWebApplicationInfo(original_web_app_info);
+  SetRendererWebAppInstallInfo(original_web_app_info);
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
   EXPECT_EQ(original_web_app_info.start_url, web_app_info()->start_url);
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_TitleAbsentFromRenderer) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_TitleAbsentFromRenderer) {
   SetFakeWebPageMetadataAgent();
 
   web_contents_tester()->NavigateAndCommit(GURL("https://foo.example"));
 
   web_contents_tester()->SetTitle(kFooTitle);
 
-  WebApplicationInfo original_web_app_info;
+  WebAppInstallInfo original_web_app_info;
   original_web_app_info.title = u"";
 
-  SetRendererWebApplicationInfo(original_web_app_info);
+  SetRendererWebAppInstallInfo(original_web_app_info);
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
-  // If the WebApplicationInfo has no title, we fallback to the WebContents
+  // If the WebAppInstallInfo has no title, we fallback to the WebContents
   // title.
   EXPECT_EQ(kFooTitle, web_app_info()->title);
 }
 
 TEST_F(WebAppDataRetrieverTest,
-       GetWebApplicationInfo_TitleAbsentFromWebContents) {
+       GetWebAppInstallInfo_TitleAbsentFromWebContents) {
   SetFakeWebPageMetadataAgent();
 
   web_contents_tester()->NavigateAndCommit(GURL("https://foo.example"));
 
   web_contents_tester()->SetTitle(u"");
 
-  WebApplicationInfo original_web_app_info;
+  WebAppInstallInfo original_web_app_info;
   original_web_app_info.title = u"";
 
-  SetRendererWebApplicationInfo(original_web_app_info);
+  SetRendererWebAppInstallInfo(original_web_app_info);
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
-  // If the WebApplicationInfo has no title and the WebContents has no title, we
+  // If the WebAppInstallInfo has no title and the WebContents has no title, we
   // fallback to start_url.
   EXPECT_EQ(base::UTF8ToUTF16(web_app_info()->start_url.spec()),
             web_app_info()->title);
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_ConnectionError) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_ConnectionError) {
   // Do not set fake WebPageMetadataAgent to simulate connection error.
 
   web_contents_tester()->NavigateAndCommit(GURL("https://foo.example"));
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   run_loop.Run();
 
   EXPECT_EQ(nullptr, web_app_info());
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_WebContentsDestroyed) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_WebContentsDestroyed) {
   SetFakeWebPageMetadataAgent();
 
   web_contents_tester()->NavigateAndCommit(GURL("https://foo.example"));
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   DeleteContents();
   run_loop.Run();
@@ -341,7 +341,7 @@
   run_loop.Run();
 }
 
-TEST_F(WebAppDataRetrieverTest, GetWebApplicationInfo_FrameNavigated) {
+TEST_F(WebAppDataRetrieverTest, GetWebAppInstallInfo_FrameNavigated) {
   SetFakeWebPageMetadataAgent();
 
   web_contents_tester()->SetTitle(kFooTitle);
@@ -351,9 +351,9 @@
 
   base::RunLoop run_loop;
   WebAppDataRetriever retriever;
-  retriever.GetWebApplicationInfo(
+  retriever.GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppDataRetrieverTest::GetWebApplicationInfoCallback,
+      base::BindOnce(&WebAppDataRetrieverTest::GetWebAppInstallInfoCallback,
                      base::Unretained(this), run_loop.QuitClosure()));
   web_contents_tester()->NavigateAndCommit(kFooUrl);
   run_loop.Run();
diff --git a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
index e26b114..b943ef4 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_browsertest.cc
@@ -73,8 +73,8 @@
 
   AppId app_id;
   {
-    std::unique_ptr<WebApplicationInfo> web_application_info =
-        std::make_unique<WebApplicationInfo>();
+    std::unique_ptr<WebAppInstallInfo> web_application_info =
+        std::make_unique<WebAppInstallInfo>();
     web_application_info->start_url = start_url;
     web_application_info->scope = start_url.GetWithoutFilename();
     web_application_info->title = u"App Name";
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 8bf45e4..739b6f9 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -126,7 +126,7 @@
 WebAppInstallFinalizer::~WebAppInstallFinalizer() = default;
 
 void WebAppInstallFinalizer::FinalizeInstall(
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     const FinalizeOptions& options,
     InstallFinalizedCallback callback) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -404,7 +404,7 @@
 }
 
 void WebAppInstallFinalizer::FinalizeUpdate(
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     InstallFinalizedCallback callback) {
   CHECK(started_);
 
@@ -541,7 +541,7 @@
 }
 
 void WebAppInstallFinalizer::SetWebAppManifestFieldsAndWriteData(
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     std::unique_ptr<WebApp> web_app,
     CommitCallback commit_callback) {
   SetWebAppManifestFields(web_app_info, *web_app);
@@ -614,7 +614,7 @@
     std::string old_name,
     bool should_update_os_hooks,
     FileHandlerUpdateAction file_handlers_need_os_update,
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success) {
@@ -653,7 +653,7 @@
 
 FileHandlerUpdateAction WebAppInstallFinalizer::GetFileHandlerUpdateAction(
     const AppId& app_id,
-    const WebApplicationInfo& new_web_app_info) {
+    const WebAppInstallInfo& new_web_app_info) {
   if (!os_integration_manager_->IsFileHandlingAPIAvailable(app_id))
     return FileHandlerUpdateAction::kNoUpdate;
 
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index a6fbbaf..9b4580b 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -39,7 +39,7 @@
 enum class WebAppUninstallJobResult;
 
 // An finalizer for the installation process, represents the last step.
-// Takes WebApplicationInfo as input, writes data to disk (e.g icons, shortcuts)
+// Takes WebAppInstallInfo as input, writes data to disk (e.g icons, shortcuts)
 // and registers an app.
 class WebAppInstallFinalizer {
  public:
@@ -74,7 +74,7 @@
   // All methods below are |virtual| for testing.
 
   // Write the WebApp data to disk and register the app.
-  virtual void FinalizeInstall(const WebApplicationInfo& web_app_info,
+  virtual void FinalizeInstall(const WebAppInstallInfo& web_app_info,
                                const FinalizeOptions& options,
                                InstallFinalizedCallback callback);
 
@@ -82,7 +82,7 @@
   // TODO(https://crbug.com/1196051): Chrome fails to update the manifest
   // if the app window needing update closes at the same time as Chrome.
   // Therefore, the manifest may not always update as expected.
-  virtual void FinalizeUpdate(const WebApplicationInfo& web_app_info,
+  virtual void FinalizeUpdate(const WebAppInstallInfo& web_app_info,
                               InstallFinalizedCallback callback);
 
   // Removes |webapp_uninstall_source| from |app_id|. If no more interested
@@ -170,7 +170,7 @@
                                   OsHooksErrors os_hooks_errors);
 
   void SetWebAppManifestFieldsAndWriteData(
-      const WebApplicationInfo& web_app_info,
+      const WebAppInstallInfo& web_app_info,
       std::unique_ptr<WebApp> web_app,
       CommitCallback commit_callback);
 
@@ -191,7 +191,7 @@
       std::string old_name,
       bool should_update_os_hooks,
       FileHandlerUpdateAction file_handlers_need_os_update,
-      const WebApplicationInfo& web_app_info,
+      const WebAppInstallInfo& web_app_info,
       bool success);
 
   void OnUpdateHooksFinished(InstallFinalizedCallback callback,
@@ -205,7 +205,7 @@
   // optimizations?
   FileHandlerUpdateAction GetFileHandlerUpdateAction(
       const AppId& app_id,
-      const WebApplicationInfo& new_web_app_info);
+      const WebAppInstallInfo& new_web_app_info);
 
   raw_ptr<WebAppRegistrar> registrar_ = nullptr;
   raw_ptr<WebAppSyncBridge> sync_bridge_ = nullptr;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
index 64dab5c1..4c76e3f2 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
@@ -78,7 +78,7 @@
 
   // Synchronous version of FinalizeInstall.
   FinalizeInstallResult AwaitFinalizeInstall(
-      WebApplicationInfo info,
+      WebAppInstallInfo info,
       WebAppInstallFinalizer::FinalizeOptions options) {
     FinalizeInstallResult result{};
     base::RunLoop run_loop;
@@ -108,7 +108,7 @@
 };
 
 TEST_F(WebAppInstallFinalizerUnitTest, BasicInstallSucceeds) {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL("https://foo.example");
   info->title = u"Foo Title";
   WebAppInstallFinalizer::FinalizeOptions options;
@@ -122,11 +122,11 @@
 }
 
 TEST_F(WebAppInstallFinalizerUnitTest, ConcurrentInstallSucceeds) {
-  auto info1 = std::make_unique<WebApplicationInfo>();
+  auto info1 = std::make_unique<WebAppInstallInfo>();
   info1->start_url = GURL("https://foo1.example");
   info1->title = u"Foo1 Title";
 
-  auto info2 = std::make_unique<WebApplicationInfo>();
+  auto info2 = std::make_unique<WebAppInstallInfo>();
   info2->start_url = GURL("https://foo2.example");
   info2->title = u"Foo2 Title";
 
@@ -176,7 +176,7 @@
 }
 
 TEST_F(WebAppInstallFinalizerUnitTest, InstallStoresLatestWebAppInstallSource) {
-  auto info = std::make_unique<WebApplicationInfo>();
+  auto info = std::make_unique<WebAppInstallInfo>();
   info->start_url = GURL("https://foo.example");
   info->title = u"Foo Title";
   WebAppInstallFinalizer::FinalizeOptions options;
diff --git a/chrome/browser/web_applications/web_app_install_manager.cc b/chrome/browser/web_applications/web_app_install_manager.cc
index c5dc6b5..3eef2bdb 100644
--- a/chrome/browser/web_applications/web_app_install_manager.cc
+++ b/chrome/browser/web_applications/web_app_install_manager.cc
@@ -29,7 +29,6 @@
 #include "components/webapps/browser/installable/installable_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "url/url_constants.h"
 
 namespace web_app {
 
@@ -198,7 +197,7 @@
 }
 
 void WebAppInstallManager::InstallWebAppFromInfo(
-    std::unique_ptr<WebApplicationInfo> web_application_info,
+    std::unique_ptr<WebAppInstallInfo> web_application_info,
     bool overwrite_existing_manifest_fields,
     ForInstallableSite for_installable_site,
     webapps::WebappInstallSource install_source,
@@ -209,7 +208,7 @@
 }
 
 void WebAppInstallManager::InstallWebAppFromInfo(
-    std::unique_ptr<WebApplicationInfo> web_application_info,
+    std::unique_ptr<WebAppInstallInfo> web_application_info,
     bool overwrite_existing_manifest_fields,
     ForInstallableSite for_installable_site,
     const absl::optional<WebAppInstallParams>& install_params,
@@ -258,7 +257,7 @@
 
 void WebAppInstallManager::EnqueueInstallAppFromSync(
     const AppId& sync_app_id,
-    std::unique_ptr<WebApplicationInfo> web_application_info,
+    std::unique_ptr<WebAppInstallInfo> web_application_info,
     OnceInstallCallback callback) {
   DCHECK(started_);
 #if defined(OS_CHROMEOS)
@@ -352,7 +351,7 @@
   for (WebApp* web_app : web_apps) {
     DCHECK(web_app->is_from_sync_and_pending_installation());
 
-    auto web_application_info = std::make_unique<WebApplicationInfo>();
+    auto web_application_info = std::make_unique<WebAppInstallInfo>();
     web_application_info->manifest_id = web_app->manifest_id();
     web_application_info->start_url = web_app->start_url();
     web_application_info->title =
@@ -400,7 +399,7 @@
 void WebAppInstallManager::
     LoadAndInstallWebAppFromManifestWithFallbackCompleted_ForAppSync(
         const AppId& sync_app_id,
-        std::unique_ptr<WebApplicationInfo> web_application_info,
+        std::unique_ptr<WebAppInstallInfo> web_application_info,
         OnceInstallCallback callback,
         const AppId& web_app_id,
         InstallResultCode code) {
@@ -471,9 +470,8 @@
   current_queued_task_ = pending_task.task;
 
   // Load about:blank to ensure ready and clean up any left over state.
-  url_loader_->LoadUrl(
-      GURL(url::kAboutBlankURL), web_contents_.get(),
-      WebAppUrlLoader::UrlComparison::kExact,
+  url_loader_->PrepareForLoad(
+      web_contents_.get(),
       base::BindOnce(&WebAppInstallManager::OnWebContentsReadyRunTask,
                      GetWeakPtr(), std::move(pending_task)));
 }
diff --git a/chrome/browser/web_applications/web_app_install_manager.h b/chrome/browser/web_applications/web_app_install_manager.h
index 5d3e100..637369cb 100644
--- a/chrome/browser/web_applications/web_app_install_manager.h
+++ b/chrome/browser/web_applications/web_app_install_manager.h
@@ -104,14 +104,14 @@
   // If `web_application_info` contains data freshly fetched from the web app's
   // site then `overwrite_existing_manifest_fields` should be true.
   void InstallWebAppFromInfo(
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       bool overwrite_existing_manifest_fields,
       ForInstallableSite for_installable_site,
       webapps::WebappInstallSource install_source,
       OnceInstallCallback callback);
 
   void InstallWebAppFromInfo(
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       bool overwrite_existing_manifest_fields,
       ForInstallableSite for_installable_site,
       const absl::optional<WebAppInstallParams>& install_params,
@@ -157,14 +157,14 @@
 
   void EnqueueInstallAppFromSync(
       const AppId& sync_app_id,
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       OnceInstallCallback callback);
   bool IsAppIdAlreadyEnqueued(const AppId& app_id) const;
 
   // On failure will attempt a fallback install only loading icon URLs.
   void LoadAndInstallWebAppFromManifestWithFallbackCompleted_ForAppSync(
       const AppId& sync_app_id,
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       OnceInstallCallback callback,
       const AppId& web_app_id,
       InstallResultCode code);
diff --git a/chrome/browser/web_applications/web_app_install_manager_unittest.cc b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
index 3312baf..5fee589f 100644
--- a/chrome/browser/web_applications/web_app_install_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_manager_unittest.cc
@@ -63,9 +63,9 @@
 constexpr SquareSizePx kDefaultImageSize = 100;
 constexpr char kIconUrl[] = "https://example.com/app.ico";
 
-std::unique_ptr<WebApplicationInfo> ConvertWebAppToRendererWebApplicationInfo(
+std::unique_ptr<WebAppInstallInfo> ConvertWebAppToRendererWebAppInstallInfo(
     const WebApp& app) {
-  auto web_application_info = std::make_unique<WebApplicationInfo>();
+  auto web_application_info = std::make_unique<WebAppInstallInfo>();
   // Most fields are expected to be populated by a manifest data in a subsequent
   // override install process data flow. TODO(loyso): Make it more robust.
   web_application_info->description = base::UTF8ToUTF16(app.description());
@@ -120,8 +120,8 @@
     const WebApp& app) {
   auto data_retriever = std::make_unique<FakeDataRetriever>();
 
-  data_retriever->SetRendererWebApplicationInfo(
-      ConvertWebAppToRendererWebApplicationInfo(app));
+  data_retriever->SetRendererWebAppInstallInfo(
+      ConvertWebAppToRendererWebAppInstallInfo(app));
   data_retriever->SetManifest(ConvertWebAppToManifest(app),
                               /*is_installable=*/true);
   data_retriever->SetIcons(ConvertWebAppIconsToIconsMap(app));
@@ -339,7 +339,7 @@
   }
 
   InstallResult InstallWebAppFromInfo(
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       bool overwrite_existing_manifest_fields,
       webapps::WebappInstallSource install_source) {
     InstallResult result;
@@ -976,7 +976,7 @@
   const AppId expected_app_id =
       GenerateAppId(/*manifest_id=*/absl::nullopt, url);
 
-  auto server_web_app_info = std::make_unique<WebApplicationInfo>();
+  auto server_web_app_info = std::make_unique<WebAppInstallInfo>();
   server_web_app_info->start_url = url;
   server_web_app_info->scope = url;
   server_web_app_info->title = u"Test web app";
@@ -1088,7 +1088,7 @@
   const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, start_url);
 
   // Reproduces `ApkWebAppInstaller` install parameters.
-  auto apk_web_application_info = std::make_unique<WebApplicationInfo>();
+  auto apk_web_application_info = std::make_unique<WebAppInstallInfo>();
   apk_web_application_info->start_url = start_url;
   apk_web_application_info->scope = GURL("https://example.com/apk_scope");
   apk_web_application_info->title = u"Name from APK";
diff --git a/chrome/browser/web_applications/web_app_install_params.h b/chrome/browser/web_applications/web_app_install_params.h
index 62af0d9..be356982 100644
--- a/chrome/browser/web_applications/web_app_install_params.h
+++ b/chrome/browser/web_applications/web_app_install_params.h
@@ -17,7 +17,7 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace content {
 class WebContents;
@@ -35,13 +35,13 @@
 // web app.
 using WebAppInstallationAcceptanceCallback =
     base::OnceCallback<void(bool user_accepted,
-                            std::unique_ptr<WebApplicationInfo>)>;
+                            std::unique_ptr<WebAppInstallInfo>)>;
 
 // Callback to show the WebApp installation confirmation bubble in UI.
-// |web_app_info| is the WebApplicationInfo to be installed.
+// |web_app_info| is the WebAppInstallInfo to be installed.
 using WebAppInstallDialogCallback = base::OnceCallback<void(
     content::WebContents* initiator_web_contents,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     WebAppInstallationAcceptanceCallback acceptance_callback)>;
 
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc
index ae5c9004..e9350e8 100644
--- a/chrome/browser/web_applications/web_app_install_task.cc
+++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -173,10 +173,10 @@
   install_callback_ = std::move(install_callback);
   install_source_ = install_source;
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
 
   if (install_params_)
-    ApplyParamsToWebApplicationInfo(*install_params_, *web_app_info);
+    ApplyParamsToWebAppInstallInfo(*install_params_, *web_app_info);
 
   data_retriever_->CheckInstallabilityAndRetrieveManifest(
       web_contents(), bypass_service_worker_check,
@@ -200,10 +200,9 @@
   install_callback_ = std::move(install_callback);
   install_source_ = install_source;
 
-  data_retriever_->GetWebApplicationInfo(
-      web_contents(),
-      base::BindOnce(&WebAppInstallTask::OnGetWebApplicationInfo, GetWeakPtr(),
-                     force_shortcut_app));
+  data_retriever_->GetWebAppInstallInfo(
+      web_contents(), base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo,
+                                     GetWeakPtr(), force_shortcut_app));
 }
 
 void WebAppInstallTask::LoadAndInstallWebAppFromManifestWithFallback(
@@ -227,7 +226,7 @@
   url_loader->LoadUrl(
       launch_url, contents,
       WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
-      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebApplicationInfo,
+      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo,
                      GetWeakPtr(), launch_url));
 }
 
@@ -251,7 +250,7 @@
   url_loader->LoadUrl(
       install_url, contents,
       WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
-      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebApplicationInfo,
+      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo,
                      GetWeakPtr(), install_url));
 }
 
@@ -279,7 +278,7 @@
 }
 
 void WebAppInstallTask::InstallWebAppFromInfo(
-    std::unique_ptr<WebApplicationInfo> web_application_info,
+    std::unique_ptr<WebAppInstallInfo> web_application_info,
     bool overwrite_existing_manifest_fields,
     ForInstallableSite for_installable_site,
     webapps::WebappInstallSource install_source,
@@ -291,7 +290,7 @@
   // No IconsMap to populate shortcut item icons from.
 
   if (install_params_)
-    ApplyParamsToWebApplicationInfo(*install_params_, *web_application_info);
+    ApplyParamsToWebAppInstallInfo(*install_params_, *web_application_info);
 
   install_source_ = install_source;
   background_installation_ = true;
@@ -324,16 +323,16 @@
   install_source_ = install_source;
   background_installation_ = true;
 
-  data_retriever_->GetWebApplicationInfo(
+  data_retriever_->GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppInstallTask::OnGetWebApplicationInfo, GetWeakPtr(),
+      base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo, GetWeakPtr(),
                      /*force_shortcut_app=*/false));
 }
 
-void WebAppInstallTask::LoadAndRetrieveWebApplicationInfoWithIcons(
+void WebAppInstallTask::LoadAndRetrieveWebAppInstallInfoWithIcons(
     const GURL& start_url,
     WebAppUrlLoader* url_loader,
-    RetrieveWebApplicationInfoWithIconsCallback callback) {
+    RetrieveWebAppInstallInfoWithIconsCallback callback) {
   CheckInstallPreconditions();
 
   retrieve_info_callback_ = std::move(callback);
@@ -347,7 +346,7 @@
   url_loader->LoadUrl(
       start_url, web_contents(),
       WebAppUrlLoader::UrlComparison::kIgnoreQueryParamsAndRef,
-      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebApplicationInfo,
+      base::BindOnce(&WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo,
                      GetWeakPtr(), start_url));
 }
 
@@ -430,7 +429,7 @@
   return !web_contents() || web_contents()->IsBeingDestroyed();
 }
 
-void WebAppInstallTask::OnWebAppUrlLoadedGetWebApplicationInfo(
+void WebAppInstallTask::OnWebAppUrlLoadedGetWebAppInstallInfo(
     const GURL& url_to_load,
     WebAppUrlLoader::Result result) {
   if (ShouldStopInstall())
@@ -454,9 +453,9 @@
     return;
   }
 
-  data_retriever_->GetWebApplicationInfo(
+  data_retriever_->GetWebAppInstallInfo(
       web_contents(),
-      base::BindOnce(&WebAppInstallTask::OnGetWebApplicationInfo, GetWeakPtr(),
+      base::BindOnce(&WebAppInstallTask::OnGetWebAppInstallInfo, GetWeakPtr(),
                      /*force_shortcut_app*/ false));
 }
 
@@ -509,16 +508,16 @@
   }
 }
 
-void WebAppInstallTask::OnGetWebApplicationInfo(
+void WebAppInstallTask::OnGetWebAppInstallInfo(
     bool force_shortcut_app,
-    std::unique_ptr<WebApplicationInfo> web_app_info) {
+    std::unique_ptr<WebAppInstallInfo> web_app_info) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (ShouldStopInstall())
     return;
 
   if (!web_app_info) {
     CallInstallCallback(AppId(),
-                        InstallResultCode::kGetWebApplicationInfoFailed);
+                        InstallResultCode::kGetWebAppInstallInfoFailed);
     return;
   }
 
@@ -534,7 +533,7 @@
     if (install_params_->fallback_app_name.has_value())
       web_app_info->title = install_params_->fallback_app_name.value();
 
-    ApplyParamsToWebApplicationInfo(*install_params_, *web_app_info);
+    ApplyParamsToWebAppInstallInfo(*install_params_, *web_app_info);
   }
 
   data_retriever_->CheckInstallabilityAndRetrieveManifest(
@@ -544,9 +543,9 @@
                      force_shortcut_app));
 }
 
-void WebAppInstallTask::ApplyParamsToWebApplicationInfo(
+void WebAppInstallTask::ApplyParamsToWebAppInstallInfo(
     const WebAppInstallParams& install_params,
-    WebApplicationInfo& web_app_info) {
+    WebAppInstallInfo& web_app_info) {
   if (install_params.user_display_mode != DisplayMode::kUndefined)
     web_app_info.user_display_mode = install_params.user_display_mode;
 
@@ -567,7 +566,7 @@
 }
 
 void WebAppInstallTask::OnDidPerformInstallableCheck(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     bool force_shortcut_app,
     blink::mojom::ManifestPtr opt_manifest,
     const GURL& manifest_url,
@@ -638,7 +637,7 @@
 
 void WebAppInstallTask::CheckForPlayStoreIntentOrGetIcons(
     blink::mojom::ManifestPtr opt_manifest,
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     std::vector<GURL> icon_urls,
     ForInstallableSite for_installable_site,
     bool skip_page_favicons) {
@@ -697,7 +696,7 @@
 }
 
 void WebAppInstallTask::OnDidCheckForIntentToPlayStore(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     std::vector<GURL> icon_urls,
     ForInstallableSite for_installable_site,
     bool skip_page_favicons,
@@ -728,7 +727,7 @@
 
 void WebAppInstallTask::InstallWebAppFromInfoRetrieveIcons(
     content::WebContents* web_contents,
-    std::unique_ptr<WebApplicationInfo> web_application_info,
+    std::unique_ptr<WebAppInstallInfo> web_application_info,
     WebAppInstallFinalizer::FinalizeOptions finalize_options,
     OnceInstallCallback callback) {
   CheckInstallPreconditions();
@@ -753,7 +752,7 @@
 }
 
 void WebAppInstallTask::OnIconsRetrieved(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     WebAppInstallFinalizer::FinalizeOptions finalize_options,
     IconsDownloadedResult result,
     IconsMap icons_map,
@@ -778,7 +777,7 @@
 }
 
 void WebAppInstallTask::OnIconsRetrievedShowDialog(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     ForInstallableSite for_installable_site,
     IconsDownloadedResult result,
     IconsMap icons_map,
@@ -811,7 +810,7 @@
 void WebAppInstallTask::OnDialogCompleted(
     ForInstallableSite for_installable_site,
     bool user_accepted,
-    std::unique_ptr<WebApplicationInfo> web_app_info) {
+    std::unique_ptr<WebAppInstallInfo> web_app_info) {
   if (ShouldStopInstall())
     return;
 
@@ -826,7 +825,7 @@
     return;
   }
 
-  WebApplicationInfo web_app_info_copy = *web_app_info;
+  WebAppInstallInfo web_app_info_copy = *web_app_info;
 
   // This metric is recorded regardless of the installation result.
   RecordInstallEvent();
@@ -867,7 +866,7 @@
 }
 
 void WebAppInstallTask::OnInstallFinalizedCreateShortcuts(
-    std::unique_ptr<WebApplicationInfo> web_app_info,
+    std::unique_ptr<WebAppInstallInfo> web_app_info,
     const AppId& app_id,
     InstallResultCode code) {
   if (ShouldStopInstall())
@@ -993,8 +992,6 @@
   if (!error_dict_ || !error_dict_->DictEmpty())
     return;
 
-  // `install_source_` is kNoInstallSource for `UpdateWebAppFromInfo` and
-  // `OnIconsRetrievedFinalizeUpdate`.
   error_dict_->SetStringKey("!url", url);
   error_dict_->SetIntKey("install_source", static_cast<int>(install_source_));
   error_dict_->SetBoolKey("background_installation", background_installation_);
@@ -1045,7 +1042,7 @@
 }
 
 void WebAppInstallTask::LogDownloadedIconsErrors(
-    const WebApplicationInfo& web_app_info,
+    const WebAppInstallInfo& web_app_info,
     IconsDownloadedResult icons_downloaded_result,
     const IconsMap& icons_map,
     const DownloadedIconsHttpResults& icons_http_results) {
diff --git a/chrome/browser/web_applications/web_app_install_task.h b/chrome/browser/web_applications/web_app_install_task.h
index 6b58969..b7dd9da3 100644
--- a/chrome/browser/web_applications/web_app_install_task.h
+++ b/chrome/browser/web_applications/web_app_install_task.h
@@ -27,7 +27,7 @@
 
 class GURL;
 class Profile;
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace content {
 class WebContents;
@@ -46,8 +46,8 @@
 // WebAppInstallTask is an implementation detail of WebAppInstallManager.
 class WebAppInstallTask : content::WebContentsObserver {
  public:
-  using RetrieveWebApplicationInfoWithIconsCallback =
-      base::OnceCallback<void(std::unique_ptr<WebApplicationInfo>)>;
+  using RetrieveWebAppInstallInfoWithIconsCallback =
+      base::OnceCallback<void(std::unique_ptr<WebAppInstallInfo>)>;
 
   WebAppInstallTask(Profile* profile,
                     OsIntegrationManager* os_integration_manager,
@@ -119,7 +119,7 @@
   // entire web app installation data.
   void InstallWebAppFromInfoRetrieveIcons(
       content::WebContents* web_contents,
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       WebAppInstallFinalizer::FinalizeOptions finalize_options,
       OnceInstallCallback callback);
 
@@ -127,7 +127,7 @@
   // |web_application_info| which holds all the data needed for installation.
   // WebAppInstallManager doesn't fetch a manifest.
   void InstallWebAppFromInfo(
-      std::unique_ptr<WebApplicationInfo> web_application_info,
+      std::unique_ptr<WebAppInstallInfo> web_application_info,
       bool overwrite_existing_manifest_fields,
       ForInstallableSite for_installable_site,
       webapps::WebappInstallSource install_source,
@@ -142,12 +142,12 @@
                                webapps::WebappInstallSource install_source,
                                OnceInstallCallback callback);
 
-  // Obtains WebApplicationInfo about web app located at |start_url|, fallbacks
+  // Obtains WebAppInstallInfo about web app located at |start_url|, fallbacks
   // to title/favicon if manifest is not present.
-  void LoadAndRetrieveWebApplicationInfoWithIcons(
+  void LoadAndRetrieveWebAppInstallInfoWithIcons(
       const GURL& start_url,
       WebAppUrlLoader* url_loader,
-      RetrieveWebApplicationInfoWithIconsCallback callback);
+      RetrieveWebAppInstallInfoWithIconsCallback callback);
 
   static std::unique_ptr<content::WebContents> CreateWebContents(
       Profile* profile);
@@ -184,8 +184,8 @@
   // install_callback_.
   bool ShouldStopInstall() const;
 
-  void OnWebAppUrlLoadedGetWebApplicationInfo(const GURL& url_to_load,
-                                              WebAppUrlLoader::Result result);
+  void OnWebAppUrlLoadedGetWebAppInstallInfo(const GURL& url_to_load,
+                                             WebAppUrlLoader::Result result);
 
   void OnWebAppUrlLoadedCheckAndRetrieveManifest(
       const GURL& url_to_load,
@@ -196,18 +196,16 @@
                                      bool valid_manifest_for_web_app,
                                      bool is_installable);
 
-  void OnGetWebApplicationInfo(
-      bool force_shortcut_app,
-      std::unique_ptr<WebApplicationInfo> web_app_info);
+  void OnGetWebAppInstallInfo(bool force_shortcut_app,
+                              std::unique_ptr<WebAppInstallInfo> web_app_info);
 
   // Makes amendments to |web_app_info| based on the options set in
   // |install_params|.
-  void ApplyParamsToWebApplicationInfo(
-      const WebAppInstallParams& install_params,
-      WebApplicationInfo& web_app_info);
+  void ApplyParamsToWebAppInstallInfo(const WebAppInstallParams& install_params,
+                                      WebAppInstallInfo& web_app_info);
 
   void OnDidPerformInstallableCheck(
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       bool force_shortcut_app,
       blink::mojom::ManifestPtr opt_manifest,
       const GURL& manifest_url,
@@ -220,7 +218,7 @@
   // check if it cannot be made.
   void CheckForPlayStoreIntentOrGetIcons(
       blink::mojom::ManifestPtr opt_manifest,
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       std::vector<GURL> icon_urls,
       ForInstallableSite for_installable_site,
       bool skip_page_favicons);
@@ -228,7 +226,7 @@
   // Called when the asynchronous check for whether an intent to the Play Store
   // should be made returns.
   void OnDidCheckForIntentToPlayStore(
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       std::vector<GURL> icon_urls,
       ForInstallableSite for_installable_site,
       bool skip_page_favicons,
@@ -236,23 +234,23 @@
       bool should_intent_to_store);
 
   void OnIconsRetrieved(
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       WebAppInstallFinalizer::FinalizeOptions finalize_options,
       IconsDownloadedResult result,
       IconsMap icons_map,
       DownloadedIconsHttpResults icons_http_results);
   void OnIconsRetrievedShowDialog(
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       ForInstallableSite for_installable_site,
       IconsDownloadedResult result,
       IconsMap icons_map,
       DownloadedIconsHttpResults icons_http_results);
   void OnDialogCompleted(ForInstallableSite for_installable_site,
                          bool user_accepted,
-                         std::unique_ptr<WebApplicationInfo> web_app_info);
+                         std::unique_ptr<WebAppInstallInfo> web_app_info);
   void OnInstallFinalized(const AppId& app_id, InstallResultCode code);
   void OnInstallFinalizedCreateShortcuts(
-      std::unique_ptr<WebApplicationInfo> web_app_info,
+      std::unique_ptr<WebAppInstallInfo> web_app_info,
       const AppId& app_id,
       InstallResultCode code);
   void OnOsHooksCreated(DisplayMode user_display_mode,
@@ -275,7 +273,7 @@
                              const std::string& url,
                              const AppId& app_id);
   void LogDownloadedIconsErrors(
-      const WebApplicationInfo& web_app_info,
+      const WebAppInstallInfo& web_app_info,
       IconsDownloadedResult icons_downloaded_result,
       const IconsMap& icons_map,
       const DownloadedIconsHttpResults& icons_http_results);
@@ -284,13 +282,13 @@
   // methods.
   bool initiated_ = false;
 
-  // Whether we should just obtain WebApplicationInfo instead of the actual
+  // Whether we should just obtain WebAppInstallInfo instead of the actual
   // installation.
   bool only_retrieve_web_application_info_ = false;
 
   WebAppInstallDialogCallback dialog_callback_;
   OnceInstallCallback install_callback_;
-  RetrieveWebApplicationInfoWithIconsCallback retrieve_info_callback_;
+  RetrieveWebAppInstallInfoWithIconsCallback retrieve_info_callback_;
   absl::optional<WebAppInstallParams> install_params_;
   absl::optional<AppId> expected_app_id_;
   bool background_installation_ = false;
@@ -302,7 +300,7 @@
   webapps::WebappInstallSource install_source_ = kNoInstallSource;
 
   std::unique_ptr<WebAppDataRetriever> data_retriever_;
-  std::unique_ptr<WebApplicationInfo> web_application_info_;
+  std::unique_ptr<WebAppInstallInfo> web_application_info_;
   std::unique_ptr<content::WebContents> web_contents_;
   content::WebContents* installing_web_contents_ = nullptr;
 
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index 8ab09bc6..1c7a7c3 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -164,7 +164,7 @@
                              const GURL& scope,
                              absl::optional<SkColor> theme_color,
                              DisplayMode user_display_mode) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
 
     web_app_info->start_url = url;
     web_app_info->title = base::UTF8ToUTF16(name);
@@ -173,7 +173,7 @@
     web_app_info->theme_color = theme_color;
     web_app_info->user_display_mode = user_display_mode;
 
-    data_retriever_->SetRendererWebApplicationInfo(std::move(web_app_info));
+    data_retriever_->SetRendererWebAppInstallInfo(std::move(web_app_info));
   }
 
   void CreateRendererAppInfo(const GURL& url,
@@ -211,9 +211,9 @@
   void CreateDataToRetrieve(const GURL& url, DisplayMode user_display_mode) {
     DCHECK(data_retriever_);
 
-    auto renderer_web_app_info = std::make_unique<WebApplicationInfo>();
+    auto renderer_web_app_info = std::make_unique<WebAppInstallInfo>();
     renderer_web_app_info->user_display_mode = user_display_mode;
-    data_retriever_->SetRendererWebApplicationInfo(
+    data_retriever_->SetRendererWebAppInstallInfo(
         std::move(renderer_web_app_info));
 
     auto manifest = blink::mojom::Manifest::New();
@@ -289,14 +289,14 @@
     return result;
   }
 
-  std::unique_ptr<WebApplicationInfo>
-  LoadAndRetrieveWebApplicationInfoWithIcons(const GURL& url) {
-    std::unique_ptr<WebApplicationInfo> result;
+  std::unique_ptr<WebAppInstallInfo> LoadAndRetrieveWebAppInstallInfoWithIcons(
+      const GURL& url) {
+    std::unique_ptr<WebAppInstallInfo> result;
     base::RunLoop run_loop;
-    install_task_->LoadAndRetrieveWebApplicationInfoWithIcons(
+    install_task_->LoadAndRetrieveWebAppInstallInfoWithIcons(
         url, &url_loader(),
         base::BindLambdaForTesting(
-            [&](std::unique_ptr<WebApplicationInfo> web_app_info) {
+            [&](std::unique_ptr<WebAppInstallInfo> web_app_info) {
               result = std::move(web_app_info);
               run_loop.Quit();
             }));
@@ -398,7 +398,7 @@
                              absl::optional<SkColor> theme_color,
                              DisplayMode user_display_mode,
                              bool run_on_os_login) {
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
 
     web_app_info->start_url = url;
     web_app_info->title = base::UTF8ToUTF16(name);
@@ -408,7 +408,7 @@
     web_app_info->user_display_mode = user_display_mode;
     web_app_info->run_on_os_login = run_on_os_login;
 
-    data_retriever_->SetRendererWebApplicationInfo(std::move(web_app_info));
+    data_retriever_->SetRendererWebAppInstallInfo(std::move(web_app_info));
   }
 
  private:
@@ -514,7 +514,7 @@
   EXPECT_TRUE(callback_called);
 }
 
-TEST_F(WebAppInstallTaskTest, GetWebApplicationInfoFailed) {
+TEST_F(WebAppInstallTaskTest, GetWebAppInstallInfoFailed) {
   // data_retriever_ with empty info means an error.
 
   base::RunLoop run_loop;
@@ -527,7 +527,7 @@
       base::BindOnce(test::TestAcceptDialogCallback),
       base::BindLambdaForTesting(
           [&](const AppId& installed_app_id, InstallResultCode code) {
-            EXPECT_EQ(InstallResultCode::kGetWebApplicationInfoFailed, code);
+            EXPECT_EQ(InstallResultCode::kGetWebAppInstallInfoFailed, code);
             EXPECT_EQ(AppId(), installed_app_id);
             callback_called = true;
             run_loop.Quit();
@@ -676,7 +676,7 @@
 
   InstallWebAppFromManifestWithFallback();
 
-  std::unique_ptr<WebApplicationInfo> web_app_info =
+  std::unique_ptr<WebAppInstallInfo> web_app_info =
       fake_install_finalizer().web_app_info();
 
   // Make sure that icons have been generated for all sub sizes.
@@ -716,7 +716,7 @@
 
   InstallWebAppFromManifestWithFallback();
 
-  std::unique_ptr<WebApplicationInfo> web_app_info =
+  std::unique_ptr<WebAppInstallInfo> web_app_info =
       fake_install_finalizer().web_app_info();
 
   // Make sure that icons have been generated for all sizes.
@@ -758,7 +758,7 @@
 
   InstallWebAppFromManifestWithFallback();
 
-  std::unique_ptr<WebApplicationInfo> web_app_info =
+  std::unique_ptr<WebAppInstallInfo> web_app_info =
       fake_install_finalizer().web_app_info();
   EXPECT_TRUE(ContainsOneIconOfEachSize(web_app_info->icon_bitmaps.any));
   EXPECT_TRUE(web_app_info->manifest_icons.empty());
@@ -829,7 +829,7 @@
       }
     }
 
-    data_retriever().SetEmptyRendererWebApplicationInfo();
+    data_retriever().SetEmptyRendererWebAppInstallInfo();
     data_retriever().SetManifest(std::move(manifest), /*is_installable=*/true);
     data_retriever().SetIcons(std::move(icons_map));
   }
@@ -1036,7 +1036,7 @@
   const GURL url = GURL("https://example.com/path");
   const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = url;
   web_app_info->user_display_mode = DisplayMode::kStandalone;
   web_app_info->title = u"App Name";
@@ -1051,7 +1051,7 @@
             EXPECT_EQ(InstallResultCode::kSuccessNewInstall, code);
             EXPECT_EQ(app_id, installed_app_id);
 
-            std::unique_ptr<WebApplicationInfo> final_web_app_info =
+            std::unique_ptr<WebAppInstallInfo> final_web_app_info =
                 fake_install_finalizer().web_app_info();
             EXPECT_EQ(final_web_app_info->user_display_mode,
                       DisplayMode::kStandalone);
@@ -1065,7 +1065,7 @@
 TEST_F(WebAppInstallTaskTest, InstallWebAppFromInfo_GenerateIcons) {
   SetInstallFinalizerForTesting();
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   web_app_info->start_url = GURL("https://example.com/path");
   web_app_info->user_display_mode = DisplayMode::kBrowser;
   web_app_info->title = u"App Name";
@@ -1081,7 +1081,7 @@
       ForInstallableSite::kYes, webapps::WebappInstallSource::ARC,
       base::BindLambdaForTesting([&](const AppId& installed_app_id,
                                      InstallResultCode code) {
-        std::unique_ptr<WebApplicationInfo> final_web_app_info =
+        std::unique_ptr<WebAppInstallInfo> final_web_app_info =
             fake_install_finalizer().web_app_info();
 
         // Make sure that icons have been generated for all sub sizes.
@@ -1119,7 +1119,7 @@
                                      InstallResultCode code) {
         EXPECT_EQ(InstallResultCode::kSuccessNewInstall, code);
 
-        std::unique_ptr<WebApplicationInfo> final_web_app_info =
+        std::unique_ptr<WebAppInstallInfo> final_web_app_info =
             fake_install_finalizer().web_app_info();
         // Make sure that icons have been generated for all sub sizes.
         EXPECT_TRUE(
@@ -1320,7 +1320,7 @@
   }
 }
 
-TEST_F(WebAppInstallTaskTest, LoadAndRetrieveWebApplicationInfoWithIcons) {
+TEST_F(WebAppInstallTaskTest, LoadAndRetrieveWebAppInstallInfoWithIcons) {
   const GURL url = GURL("https://example.com/path");
   const GURL start_url = GURL("https://example.com/start");
   const std::string name = "Name";
@@ -1331,8 +1331,8 @@
     url_loader().SetNextLoadUrlResult(
         url, WebAppUrlLoader::Result::kRedirectedUrlLoaded);
 
-    std::unique_ptr<WebApplicationInfo> result =
-        LoadAndRetrieveWebApplicationInfoWithIcons(url);
+    std::unique_ptr<WebAppInstallInfo> result =
+        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
     EXPECT_FALSE(result);
   }
   ResetInstallTask();
@@ -1341,8 +1341,8 @@
     url_loader().SetNextLoadUrlResult(
         url, WebAppUrlLoader::Result::kFailedPageTookTooLong);
 
-    std::unique_ptr<WebApplicationInfo> result =
-        LoadAndRetrieveWebApplicationInfoWithIcons(url);
+    std::unique_ptr<WebAppInstallInfo> result =
+        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
     EXPECT_FALSE(result);
   }
   ResetInstallTask();
@@ -1351,8 +1351,8 @@
     CreateRendererAppInfo(url, name, description);
     url_loader().SetNextLoadUrlResult(url, WebAppUrlLoader::Result::kUrlLoaded);
 
-    std::unique_ptr<WebApplicationInfo> result =
-        LoadAndRetrieveWebApplicationInfoWithIcons(url);
+    std::unique_ptr<WebAppInstallInfo> result =
+        LoadAndRetrieveWebAppInstallInfoWithIcons(url);
     EXPECT_TRUE(result);
     EXPECT_EQ(result->start_url, start_url);
     EXPECT_TRUE(result->manifest_icons.empty());
@@ -1370,11 +1370,11 @@
         profile(), &fake_os_integration_manager(), install_finalizer_.get(),
         std::move(data_retriever), &registrar());
 
-    std::unique_ptr<WebApplicationInfo> info;
-    task->LoadAndRetrieveWebApplicationInfoWithIcons(
+    std::unique_ptr<WebAppInstallInfo> info;
+    task->LoadAndRetrieveWebAppInstallInfoWithIcons(
         url, &url_loader(),
         base::BindLambdaForTesting(
-            [&](std::unique_ptr<WebApplicationInfo> app_info) {
+            [&](std::unique_ptr<WebAppInstallInfo> app_info) {
               info = std::move(app_info);
               run_loop.Quit();
             }));
@@ -1394,12 +1394,12 @@
   manifest->start_url = GURL("https://example.com/start");
   manifest->isolated_storage = true;
 
-  auto web_app_info = std::make_unique<WebApplicationInfo>();
+  auto web_app_info = std::make_unique<WebAppInstallInfo>();
   UpdateWebAppInfoFromManifest(*manifest, manifest_start_url,
                                web_app_info.get());
 
   data_retriever_->SetManifest(std::move(manifest), /*is_installable=*/true);
-  data_retriever_->SetRendererWebApplicationInfo(std::move(web_app_info));
+  data_retriever_->SetRendererWebAppInstallInfo(std::move(web_app_info));
 
   base::RunLoop run_loop;
   bool callback_called = false;
@@ -1572,7 +1572,7 @@
                                        InstallResultCode code) {
           result.app_id = installed_app_id;
           result.code = code;
-          std::unique_ptr<WebApplicationInfo> final_web_app_info =
+          std::unique_ptr<WebAppInstallInfo> final_web_app_info =
               fake_install_finalizer().web_app_info();
           EXPECT_EQ(theme_color, final_web_app_info->theme_color);
           EXPECT_EQ(1u, final_web_app_info->shortcuts_menu_item_infos.size());
@@ -1619,7 +1619,7 @@
     InstallResult result;
     const AppId app_id = GenerateAppId(/*manifest_id=*/absl::nullopt, url);
 
-    auto web_app_info = std::make_unique<WebApplicationInfo>();
+    auto web_app_info = std::make_unique<WebAppInstallInfo>();
     web_app_info->start_url = url;
     web_app_info->user_display_mode = DisplayMode::kStandalone;
     web_app_info->theme_color = theme_color;
@@ -1648,7 +1648,7 @@
                                        InstallResultCode code) {
           result.app_id = installed_app_id;
           result.code = code;
-          std::unique_ptr<WebApplicationInfo> final_web_app_info =
+          std::unique_ptr<WebAppInstallInfo> final_web_app_info =
               fake_install_finalizer().web_app_info();
           EXPECT_EQ(theme_color, final_web_app_info->theme_color);
           EXPECT_EQ(1u, final_web_app_info->shortcuts_menu_item_infos.size());
@@ -1799,9 +1799,8 @@
     return manifest;
   }
 
-  std::unique_ptr<WebApplicationInfo> CreateWebApplicationInfo(
-      const GURL& url) {
-    auto app_info = std::make_unique<WebApplicationInfo>();
+  std::unique_ptr<WebAppInstallInfo> CreateWebAppInstallInfo(const GURL& url) {
+    auto app_info = std::make_unique<WebAppInstallInfo>();
     app_info->title = u"Test App";
     app_info->start_url = url;
     app_info->scope = url;
@@ -1844,7 +1843,7 @@
 
   InstallResult UpdateWebAppFromInfo(
       const AppId& app_id,
-      std::unique_ptr<WebApplicationInfo> app_info) {
+      std::unique_ptr<WebAppInstallInfo> app_info) {
     base::RunLoop run_loop;
     bool callback_called = false;
     InstallResult result;
@@ -1918,7 +1917,7 @@
   ResetInstallTask();
 
   // Update the app, adding a file handler.
-  auto app_info = CreateWebApplicationInfo(url);
+  auto app_info = CreateWebAppInstallInfo(url);
   std::vector<blink::mojom::ManifestFileHandlerPtr> file_handlers;
   AddFileHandler(&file_handlers);
   app_info->file_handlers = CreateFileHandlersFromManifest(file_handlers, url);
@@ -1950,7 +1949,7 @@
   ResetInstallTask();
 
   // Update the app, adding a file handler.
-  auto app_info = CreateWebApplicationInfo(url);
+  auto app_info = CreateWebAppInstallInfo(url);
   std::vector<blink::mojom::ManifestFileHandlerPtr> file_handlers;
   AddFileHandler(&file_handlers);
   app_info->file_handlers = CreateFileHandlersFromManifest(file_handlers, url);
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index 5efd96b..0f57321e 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -240,7 +240,7 @@
   return protocol_handlers;
 }
 
-void PopulateShortcutItemIcons(WebApplicationInfo* web_app_info,
+void PopulateShortcutItemIcons(WebAppInstallInfo* web_app_info,
                                const IconsMap& icons_map) {
   web_app_info->shortcuts_menu_icon_bitmaps.clear();
   for (auto& shortcut : web_app_info->shortcuts_menu_item_infos) {
@@ -272,7 +272,7 @@
 // Reconcile the file handling icons that were specified in the manifest with
 // the icons we were successfully able to download. Store the actual bitmaps and
 // update the icon metadata in `web_app_info`.
-void PopulateFileHandlingIcons(WebApplicationInfo* web_app_info,
+void PopulateFileHandlingIcons(WebAppInstallInfo* web_app_info,
                                const IconsMap& icons_map) {
   IconsMap& other_icon_bitmaps = web_app_info->other_icon_bitmaps;
   other_icon_bitmaps.clear();
@@ -362,7 +362,7 @@
 
 void UpdateWebAppInfoFromManifest(const blink::mojom::Manifest& manifest,
                                   const GURL& manifest_url,
-                                  WebApplicationInfo* web_app_info) {
+                                  WebAppInstallInfo* web_app_info) {
   // Give the full length name priority if it's not empty.
   std::u16string name = manifest.name.value_or(std::u16string());
   if (!name.empty())
@@ -413,7 +413,7 @@
   if (!manifest.display_override.empty())
     web_app_info->display_override = manifest.display_override;
 
-  // Create the WebApplicationInfo icons list *outside* of |web_app_info|, so
+  // Create the WebAppInstallInfo icons list *outside* of |web_app_info|, so
   // that we can decide later whether or not to replace the existing icons.
   std::vector<apps::IconInfo> web_app_icons;
   for (const auto& icon : manifest.icons) {
@@ -490,7 +490,7 @@
 }
 
 std::vector<GURL> GetValidIconUrlsToDownload(
-    const WebApplicationInfo& web_app_info) {
+    const WebAppInstallInfo& web_app_info) {
   std::vector<GURL> web_app_info_icon_urls;
   // App icons.
   for (const apps::IconInfo& info : web_app_info.manifest_icons) {
@@ -523,13 +523,13 @@
   return web_app_info_icon_urls;
 }
 
-void PopulateOtherIcons(WebApplicationInfo* web_app_info,
+void PopulateOtherIcons(WebAppInstallInfo* web_app_info,
                         const IconsMap& icons_map) {
   PopulateShortcutItemIcons(web_app_info, icons_map);
   PopulateFileHandlingIcons(web_app_info, icons_map);
 }
 
-void PopulateProductIcons(WebApplicationInfo* web_app_info,
+void PopulateProductIcons(WebAppInstallInfo* web_app_info,
                           const IconsMap* icons_map) {
   std::vector<apps::IconInfo> manifest_icons_any;
   std::vector<apps::IconInfo> manifest_icons_maskable;
diff --git a/chrome/browser/web_applications/web_app_install_utils.h b/chrome/browser/web_applications/web_app_install_utils.h
index b415ec4..ce85817 100644
--- a/chrome/browser/web_applications/web_app_install_utils.h
+++ b/chrome/browser/web_applications/web_app_install_utils.h
@@ -47,21 +47,21 @@
         manifest_file_handlers,
     const GURL& app_scope);
 
-// Update the given WebApplicationInfo with information from the manifest.
+// Update the given WebAppInstallInfo with information from the manifest.
 // Will sanitise the manifest fields to be suitable for installation to prevent
 // sites from using arbitrarily large amounts of disk space.
 void UpdateWebAppInfoFromManifest(const blink::mojom::Manifest& manifest,
                                   const GURL& manifest_url,
-                                  WebApplicationInfo* web_app_info);
+                                  WebAppInstallInfo* web_app_info);
 
 // Form a list of icons to download: Remove icons with invalid urls.
 std::vector<GURL> GetValidIconUrlsToDownload(
-    const WebApplicationInfo& web_app_info);
+    const WebAppInstallInfo& web_app_info);
 
-// Populate non-product icons in WebApplicationInfo using the IconsMap. This
+// Populate non-product icons in WebAppInstallInfo using the IconsMap. This
 // currently covers shortcut item icons and file handler icons. It ignores
 // icons that might have already existed in `web_app_info`.
-void PopulateOtherIcons(WebApplicationInfo* web_app_info,
+void PopulateOtherIcons(WebAppInstallInfo* web_app_info,
                         const IconsMap& icons_map);
 
 // Populates main product icons into `web_app_info`. This method filters icons
@@ -70,7 +70,7 @@
 // `icons_map` is null or missing icons, it will generate icons for sizes where
 // resizing is not possible. Icons which were already populated in
 // `web_app_info` may be retained, and even used to generate missing icons.
-void PopulateProductIcons(WebApplicationInfo* web_app_info,
+void PopulateProductIcons(WebAppInstallInfo* web_app_info,
                           const IconsMap* icons_map);
 
 // Record an app banner added to homescreen event to ensure banners are not
diff --git a/chrome/browser/web_applications/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
index a720bc4..bd4a9dbf 100644
--- a/chrome/browser/web_applications/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_utils_unittest.cc
@@ -72,7 +72,7 @@
   base::test::ScopedFeatureList feature_list(
       blink::features::kFileHandlingIcons);
 
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title = kAlternativeAppTitle;
   web_app_info.start_url = GURL("http://www.notchromium.org");
   apps::IconInfo info;
@@ -207,7 +207,7 @@
 }
 
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_EmptyName) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   blink::mojom::Manifest manifest;
   manifest.name = absl::nullopt;
@@ -233,7 +233,7 @@
   // Produces 1 icon_info.
   icon.purpose = {Purpose::MONOCHROME};
   manifest.icons.push_back(icon);
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   UpdateWebAppInfoFromManifest(
       manifest, GURL("http://www.chromium.org/manifest.json"), &web_app_info);
@@ -254,8 +254,8 @@
   icon.src = GURL("fav1.png");
   icon.purpose = {Purpose::MASKABLE};
   manifest.icons.push_back(icon);
-  // WebApplicationInfo has existing icons (simulating found in page metadata).
-  WebApplicationInfo web_app_info;
+  // WebAppInstallInfo has existing icons (simulating found in page metadata).
+  WebAppInstallInfo web_app_info;
   apps::IconInfo icon_info;
   web_app_info.manifest_icons.push_back(icon_info);
   web_app_info.manifest_icons.push_back(icon_info);
@@ -268,7 +268,7 @@
 
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_ShareTarget) {
   blink::mojom::Manifest manifest;
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   {
     blink::Manifest::ShareTarget share_target;
@@ -345,7 +345,7 @@
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures({blink::features::kFileHandlingIcons}, {});
 
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title = kAlternativeAppTitle;
   web_app_info.start_url = GURL("http://www.notchromium.org");
   apps::IconInfo info;
@@ -388,7 +388,7 @@
     url_handler->has_origin_wildcard = true;
     manifest.url_handlers.push_back(std::move(url_handler));
   }
-  WebApplicationInfo web_app_info_original{web_app_info};
+  WebAppInstallInfo web_app_info_original{web_app_info};
 
   const GURL kAppManifestUrl("http://www.chromium.org/manifest.json");
   UpdateWebAppInfoFromManifest(manifest, kAppManifestUrl, &web_app_info);
@@ -521,7 +521,7 @@
     icon.sizes.emplace_back(i, i);
     manifest.icons.push_back(std::move(icon));
   }
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   UpdateWebAppInfoFromManifest(
       manifest, GURL("http://www.chromium.org/manifest.json"), &web_app_info);
@@ -544,7 +544,7 @@
 
     manifest.shortcuts.push_back(shortcut_item);
   }
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   UpdateWebAppInfoFromManifest(
       manifest, GURL("http://www.chromium.org/manifest.json"), &web_app_info);
 
@@ -571,7 +571,7 @@
     manifest.icons.push_back(std::move(icon));
   }
 
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   UpdateWebAppInfoFromManifest(
       manifest, GURL("http://www.chromium.org/manifest.json"), &web_app_info);
 
@@ -598,7 +598,7 @@
 
     manifest.shortcuts.push_back(shortcut_item);
   }
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   UpdateWebAppInfoFromManifest(
       manifest, GURL("http://www.chromium.org/manifest.json"), &web_app_info);
 
@@ -615,7 +615,7 @@
 // Tests that SkBitmaps associated with shortcut item icons are populated in
 // their own map in web_app_info.
 TEST(WebAppInstallUtils, PopulateShortcutItemIcons) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   WebAppShortcutsMenuItemInfo::Icon icon;
 
   const GURL kIconUrl1("http://www.chromium.org/shortcuts/icon1.png");
@@ -670,7 +670,7 @@
 // Tests that when PopulateOtherItemIcons is called with no shortcut icon
 // urls specified, no data is written to shortcuts_menu_item_infos.
 TEST(WebAppInstallUtils, PopulateShortcutItemIconsNoShortcutIcons) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   IconsMap icons_map;
   std::vector<SkBitmap> bmp1 = {CreateSquareIcon(32, SK_ColorWHITE)};
   std::vector<SkBitmap> bmp2 = {CreateSquareIcon(32, SK_ColorBLUE)};
@@ -698,7 +698,7 @@
   icons_map.emplace(kIconUrl2, bmp2);
 
   // Construct |web_app_info| to pass icon infos.
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title = u"App Name";
   apps::IconInfo info;
   // Icon at URL 1 has both kAny and kMaskable purpose.
@@ -732,7 +732,7 @@
   icons_map.emplace(kIconUrl1, bmp1);
 
   // Construct |web_app_info| to pass icon infos.
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title = u"App Name";
   apps::IconInfo info;
   info.url = kIconUrl1;
@@ -749,7 +749,7 @@
 }
 
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_InvalidManifestUrl) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   blink::mojom::Manifest manifest;
 
   UpdateWebAppInfoFromManifest(manifest, GURL("foo"), &web_app_info);
@@ -760,7 +760,7 @@
 // app icon or shortcut icon data in web_app_info, and kDesktopPWAShortcutsMenu
 // feature enabled, web_app_info.icon_bitmaps_any is correctly populated.
 TEST(WebAppInstallUtils, PopulateProductIconsNoWebAppIconData_WithShortcuts) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.title = u"App Name";
 
   IconsMap icons_map;
@@ -777,7 +777,7 @@
 
 TEST(WebAppInstallUtils, PopulateProductIcons_IsGeneratedIcon) {
   {
-    WebApplicationInfo web_app_info;
+    WebAppInstallInfo web_app_info;
     web_app_info.title = u"App Name";
 
     IconsMap icons_map;
@@ -788,7 +788,7 @@
     EXPECT_TRUE(ContainsOneIconOfEachSize(web_app_info.icon_bitmaps.any));
   }
   {
-    WebApplicationInfo web_app_info;
+    WebAppInstallInfo web_app_info;
     web_app_info.title = u"App Name";
 
     IconsMap icons_map;
@@ -805,7 +805,7 @@
       EXPECT_EQ(SK_ColorCYAN, bitmap_any.second.getColor(0, 0));
   }
   {
-    WebApplicationInfo web_app_info;
+    WebAppInstallInfo web_app_info;
     web_app_info.title = u"App Name";
 
     IconsMap icons_map;
@@ -825,7 +825,7 @@
 
 TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_Translations) {
   blink::mojom::Manifest manifest;
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
 
   {
     blink::Manifest::TranslationItem item;
@@ -982,7 +982,7 @@
 
   std::vector<blink::mojom::ManifestFileHandlerPtr> manifest_file_handlers =
       CreateManifestFileHandlers(1);
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.file_handlers =
       CreateFileHandlersFromManifest(manifest_file_handlers, GetStartUrl());
 
diff --git a/chrome/browser/web_applications/web_app_installation_utils.cc b/chrome/browser/web_applications/web_app_installation_utils.cc
index 4c2f2226..555537ec 100644
--- a/chrome/browser/web_applications/web_app_installation_utils.cc
+++ b/chrome/browser/web_applications/web_app_installation_utils.cc
@@ -62,7 +62,7 @@
 
 }  // namespace
 
-void SetWebAppManifestFields(const WebApplicationInfo& web_app_info,
+void SetWebAppManifestFields(const WebAppInstallInfo& web_app_info,
                              WebApp& web_app) {
   DCHECK(!web_app_info.title.empty());
   web_app.SetName(base::UTF16ToUTF8(web_app_info.title));
diff --git a/chrome/browser/web_applications/web_app_installation_utils.h b/chrome/browser/web_applications/web_app_installation_utils.h
index 3032c076..0db6a8e 100644
--- a/chrome/browser/web_applications/web_app_installation_utils.h
+++ b/chrome/browser/web_applications/web_app_installation_utils.h
@@ -7,7 +7,7 @@
 
 #include "chrome/browser/web_applications/web_app_id.h"
 
-struct WebApplicationInfo;
+struct WebAppInstallInfo;
 
 namespace web_app {
 
@@ -16,7 +16,7 @@
 class WebApp;
 
 // Updates |web_app| using |web_app_info|
-void SetWebAppManifestFields(const WebApplicationInfo& web_app_info,
+void SetWebAppManifestFields(const WebAppInstallInfo& web_app_info,
                              WebApp& web_app);
 
 // Possibly updates |options| to disable OS-integrations based on the
diff --git a/chrome/browser/web_applications/web_app_installation_utils_unittest.cc b/chrome/browser/web_applications/web_app_installation_utils_unittest.cc
index bb2102d..4556c76 100644
--- a/chrome/browser/web_applications/web_app_installation_utils_unittest.cc
+++ b/chrome/browser/web_applications/web_app_installation_utils_unittest.cc
@@ -32,7 +32,7 @@
 }  // namespace
 
 TEST(WebAppInstallationUtils, SetWebAppManifestFields_Summary) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.start_url = GURL("https://www.chromium.org/index.html");
   web_app_info.scope = web_app_info.start_url.GetWithoutFilename();
   web_app_info.title = u"App Name";
@@ -71,7 +71,7 @@
 }
 
 TEST(WebAppInstallationUtils, SetWebAppManifestFields_ShareTarget) {
-  WebApplicationInfo web_app_info;
+  WebAppInstallInfo web_app_info;
   web_app_info.start_url = StartUrl();
   web_app_info.scope = web_app_info.start_url.GetWithoutFilename();
   web_app_info.title = u"App Name";
diff --git a/chrome/browser/web_applications/web_app_mover.cc b/chrome/browser/web_applications/web_app_mover.cc
index 0205f86..4f49cbe 100644
--- a/chrome/browser/web_applications/web_app_mover.cc
+++ b/chrome/browser/web_applications/web_app_mover.cc
@@ -301,7 +301,7 @@
       web_contents, true, webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
       base::BindOnce(
           [](content::WebContents* initiator_web_contents,
-             std::unique_ptr<WebApplicationInfo> web_app_info,
+             std::unique_ptr<WebAppInstallInfo> web_app_info,
              ForInstallableSite for_installable_site,
              WebAppInstallationAcceptanceCallback acceptance_callback) {
             // Note: |open_as_window| is set to false here (which it should be
diff --git a/chrome/browser/web_applications/web_application_info.cc b/chrome/browser/web_applications/web_application_info.cc
index 1b56eb6f..3310e07 100644
--- a/chrome/browser/web_applications/web_application_info.cc
+++ b/chrome/browser/web_applications/web_application_info.cc
@@ -212,13 +212,12 @@
   return root;
 }
 
-// WebApplicationInfo
-WebApplicationInfo::WebApplicationInfo() = default;
+// WebAppInstallInfo
+WebAppInstallInfo::WebAppInstallInfo() = default;
 
-WebApplicationInfo::WebApplicationInfo(const WebApplicationInfo& other) =
-    default;
+WebAppInstallInfo::WebAppInstallInfo(const WebAppInstallInfo& other) = default;
 
-WebApplicationInfo::WebApplicationInfo(
+WebAppInstallInfo::WebAppInstallInfo(
     const webapps::mojom::WebPageMetadata& metadata)
     : title(metadata.application_name),
       description(metadata.description),
@@ -243,7 +242,7 @@
   }
 }
 
-WebApplicationInfo::~WebApplicationInfo() = default;
+WebAppInstallInfo::~WebAppInstallInfo() = default;
 
 bool operator==(const IconSizes& icon_sizes1, const IconSizes& icon_sizes2) {
   return std::tie(icon_sizes1.any, icon_sizes1.maskable,
diff --git a/chrome/browser/web_applications/web_application_info.h b/chrome/browser/web_applications/web_application_info.h
index 2fbc940..c59601b 100644
--- a/chrome/browser/web_applications/web_application_info.h
+++ b/chrome/browser/web_applications/web_application_info.h
@@ -165,17 +165,17 @@
 };
 
 // Structure used when installing a web page as an app.
-struct WebApplicationInfo {
+struct WebAppInstallInfo {
   enum MobileCapable {
     MOBILE_CAPABLE_UNSPECIFIED,
     MOBILE_CAPABLE,
     MOBILE_CAPABLE_APPLE
   };
 
-  WebApplicationInfo();
-  WebApplicationInfo(const WebApplicationInfo& other);
-  explicit WebApplicationInfo(const webapps::mojom::WebPageMetadata& metadata);
-  ~WebApplicationInfo();
+  WebAppInstallInfo();
+  WebAppInstallInfo(const WebAppInstallInfo& other);
+  explicit WebAppInstallInfo(const webapps::mojom::WebPageMetadata& metadata);
+  ~WebAppInstallInfo();
 
   // Id specified in the manifest.
   absl::optional<std::string> manifest_id;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 0845915..09c8a2f3 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1641772527-f3cf5225c389ca5506cb2fa2a029789c3ef5d445.profdata
+chrome-linux-main-1641815658-a5ab5a1fc52e96782cdcee31e1f1aa23ceda8372.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 4e12db8..6d29610 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1641750463-f7c6f053ef566ff1133d19dcf200295e52d65344.profdata
+chrome-mac-main-1641793337-2e4d3a2b7b73d8cc9091fa78b5f157aaae2daca3.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 90d1f06..9e3f716 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1641726917-79adf5b1fb33a7d8209020d2ed81a6c88d94eb65.profdata
+chrome-win32-main-1641803336-4a7e270c35d3d270eac2bf1d6a5cf5c3e5abfd57.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index e0142374..8d66211 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1641760364-31740d35312a91a7b77ad5a4e0881a0f525a1a73.profdata
+chrome-win64-main-1641803336-28310930e85fdee615d31b40cd1a1d7a705caf06.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index b2d207eed..a9ccbe54 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -8946,6 +8946,8 @@
     "../browser/sync/test/integration/device_info_helper.h",
     "../browser/sync/test/integration/encryption_helper.cc",
     "../browser/sync/test/integration/encryption_helper.h",
+    "../browser/sync/test/integration/exponential_backoff_helper.cc",
+    "../browser/sync/test/integration/exponential_backoff_helper.h",
     "../browser/sync/test/integration/fake_server_invalidation_sender.cc",
     "../browser/sync/test/integration/fake_server_invalidation_sender.h",
     "../browser/sync/test/integration/fake_server_sync_invalidation_sender.cc",
@@ -8958,8 +8960,6 @@
     "../browser/sync/test/integration/passwords_helper.h",
     "../browser/sync/test/integration/quiesce_status_change_checker.cc",
     "../browser/sync/test/integration/quiesce_status_change_checker.h",
-    "../browser/sync/test/integration/retry_verifier.cc",
-    "../browser/sync/test/integration/retry_verifier.h",
     "../browser/sync/test/integration/secondary_account_helper.cc",
     "../browser/sync/test/integration/secondary_account_helper.h",
     "../browser/sync/test/integration/single_client_status_change_checker.cc",
diff --git a/chrome/test/data/printing/legacy-layout-engine-known-bug.html b/chrome/test/data/printing/legacy-layout-engine-known-bug.html
new file mode 100644
index 0000000..1bb265e
--- /dev/null
+++ b/chrome/test/data/printing/legacy-layout-engine-known-bug.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!-- This is laid out correctly with LayoutNG, but not with the legacy engine.
+     We can use this to determine which layout engine is being used. -->
+<div style="float:right; width:50px; height:100px;"></div>
+<div style="width:100px;">
+  <div style="height:15px;"></div>
+  <div id="target" style="background:red;">
+    <div style="clear:right;">
+      <div style="margin-top:85px;"></div>
+    </div>
+  </div>
+</div>
+
+<!-- Try our best to trigger legacy engine fallback for printing, by using as
+     many layout types as we can think of. -->
+<div style="display:flex;"></div>
+<div style="display:grid;"></div>
+<div style="display:table;"></div>
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index a0ad8d1..96fe1e7 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -12,6 +12,7 @@
   "appearance_page_test.ts",
   "clear_browsing_data_test.ts",
   "downloads_page_test.ts",
+  "password_edit_dialog_test.ts",
   "people_page_test.ts",
   "people_page_sync_page_test.ts",
   "personalization_options_test.ts",
@@ -67,10 +68,9 @@
   "multi_store_password_ui_entry_test.js",
   "on_startup_page_tests.ts",
   "password_check_test.js",
-  "password_edit_dialog_test.js",
   "passwords_and_autofill_fake_data.ts",
   "passwords_device_section_test.js",
-  "passwords_export_test.js",
+  "passwords_export_test.ts",
   "passwords_section_test.js",
   "payments_section_interactive_test.ts",
   "payments_section_test.ts",
diff --git a/chrome/test/data/webui/settings/password_edit_dialog_test.js b/chrome/test/data/webui/settings/password_edit_dialog_test.ts
similarity index 84%
rename from chrome/test/data/webui/settings/password_edit_dialog_test.js
rename to chrome/test/data/webui/settings/password_edit_dialog_test.ts
index 663885c..533ff75 100644
--- a/chrome/test/data/webui/settings/password_edit_dialog_test.js
+++ b/chrome/test/data/webui/settings/password_edit_dialog_test.ts
@@ -7,9 +7,10 @@
 // clang-format off
 import 'chrome://settings/lazy_load.js';
 
-import {isChromeOS, isLacros} from 'chrome://resources/js/cr.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {PasswordEditDialogElement} from 'chrome://settings/lazy_load.js';
 import {PasswordManagerImpl} from 'chrome://settings/settings.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {eventToPromise, flushTasks} from 'chrome://webui-test/test_util.js';
 
 import {createMultiStorePasswordEntry, PasswordSectionElementFactory} from './passwords_and_autofill_fake_data.js';
@@ -20,28 +21,28 @@
 /**
  * Helper function to test if an element is visible.
  */
-function isElementVisible(element) {
+function isElementVisible(element: HTMLElement) {
   return element && !element.hidden;
 }
 
 /**
  * Helper function to test if all components of edit dialog are shown correctly.
  */
-function assertEditDialogParts(passwordDialog) {
+function assertEditDialogParts(passwordDialog: PasswordEditDialogElement) {
   assertEquals(
       passwordDialog.i18n('editPasswordTitle'),
-      passwordDialog.$.title.textContent.trim());
-  assertTrue(passwordDialog.$.websiteInput.readonly);
-  assertFalse(passwordDialog.$.usernameInput.readonly);
-  assertFalse(passwordDialog.$.passwordInput.readonly);
-  assertTrue(passwordDialog.$.passwordInput.required);
+      passwordDialog.$.title.textContent!.trim());
+  assertTrue(!!passwordDialog.$.websiteInput.readonly);
+  assertFalse(!!passwordDialog.$.usernameInput.readonly);
+  assertFalse(!!passwordDialog.$.passwordInput.readonly);
+  assertTrue(!!passwordDialog.$.passwordInput.required);
   assertFalse(isElementVisible(passwordDialog.$.storePicker));
-  assertTrue(!!passwordDialog.shadowRoot.querySelector('#showPasswordButton'));
+  assertTrue(!!passwordDialog.shadowRoot!.querySelector('#showPasswordButton'));
   assertTrue(isElementVisible(passwordDialog.$.footnote));
   assertTrue(isElementVisible(passwordDialog.$.cancel));
   assertEquals(
       passwordDialog.i18n('save'),
-      passwordDialog.$.actionButton.textContent.trim());
+      passwordDialog.$.actionButton.textContent!.trim());
   assertFalse(passwordDialog.$.actionButton.disabled);
 }
 
@@ -49,42 +50,43 @@
  * Helper function to test if all components of details dialog are shown
  * correctly.
  */
-function assertDetailsDialogParts(passwordDialog) {
+function assertDetailsDialogParts(passwordDialog: PasswordEditDialogElement) {
   assertEquals(
       passwordDialog.i18n('passwordDetailsTitle'),
-      passwordDialog.$.title.textContent.trim());
-  assertTrue(passwordDialog.$.websiteInput.readonly);
-  assertTrue(passwordDialog.$.usernameInput.readonly);
-  assertTrue(passwordDialog.$.passwordInput.readonly);
-  assertFalse(passwordDialog.$.passwordInput.required);
+      passwordDialog.$.title.textContent!.trim());
+  assertTrue(!!passwordDialog.$.websiteInput.readonly);
+  assertTrue(!!passwordDialog.$.usernameInput.readonly);
+  assertTrue(!!passwordDialog.$.passwordInput.readonly);
+  assertFalse(!!passwordDialog.$.passwordInput.required);
   assertFalse(isElementVisible(passwordDialog.$.storePicker));
-  assertFalse(!!passwordDialog.shadowRoot.querySelector('#showPasswordButton'));
+  assertFalse(
+      !!passwordDialog.shadowRoot!.querySelector('#showPasswordButton'));
   assertFalse(isElementVisible(passwordDialog.$.footnote));
   assertFalse(isElementVisible(passwordDialog.$.cancel));
   assertEquals(
       passwordDialog.i18n('done'),
-      passwordDialog.$.actionButton.textContent.trim());
+      passwordDialog.$.actionButton.textContent!.trim());
   assertFalse(passwordDialog.$.actionButton.disabled);
 }
 
 /**
  * Helper function to test if all components of add dialog are shown correctly.
  */
-function assertAddDialogParts(passwordDialog) {
+function assertAddDialogParts(passwordDialog: PasswordEditDialogElement) {
   assertEquals(
       passwordDialog.i18n('addPasswordTitle'),
-      passwordDialog.$.title.textContent.trim());
-  assertFalse(passwordDialog.$.websiteInput.readonly);
-  assertFalse(passwordDialog.$.usernameInput.readonly);
-  assertFalse(passwordDialog.$.passwordInput.readonly);
-  assertTrue(passwordDialog.$.passwordInput.required);
+      passwordDialog.$.title.textContent!.trim());
+  assertFalse(!!passwordDialog.$.websiteInput.readonly);
+  assertFalse(!!passwordDialog.$.usernameInput.readonly);
+  assertFalse(!!passwordDialog.$.passwordInput.readonly);
+  assertTrue(!!passwordDialog.$.passwordInput.required);
   assertFalse(isElementVisible(passwordDialog.$.storageDetails));
-  assertTrue(!!passwordDialog.shadowRoot.querySelector('#showPasswordButton'));
+  assertTrue(!!passwordDialog.shadowRoot!.querySelector('#showPasswordButton'));
   assertTrue(isElementVisible(passwordDialog.$.footnote));
   assertTrue(isElementVisible(passwordDialog.$.cancel));
   assertEquals(
       passwordDialog.i18n('save'),
-      passwordDialog.$.actionButton.textContent.trim());
+      passwordDialog.$.actionButton.textContent!.trim());
   assertTrue(passwordDialog.$.actionButton.disabled);
 }
 
@@ -92,7 +94,9 @@
  * Helper function to update website input and trigger validation.
  */
 async function updateWebsiteInput(
-    dialog, passwordManager, newValue, isValid = true) {
+    dialog: PasswordEditDialogElement,
+    passwordManager: TestPasswordManagerProxy, newValue: string,
+    isValid = true) {
   const shouldGetUrlCollection = !!newValue.length;
   if (shouldGetUrlCollection) {
     passwordManager.resetResolver('getUrlCollection');
@@ -117,13 +121,11 @@
 
 /**
  * Helper function to test change saved password behavior.
- * @param {!PasswordEditDialogElement} editDialog
- * @param {!Array<number>} entryIds Ids to be called as a changeSavedPassword
- *     parameter.
- * @param {TestPasswordManagerProxy} passwordManager
+ * @param entryIds Ids to be called as a changeSavedPassword parameter.
  */
 async function changeSavedPasswordTestHelper(
-    editDialog, entryIds, passwordManager) {
+    editDialog: PasswordEditDialogElement, entryIds: number[],
+    passwordManager: TestPasswordManagerProxy) {
   const NEW_USERNAME = 'new_username';
   const NEW_PASSWORD = 'new_password';
 
@@ -151,13 +153,13 @@
 
 /**
  * Helper function to test add password behavior.
- * @param {!PasswordEditDialogElement} addDialog
- * @param {!TestPasswordManagerProxy} passwordManager
- * @param {boolean} expectedUseAccountStore True for account store, false for
- *     device store.
+ * @param expectedUseAccountStore True for account store, false for device
+ *     store.
  */
 async function addPasswordTestHelper(
-    addDialog, passwordManager, expectedUseAccountStore) {
+    addDialog: PasswordEditDialogElement,
+    passwordManager: TestPasswordManagerProxy,
+    expectedUseAccountStore: boolean) {
   const WEBSITE = 'example.com';
   const USERNAME = 'username';
   const PASSWORD = 'password';
@@ -179,14 +181,11 @@
 }
 
 suite('PasswordEditDialog', function() {
-  /** @type {TestPasswordManagerProxy} */
-  let passwordManager = null;
-
-  /** @type {PasswordSectionElementFactory} */
-  let elementFactory = null;
+  let passwordManager: TestPasswordManagerProxy;
+  let elementFactory: PasswordSectionElementFactory;
 
   setup(function() {
-    PolymerTest.clearBody();
+    document.body.innerHTML = '';
     // Override the PasswordManagerImpl for testing.
     passwordManager = new TestPasswordManagerProxy();
     PasswordManagerImpl.setInstance(passwordManager);
@@ -231,7 +230,7 @@
     const editDialog = elementFactory.createPasswordEditDialog(accountEntry);
 
     return changeSavedPasswordTestHelper(
-        editDialog, [accountEntry.accountId], passwordManager);
+        editDialog, [accountEntry.accountId!], passwordManager);
   });
 
   test('changesPasswordForDeviceId', function() {
@@ -240,7 +239,7 @@
     const editDialog = elementFactory.createPasswordEditDialog(deviceEntry);
 
     return changeSavedPasswordTestHelper(
-        editDialog, [deviceEntry.deviceId], passwordManager);
+        editDialog, [deviceEntry.deviceId!], passwordManager);
   });
 
   test('changesPasswordForBothId', function() {
@@ -249,7 +248,7 @@
     const editDialog = elementFactory.createPasswordEditDialog(multiEntry);
 
     return changeSavedPasswordTestHelper(
-        editDialog, [multiEntry.accountId, multiEntry.deviceId],
+        editDialog, [multiEntry.accountId!, multiEntry.deviceId!],
         passwordManager);
   });
 
@@ -261,7 +260,7 @@
           {url: 'goo.gl', username: 'mark', accountId: 0})
     ];
     const editDialog = elementFactory.createPasswordEditDialog(
-        accountPasswords[0], accountPasswords);
+        accountPasswords[0]!, accountPasswords);
 
     editDialog.$.usernameInput.value = 'mark';
     assertTrue(editDialog.$.usernameInput.invalid);
@@ -272,7 +271,7 @@
     assertFalse(editDialog.$.actionButton.disabled);
 
     return changeSavedPasswordTestHelper(
-        editDialog, [accountPasswords[0].accountId], passwordManager);
+        editDialog, [accountPasswords[0]!.accountId!], passwordManager);
   });
 
   test('changesUsernameWhenReusedForDifferentStore', async function() {
@@ -381,10 +380,10 @@
     assertEquals(false, addDialog.$.websiteInput.autofocus);
     assertEquals(
         addDialog.i18n('addPasswordStoreOptionAccount', addDialog.accountEmail),
-        picker.options[0].textContent.trim());
+        picker.options[0]!.textContent!.trim());
     assertEquals(
         addDialog.i18n('addPasswordStoreOptionDevice'),
-        picker.options[1].textContent.trim());
+        picker.options[1]!.textContent!.trim());
   });
 
   test('checksRequiredFieldsWhenAddPassword', async function() {
@@ -585,32 +584,32 @@
         assertEquals(existingEntry.password, addDialog.$.passwordInput.value);
       });
 
+  // <if expr="not chromeos_ash and not chromeos_lacros">
   // On ChromeOS/Lacros the behavior is different (on failure we request token
   // and retry).
-  if (!isChromeOS && !isLacros) {
-    test(
-        'notSwitchToEditModeOnViewPasswordClickWhenRequestPlaintextPasswordFailed',
-        async function() {
-          const existingEntry = createMultiStorePasswordEntry(
-              {url: 'website.com', username: 'username', accountId: 0});
-          const addDialog =
-              elementFactory.createPasswordEditDialog(null, [existingEntry]);
-          assertFalse(isElementVisible(addDialog.$.viewExistingPasswordLink));
+  test(
+      'notSwitchToEditModeOnViewPasswordClickWhenRequestPlaintextPasswordFailed',
+      async function() {
+        const existingEntry = createMultiStorePasswordEntry(
+            {url: 'website.com', username: 'username', accountId: 0});
+        const addDialog =
+            elementFactory.createPasswordEditDialog(null, [existingEntry]);
+        assertFalse(isElementVisible(addDialog.$.viewExistingPasswordLink));
 
-          await updateWebsiteInput(
-              addDialog, passwordManager, existingEntry.urls.shown);
-          addDialog.$.usernameInput.value = existingEntry.username;
-          assertTrue(isElementVisible(addDialog.$.viewExistingPasswordLink));
+        await updateWebsiteInput(
+            addDialog, passwordManager, existingEntry.urls.shown);
+        addDialog.$.usernameInput.value = existingEntry.username;
+        assertTrue(isElementVisible(addDialog.$.viewExistingPasswordLink));
 
-          // By default requestPlaintextPassword fails if value not set.
-          addDialog.$.viewExistingPasswordLink.click();
-          const {id, reason} =
-              await passwordManager.whenCalled('requestPlaintextPassword');
-          assertEquals(existingEntry.getAnyId(), id);
-          assertEquals(chrome.passwordsPrivate.PlaintextReason.EDIT, reason);
-          await flushTasks();
+        // By default requestPlaintextPassword fails if value not set.
+        addDialog.$.viewExistingPasswordLink.click();
+        const {id, reason} =
+            await passwordManager.whenCalled('requestPlaintextPassword');
+        assertEquals(existingEntry.getAnyId(), id);
+        assertEquals(chrome.passwordsPrivate.PlaintextReason.EDIT, reason);
+        await flushTasks();
 
-          assertAddDialogParts(addDialog);
-        });
-  }
+        assertAddDialogParts(addDialog);
+      });
+  // </if>
 });
diff --git a/chrome/test/data/webui/settings/passwords_export_test.js b/chrome/test/data/webui/settings/passwords_export_test.js
deleted file mode 100644
index c4a30b7..0000000
--- a/chrome/test/data/webui/settings/passwords_export_test.js
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// clang-format off
-import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {MockTimer} from 'chrome://test/mock_timer.js';
-import {eventToPromise} from 'chrome://webui-test/test_util.js';
-// clang-format on
-
-// Test that tapping "Export passwords..." notifies the browser.
-export function runStartExportTest(exportDialog, passwordManager, done) {
-  passwordManager.exportPasswords = (callback) => {
-    callback();
-    done();
-  };
-
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-}
-
-// Test the export flow. If exporting is fast, we should skip the
-// in-progress view altogether.
-export function runExportFlowFastTest(exportDialog, passwordManager, done) {
-  const progressCallback =
-      passwordManager.lastCallback.addPasswordsFileExportProgressListener;
-
-  // Use this to freeze the delayed progress bar and avoid flakiness.
-  const mockTimer = new MockTimer();
-  mockTimer.install();
-
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
-
-  flush();
-  // When we are done, the export dialog closes completely.
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_start'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_error'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_progress'));
-  done();
-
-  mockTimer.uninstall();
-}
-
-// The error view is shown when an error occurs.
-export function runExportFlowErrorTest(exportDialog, passwordManager, done) {
-  const progressCallback =
-      passwordManager.lastCallback.addPasswordsFileExportProgressListener;
-
-  // Use this to freeze the delayed progress bar and avoid flakiness.
-  const mockTimer = new MockTimer();
-  mockTimer.install();
-
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-  progressCallback({
-    status: chrome.passwordsPrivate.ExportProgressStatus.FAILED_WRITE_FAILED,
-    folderName: 'tmp',
-  });
-
-  flush();
-  // Test that the error dialog is shown.
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_error').open);
-  // Test that the error dialog can be dismissed.
-  exportDialog.shadowRoot.querySelector('#cancelErrorButton').click();
-  flush();
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_error'));
-  done();
-
-  mockTimer.uninstall();
-}
-
-// The error view allows to retry.
-export function runExportFlowErrorRetryTest(
-    exportDialog, passwordManager, done) {
-  const progressCallback =
-      passwordManager.lastCallback.addPasswordsFileExportProgressListener;
-  // Use this to freeze the delayed progress bar and avoid flakiness.
-  const mockTimer = new MockTimer();
-
-  new Promise(resolve => {
-    mockTimer.install();
-
-    passwordManager.exportPasswords = resolve;
-    exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  }).then(() => {
-    // This wait allows the BlockingRequestManager to process the click if
-    // the test is running in ChromeOS.
-    progressCallback(
-        {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-    progressCallback({
-      status: chrome.passwordsPrivate.ExportProgressStatus.FAILED_WRITE_FAILED,
-      folderName: 'tmp',
-    });
-
-    flush();
-    // Test that the error dialog is shown.
-    assertTrue(exportDialog.shadowRoot.querySelector('#dialog_error').open);
-    // Test that clicking retry will start a new export.
-    passwordManager.exportPasswords = (callback) => {
-      callback();
-      done();
-    };
-    exportDialog.shadowRoot.querySelector('#tryAgainButton').click();
-
-    mockTimer.uninstall();
-  });
-}
-
-// Test the export flow. If exporting is slow, Chrome should show the
-// in-progress dialog for at least 1000ms.
-export function runExportFlowSlowTest(exportDialog, passwordManager, done) {
-  const progressCallback =
-      passwordManager.lastCallback.addPasswordsFileExportProgressListener;
-
-  const mockTimer = new MockTimer();
-  mockTimer.install();
-
-  // The initial dialog remains open for 100ms after export enters the
-  // in-progress state.
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-
-  // After 100ms of not having completed, the dialog switches to the
-  // progress bar. Chrome will continue to show the progress bar for 1000ms,
-  // despite a completion event.
-  mockTimer.tick(99);
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_start').open);
-  mockTimer.tick(1);
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_progress').open);
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_progress').open);
-
-  // After 1000ms, Chrome will display the completion event.
-  mockTimer.tick(999);
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_progress').open);
-  mockTimer.tick(1);
-  flush();
-  // On SUCCEEDED the dialog closes completely.
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_progress'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_start'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_error'));
-  done();
-
-  mockTimer.uninstall();
-}
-
-// Test that canceling the dialog while exporting will also cancel the
-// export on the browser.
-export function runCancelExportTest(exportDialog, passwordManager, done) {
-  const progressCallback =
-      passwordManager.lastCallback.addPasswordsFileExportProgressListener;
-
-  passwordManager.cancelExportPasswords = () => {
-    done();
-  };
-
-  const mockTimer = new MockTimer();
-  mockTimer.install();
-
-  // The initial dialog remains open for 100ms after export enters the
-  // in-progress state.
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  progressCallback(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-  // The progress bar only appears after 100ms.
-  mockTimer.tick(100);
-  flush();
-  assertTrue(exportDialog.shadowRoot.querySelector('#dialog_progress').open);
-  exportDialog.shadowRoot.querySelector('#cancel_progress_button').click();
-
-  flush();
-  // The dialog should be dismissed entirely.
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_progress'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_start'));
-  assertFalse(!!exportDialog.shadowRoot.querySelector('#dialog_error'));
-
-  mockTimer.uninstall();
-}
-
-export function runFireCloseEventAfterExportCompleteTest(
-    exportDialog, passwordManager) {
-  const wait = eventToPromise('passwords-export-dialog-close', exportDialog);
-  exportDialog.shadowRoot.querySelector('#exportPasswordsButton').click();
-  passwordManager.lastCallback.addPasswordsFileExportProgressListener(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
-  passwordManager.lastCallback.addPasswordsFileExportProgressListener(
-      {status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
-  return wait;
-}
diff --git a/chrome/test/data/webui/settings/passwords_export_test.ts b/chrome/test/data/webui/settings/passwords_export_test.ts
new file mode 100644
index 0000000..f3bac00
--- /dev/null
+++ b/chrome/test/data/webui/settings/passwords_export_test.ts
@@ -0,0 +1,268 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// clang-format off
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrDialogElement, PasswordsExportDialogElement} from 'chrome://settings/lazy_load.js';
+import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {MockTimer} from 'chrome://webui-test/mock_timer.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
+
+import {TestPasswordManagerProxy} from './test_password_manager_proxy.js';
+// clang-format on
+
+// Test that tapping "Export passwords..." notifies the browser.
+export function runStartExportTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  passwordManager.exportPasswords = (callback) => {
+    callback();
+    done();
+  };
+
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+}
+
+// Test the export flow. If exporting is fast, we should skip the
+// in-progress view altogether.
+export function runExportFlowFastTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  const progressCallback =
+      passwordManager.lastCallback.addPasswordsFileExportProgressListener!;
+
+  // Use this to freeze the delayed progress bar and avoid flakiness.
+  const mockTimer = new MockTimer();
+  mockTimer.install();
+
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+  flush();
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
+
+  flush();
+  // When we are done, the export dialog closes completely.
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_start'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_error'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_progress'));
+  done();
+
+  mockTimer.uninstall();
+}
+
+// The error view is shown when an error occurs.
+export function runExportFlowErrorTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  const progressCallback =
+      passwordManager.lastCallback.addPasswordsFileExportProgressListener!;
+
+  // Use this to freeze the delayed progress bar and avoid flakiness.
+  const mockTimer = new MockTimer();
+  mockTimer.install();
+
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+  progressCallback({
+    status: chrome.passwordsPrivate.ExportProgressStatus.FAILED_WRITE_FAILED,
+    folderName: 'tmp',
+  });
+
+  flush();
+  // Test that the error dialog is shown.
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_error')!.open);
+  // Test that the error dialog can be dismissed.
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#cancelErrorButton')!.click();
+  flush();
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_error'));
+  done();
+
+  mockTimer.uninstall();
+}
+
+// The error view allows to retry.
+export function runExportFlowErrorRetryTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  const progressCallback =
+      passwordManager.lastCallback.addPasswordsFileExportProgressListener!;
+  // Use this to freeze the delayed progress bar and avoid flakiness.
+  const mockTimer = new MockTimer();
+
+  new Promise(resolve => {
+    mockTimer.install();
+
+    passwordManager.exportPasswords = resolve;
+    exportDialog.shadowRoot!
+        .querySelector<HTMLElement>('#exportPasswordsButton')!.click();
+  }).then(() => {
+    // This wait allows the BlockingRequestManager to process the click if
+    // the test is running in ChromeOS.
+    progressCallback(
+        {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+    progressCallback({
+      status: chrome.passwordsPrivate.ExportProgressStatus.FAILED_WRITE_FAILED,
+      folderName: 'tmp',
+    });
+
+    flush();
+    // Test that the error dialog is shown.
+    assertTrue(exportDialog.shadowRoot!
+                   .querySelector<CrDialogElement>('#dialog_error')!.open);
+    // Test that clicking retry will start a new export.
+    passwordManager.exportPasswords = (callback) => {
+      callback();
+      done();
+    };
+    exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                                '#tryAgainButton')!.click();
+
+    mockTimer.uninstall();
+  });
+}
+
+// Test the export flow. If exporting is slow, Chrome should show the
+// in-progress dialog for at least 1000ms.
+export function runExportFlowSlowTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  const progressCallback =
+      passwordManager.lastCallback.addPasswordsFileExportProgressListener!;
+
+  const mockTimer = new MockTimer();
+  mockTimer.install();
+
+  // The initial dialog remains open for 100ms after export enters the
+  // in-progress state.
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+  flush();
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+  flush();
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+
+  // After 100ms of not having completed, the dialog switches to the
+  // progress bar. Chrome will continue to show the progress bar for 1000ms,
+  // despite a completion event.
+  mockTimer.tick(99);
+  flush();
+  assertTrue(
+      exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+                                  '#dialog_start')!.open);
+  mockTimer.tick(1);
+  flush();
+  assertTrue(exportDialog.shadowRoot!
+                 .querySelector<CrDialogElement>('#dialog_progress')!.open);
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
+  flush();
+  assertTrue(exportDialog.shadowRoot!
+                 .querySelector<CrDialogElement>('#dialog_progress')!.open);
+
+  // After 1000ms, Chrome will display the completion event.
+  mockTimer.tick(999);
+  flush();
+  assertTrue(exportDialog.shadowRoot!
+                 .querySelector<CrDialogElement>('#dialog_progress')!.open);
+  mockTimer.tick(1);
+  flush();
+  // On SUCCEEDED the dialog closes completely.
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_progress'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_start'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_error'));
+  done();
+
+  mockTimer.uninstall();
+}
+
+// Test that canceling the dialog while exporting will also cancel the
+// export on the browser.
+export function runCancelExportTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy, done: Function) {
+  const progressCallback =
+      passwordManager.lastCallback.addPasswordsFileExportProgressListener!;
+
+  passwordManager.cancelExportPasswords = () => {
+    done();
+  };
+
+  const mockTimer = new MockTimer();
+  mockTimer.install();
+
+  // The initial dialog remains open for 100ms after export enters the
+  // in-progress state.
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+  progressCallback(
+      {status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+  // The progress bar only appears after 100ms.
+  mockTimer.tick(100);
+  flush();
+  assertTrue(exportDialog.shadowRoot!
+                 .querySelector<CrDialogElement>('#dialog_progress')!.open);
+  exportDialog.shadowRoot!
+      .querySelector<HTMLElement>('#cancel_progress_button')!.click();
+
+  flush();
+  // The dialog should be dismissed entirely.
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_progress'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_start'));
+  assertFalse(!!exportDialog.shadowRoot!.querySelector<CrDialogElement>(
+      '#dialog_error'));
+
+  mockTimer.uninstall();
+}
+
+export function runFireCloseEventAfterExportCompleteTest(
+    exportDialog: PasswordsExportDialogElement,
+    passwordManager: TestPasswordManagerProxy) {
+  const wait = eventToPromise('passwords-export-dialog-close', exportDialog);
+  exportDialog.shadowRoot!.querySelector<HTMLElement>(
+                              '#exportPasswordsButton')!.click();
+  passwordManager.lastCallback.addPasswordsFileExportProgressListener!
+      ({status: chrome.passwordsPrivate.ExportProgressStatus.IN_PROGRESS});
+  passwordManager.lastCallback.addPasswordsFileExportProgressListener!
+      ({status: chrome.passwordsPrivate.ExportProgressStatus.SUCCEEDED});
+  return wait;
+}
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.ts b/chrome/test/data/webui/settings/test_password_manager_proxy.ts
index 2a7a9a2..f83a24dc 100644
--- a/chrome/test/data/webui/settings/test_password_manager_proxy.ts
+++ b/chrome/test/data/webui/settings/test_password_manager_proxy.ts
@@ -362,7 +362,7 @@
    * Sets the value to be returned by getUrlCollection.
    */
   setGetUrlCollectionResponse(urlCollection:
-                                  chrome.passwordsPrivate.UrlCollection) {
+                                  chrome.passwordsPrivate.UrlCollection|null) {
     this.getUrlCollectionResponse_ = urlCollection;
   }
 
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index d9ba455..7aa9f16 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14446.0.0
\ No newline at end of file
+14447.0.0
\ No newline at end of file
diff --git a/chromeos/system/name_value_pairs_parser.h b/chromeos/system/name_value_pairs_parser.h
index 2783770a..06a286e 100644
--- a/chromeos/system/name_value_pairs_parser.h
+++ b/chromeos/system/name_value_pairs_parser.h
@@ -72,6 +72,7 @@
                            TestParseNameValuePairs);
   FRIEND_TEST_ALL_PREFIXES(NameValuePairsParser,
                            TestParseNameValuePairsInVpdDumpFormat);
+  FRIEND_TEST_ALL_PREFIXES(NameValuePairsParser, TestParseErrorInVpdDumpFormat);
   FRIEND_TEST_ALL_PREFIXES(NameValuePairsParser,
                            TestParseNameValuePairsInMachineInfoFormat);
   FRIEND_TEST_ALL_PREFIXES(NameValuePairsParser,
diff --git a/chromeos/system/name_value_pairs_parser_unittest.cc b/chromeos/system/name_value_pairs_parser_unittest.cc
index c04f82ef5..20a5b50 100644
--- a/chromeos/system/name_value_pairs_parser_unittest.cc
+++ b/chromeos/system/name_value_pairs_parser_unittest.cc
@@ -95,6 +95,22 @@
   EXPECT_EQ("value3", map["name3"]);
 }
 
+TEST(NameValuePairsParser, TestParseErrorInVpdDumpFormat) {
+  constexpr NameValuePairsFormat format = NameValuePairsFormat::kVpdDump;
+  NameValuePairsParser::NameValueMap map;
+  NameValuePairsParser parser(&map);
+
+  // Names must be quoted in VPD dump format. Unquoted names are ignored.
+  const std::string contents1 = R"(
+"name1"="value1"
+# RW_VPD execute error.
+)";
+  EXPECT_FALSE(parser.ParseNameValuePairs(contents1, format,
+                                          /*debug_source=*/"unit test"));
+  EXPECT_EQ(1U, map.size());
+  EXPECT_EQ("value1", map["name1"]);
+}
+
 TEST(NameValuePairsParser, TestParseNameValuePairsInMachineInfoFormat) {
   constexpr NameValuePairsFormat format = NameValuePairsFormat::kMachineInfo;
   NameValuePairsParser::NameValueMap map;
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn
index 289256c..6729fe4 100644
--- a/components/autofill_assistant/browser/BUILD.gn
+++ b/components/autofill_assistant/browser/BUILD.gn
@@ -382,10 +382,12 @@
     "actions/delete_password_action_unittest.cc",
     "actions/dispatch_js_event_action_unittest.cc",
     "actions/edit_password_action_unittest.cc",
+    "actions/expect_navigation_action_unittest.cc",
     "actions/fallback_handler/required_field_unittest.cc",
     "actions/fallback_handler/required_fields_fallback_handler_unittest.cc",
     "actions/generate_password_for_form_field_action_unittest.cc",
     "actions/get_element_status_action_unittest.cc",
+    "actions/navigate_action_unittest.cc",
     "actions/perform_on_single_element_action_unittest.cc",
     "actions/popup_message_action_unittest.cc",
     "actions/presave_generated_password_action_unittest.cc",
@@ -413,6 +415,7 @@
     "actions/use_credit_card_action_unittest.cc",
     "actions/wait_for_document_action_unittest.cc",
     "actions/wait_for_dom_action_unittest.cc",
+    "actions/wait_for_navigation_action_unittest.cc",
     "autofill_assistant_onboarding_fetcher_unittest.cc",
     "autofill_assistant_tts_controller_unittest.cc",
     "basic_interactions_unittest.cc",
diff --git a/components/autofill_assistant/browser/actions/expect_navigation_action_unittest.cc b/components/autofill_assistant/browser/actions/expect_navigation_action_unittest.cc
new file mode 100644
index 0000000..a12d877
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/expect_navigation_action_unittest.cc
@@ -0,0 +1,41 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/expect_navigation_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::Property;
+
+class ExpectNavigationActionTest : public testing::Test {
+ protected:
+  void Run() {
+    ActionProto action_proto;
+    *action_proto.mutable_expect_navigation() = proto_;
+    ExpectNavigationAction action(&mock_action_delegate_, action_proto);
+    action.ProcessAction(callback_.Get());
+  }
+
+  MockActionDelegate mock_action_delegate_;
+  base::MockCallback<Action::ProcessActionCallback> callback_;
+  ExpectNavigationProto proto_;
+};
+
+TEST_F(ExpectNavigationActionTest, ExpectNavigation) {
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+  Run();
+}
+
+}  // namespace
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/navigate_action_unittest.cc b/components/autofill_assistant/browser/actions/navigate_action_unittest.cc
new file mode 100644
index 0000000..884b451
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/navigate_action_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/navigate_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::Property;
+using ::testing::Return;
+
+class NavigateActionTest : public testing::Test {
+ public:
+  void SetUp() override {
+    web_contents_ = content::WebContentsTester::CreateTestWebContents(
+        &browser_context_, nullptr);
+    ON_CALL(mock_action_delegate_, GetWebContents)
+        .WillByDefault(Return(web_contents_.get()));
+  }
+
+ protected:
+  void Run() {
+    ActionProto action_proto;
+    *action_proto.mutable_navigate() = proto_;
+    NavigateAction action(&mock_action_delegate_, action_proto);
+    action.ProcessAction(callback_.Get());
+  }
+
+  content::BrowserTaskEnvironment task_environment_;
+  content::RenderViewHostTestEnabler rvh_test_enabler_;
+  content::TestBrowserContext browser_context_;
+  std::unique_ptr<content::WebContents> web_contents_;
+  MockActionDelegate mock_action_delegate_;
+  base::MockCallback<Action::ProcessActionCallback> callback_;
+  NavigateProto proto_;
+};
+
+TEST_F(NavigateActionTest, FailsForEmptyAction) {
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation).Times(0);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, UNSUPPORTED))));
+
+  Run();
+}
+
+TEST_F(NavigateActionTest, LoadsSpecifiedUrl) {
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation);
+  EXPECT_CALL(mock_action_delegate_, LoadURL(GURL("https://navigate.com")));
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  proto_.set_url("https://navigate.com");
+  Run();
+}
+
+TEST_F(NavigateActionTest, NavigatesBackwardIfPossible) {
+  content::WebContentsTester::For(web_contents_.get())
+      ->NavigateAndCommit(GURL("https://initial.com"));
+  content::WebContentsTester::For(web_contents_.get())
+      ->NavigateAndCommit(GURL("https://navigate.com"));
+
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  EXPECT_EQ(web_contents_->GetLastCommittedURL(), GURL("https://navigate.com"));
+  EXPECT_TRUE(web_contents_->GetController().CanGoBack());
+  proto_.set_go_backward(true);
+  Run();
+  content::WebContentsTester::For(web_contents_.get())
+      ->CommitPendingNavigation();
+  EXPECT_EQ(web_contents_->GetLastCommittedURL(), GURL("https://initial.com"));
+}
+
+TEST_F(NavigateActionTest, FailsIfNavigatingBackwardIsNotPossible) {
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation).Times(0);
+  EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+                                              PRECONDITION_FAILED))));
+
+  proto_.set_go_backward(true);
+  Run();
+}
+
+TEST_F(NavigateActionTest, NavigatesForwardIfPossible) {
+  content::WebContentsTester::For(web_contents_.get())
+      ->NavigateAndCommit(GURL("https://initial.com"));
+  content::WebContentsTester::For(web_contents_.get())
+      ->NavigateAndCommit(GURL("https://navigate.com"));
+  EXPECT_TRUE(web_contents_->GetController().CanGoBack());
+  web_contents_->GetController().GoBack();
+  content::WebContentsTester::For(web_contents_.get())
+      ->CommitPendingNavigation();
+
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation);
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  EXPECT_EQ(web_contents_->GetLastCommittedURL(), GURL("https://initial.com"));
+  EXPECT_TRUE(web_contents_->GetController().CanGoForward());
+  proto_.set_go_forward(true);
+  Run();
+  content::WebContentsTester::For(web_contents_.get())
+      ->CommitPendingNavigation();
+  EXPECT_EQ(web_contents_->GetLastCommittedURL(), GURL("https://navigate.com"));
+}
+
+TEST_F(NavigateActionTest, FailsIfNavigatingForwardIsNotPossible) {
+  EXPECT_CALL(mock_action_delegate_, ExpectNavigation).Times(0);
+  EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+                                              PRECONDITION_FAILED))));
+
+  proto_.set_go_forward(true);
+  Run();
+}
+
+}  // namespace
+}  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc b/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
index e4639e5..94c92a9 100644
--- a/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc
@@ -62,6 +62,8 @@
   MockWebController mock_web_controller_;
   WaitForDocumentProto proto_;
   ProcessedActionProto processed_action_;
+
+ private:
   std::unique_ptr<WaitForDocumentAction> action_;
 };
 
diff --git a/components/autofill_assistant/browser/actions/wait_for_navigation_action_unittest.cc b/components/autofill_assistant/browser/actions/wait_for_navigation_action_unittest.cc
new file mode 100644
index 0000000..e9f5a82
--- /dev/null
+++ b/components/autofill_assistant/browser/actions/wait_for_navigation_action_unittest.cc
@@ -0,0 +1,94 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/wait_for_navigation_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::Property;
+using ::testing::Return;
+
+class WaitForNavigationActionTest : public testing::Test {
+ protected:
+  WaitForNavigationActionTest()
+      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+  void Run() {
+    ActionProto action_proto;
+    *action_proto.mutable_wait_for_navigation() = proto_;
+    action_ = std::make_unique<WaitForNavigationAction>(&mock_action_delegate_,
+                                                        action_proto);
+    action_->ProcessAction(callback_.Get());
+  }
+
+  base::test::TaskEnvironment task_environment_;
+
+  MockActionDelegate mock_action_delegate_;
+  base::MockCallback<Action::ProcessActionCallback> callback_;
+  WaitForNavigationProto proto_;
+
+ private:
+  std::unique_ptr<WaitForNavigationAction> action_;
+};
+
+TEST_F(WaitForNavigationActionTest, FailsForUnexpectedNavigation) {
+  EXPECT_CALL(mock_action_delegate_, WaitForNavigation).WillOnce(Return(false));
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+  Run();
+}
+
+TEST_F(WaitForNavigationActionTest, TimesOutWithoutNavigation) {
+  EXPECT_CALL(mock_action_delegate_, WaitForNavigation).WillOnce(Return(true));
+  EXPECT_CALL(callback_,
+              Run(Pointee(Property(&ProcessedActionProto::status, TIMED_OUT))));
+
+  proto_.set_timeout_ms(1000);
+  Run();
+  task_environment_.FastForwardBy(base::Seconds(2));
+}
+
+TEST_F(WaitForNavigationActionTest, ReturnsErrorStatusForNavigationError) {
+  EXPECT_CALL(mock_action_delegate_, WaitForNavigation)
+      .WillOnce([](base::OnceCallback<void(bool)> callback) {
+        std::move(callback).Run(false);
+        return true;
+      });
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, NAVIGATION_ERROR))));
+
+  proto_.set_timeout_ms(1000);
+  Run();
+}
+
+TEST_F(WaitForNavigationActionTest, SucceedsForSuccessfulNavigation) {
+  EXPECT_CALL(mock_action_delegate_, WaitForNavigation)
+      .WillOnce([](base::OnceCallback<void(bool)> callback) {
+        std::move(callback).Run(true);
+        return true;
+      });
+  EXPECT_CALL(
+      callback_,
+      Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+  proto_.set_timeout_ms(1000);
+  Run();
+
+  // Should not crash. The callback has already been called.
+  task_environment_.FastForwardBy(base::Seconds(2));
+}
+
+}  // namespace
+}  // namespace autofill_assistant
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc
index ccfda4e3..9fccc243 100644
--- a/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -55,10 +55,10 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
 
 ContentSetting GetDefaultValue(const WebsiteSettingsInfo* info) {
-  const base::Value* initial_default = info->initial_default_value();
-  if (!initial_default)
+  const base::Value& initial_default = info->initial_default_value();
+  if (initial_default.is_none())
     return CONTENT_SETTING_DEFAULT;
-  return static_cast<ContentSetting>(initial_default->GetInt());
+  return static_cast<ContentSetting>(initial_default.GetInt());
 }
 
 ContentSetting GetDefaultValue(ContentSettingsType type) {
diff --git a/components/content_settings/core/browser/content_settings_info.cc b/components/content_settings/core/browser/content_settings_info.cc
index 836ae72a..88f44af 100644
--- a/components/content_settings/core/browser/content_settings_info.cc
+++ b/components/content_settings/core/browser/content_settings_info.cc
@@ -28,9 +28,9 @@
 ContentSettingsInfo::~ContentSettingsInfo() {}
 
 ContentSetting ContentSettingsInfo::GetInitialDefaultSetting() const {
-  const base::Value* initial_default =
+  const base::Value& initial_default =
       website_settings_info()->initial_default_value();
-  DCHECK(initial_default);
+  DCHECK(initial_default.is_int());
   return ValueToContentSetting(initial_default);
 }
 
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc
index 485aab0..4beba1869 100644
--- a/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -370,7 +370,7 @@
 
   for (const auto& it : filters_map) {
     const std::string& pattern_str = it.first;
-    const base::DictionaryValue& setting = it.second;
+    const base::Value& setting = it.second;
 
     ContentSettingsPattern pattern =
         ContentSettingsPattern::FromString(pattern_str);
diff --git a/components/content_settings/core/browser/content_settings_pref_unittest.cc b/components/content_settings/core/browser/content_settings_pref_unittest.cc
index f367417..adff32c 100644
--- a/components/content_settings/core/browser/content_settings_pref_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_pref_unittest.cc
@@ -114,16 +114,17 @@
       {kTestPatternCanonicalBeta, kTestPatternCanonicalBeta},
   };
 
-  auto original_pref_value = std::make_unique<base::DictionaryValue>();
+  base::Value original_pref_value(base::Value::Type::DICTIONARY);
   for (const auto* pattern : kTestOriginalPatterns) {
-    original_pref_value->SetKey(
+    original_pref_value.SetKey(
         pattern, CreateDummyContentSettingValue(pattern, /*expired=*/false));
   }
 
   TestingPrefServiceSimple prefs;
   prefs.registry()->RegisterDictionaryPref(kTestContentSettingPrefName);
-  prefs.SetUserPref(kTestContentSettingPrefName,
-                    std::move(original_pref_value));
+  prefs.SetUserPref(
+      kTestContentSettingPrefName,
+      base::Value::ToUniquePtrValue(std::move(original_pref_value)));
 
   PrefChangeRegistrar registrar;
   registrar.Init(&prefs);
@@ -177,20 +178,21 @@
 
   // Create two pre-existing entries, one that is expired and one that never
   // expires.
-  auto original_pref_value = std::make_unique<base::DictionaryValue>();
-  original_pref_value->SetKey(
+  base::Value original_pref_value(base::Value::Type::DICTIONARY);
+  original_pref_value.SetKey(
       kTestPatternCanonicalAlpha,
       CreateDummyContentSettingValue(kTestPatternCanonicalAlpha,
                                      /*expired=*/true));
-  original_pref_value->SetKey(
+  original_pref_value.SetKey(
       kTestPatternCanonicalBeta,
       CreateDummyContentSettingValue(kTestPatternCanonicalBeta,
                                      /*expired=*/false));
 
   TestingPrefServiceSimple prefs;
   prefs.registry()->RegisterDictionaryPref(kTestContentSettingPrefName);
-  prefs.SetUserPref(kTestContentSettingPrefName,
-                    std::move(original_pref_value));
+  prefs.SetUserPref(
+      kTestContentSettingPrefName,
+      base::Value::ToUniquePtrValue(std::move(original_pref_value)));
 
   PrefChangeRegistrar registrar;
   registrar.Init(&prefs);
@@ -232,7 +234,7 @@
 TEST(ContentSettingsPref, LegacyLastModifiedLoad) {
   constexpr char kPatternPair[] = "http://example.com,*";
 
-  auto original_pref_value = std::make_unique<base::DictionaryValue>();
+  base::Value original_pref_value(base::Value::Type::DICTIONARY);
   const base::Time last_modified =
       base::Time::FromInternalValue(13189876543210000);
 
@@ -244,12 +246,13 @@
   pref_value.SetKey(kSettingKey, base::Value(CONTENT_SETTING_BLOCK));
   pref_value.SetKey(kExpirationKey, base::Value("0"));
 
-  original_pref_value->SetKey(kPatternPair, std::move(pref_value));
+  original_pref_value.SetKey(kPatternPair, std::move(pref_value));
 
   TestingPrefServiceSimple prefs;
   prefs.registry()->RegisterDictionaryPref(kTestContentSettingPrefName);
-  prefs.SetUserPref(kTestContentSettingPrefName,
-                    std::move(original_pref_value));
+  prefs.SetUserPref(
+      kTestContentSettingPrefName,
+      base::Value::ToUniquePtrValue(std::move(original_pref_value)));
 
   PrefChangeRegistrar registrar;
   registrar.Init(&prefs);
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc
index 2a48c11..c3b9e449 100644
--- a/components/content_settings/core/browser/content_settings_registry.cc
+++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -659,8 +659,7 @@
   // Ensure that nothing has been registered yet for the given type.
   DCHECK(!website_settings_registry_->Get(type));
 
-  std::unique_ptr<base::Value> default_value(
-      new base::Value(static_cast<int>(initial_default_value)));
+  base::Value default_value(static_cast<int>(initial_default_value));
   const WebsiteSettingsInfo* website_settings_info =
       website_settings_registry_->Register(
           type, name, std::move(default_value), sync_status,
diff --git a/components/content_settings/core/browser/content_settings_registry_unittest.cc b/components/content_settings/core/browser/content_settings_registry_unittest.cc
index bdb81f19..6fa2df8 100644
--- a/components/content_settings/core/browser/content_settings_registry_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -84,9 +84,9 @@
             website_settings_info->pref_name());
   EXPECT_EQ("profile.default_content_setting_values.cookies",
             website_settings_info->default_value_pref_name());
-  ASSERT_TRUE(website_settings_info->initial_default_value()->is_int());
+  ASSERT_TRUE(website_settings_info->initial_default_value().is_int());
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            website_settings_info->initial_default_value()->GetInt());
+            website_settings_info->initial_default_value().GetInt());
 #if defined(OS_ANDROID) || defined(OS_IOS)
   EXPECT_EQ(PrefRegistry::NO_REGISTRATION_FLAGS,
             website_settings_info->GetPrefRegistrationFlags());
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
index 6f8f8e6..5c9e5cf 100644
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -136,8 +136,9 @@
         return value;
       case ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE:
         ContentSetting setting = content_settings::ValueToContentSetting(value);
-        const base::Value* initial_value = content_settings_info
-            ->website_settings_info()->initial_default_value();
+        const base::Value& initial_value =
+            content_settings_info->website_settings_info()
+                ->initial_default_value();
         ContentSetting initial_setting =
             content_settings::ValueToContentSetting(initial_value);
         if (content_settings::IsMorePermissive(setting, initial_setting))
@@ -413,18 +414,17 @@
 void HostContentSettingsMap::SetDefaultContentSetting(
     ContentSettingsType content_type,
     ContentSetting setting) {
-  std::unique_ptr<base::Value> value;
+  base::Value value;
   // A value of CONTENT_SETTING_DEFAULT implies deleting the content setting.
   if (setting != CONTENT_SETTING_DEFAULT) {
     DCHECK(content_settings::ContentSettingsRegistry::GetInstance()
                ->Get(content_type)
                ->IsDefaultSettingValid(setting));
-    value = std::make_unique<base::Value>(setting);
+    value = base::Value(setting);
   }
-  SetWebsiteSettingCustomScope(
-      ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
-      content_type,
-      content_settings::FromNullableUniquePtrValue(std::move(value)));
+  SetWebsiteSettingCustomScope(ContentSettingsPattern::Wildcard(),
+                               ContentSettingsPattern::Wildcard(), content_type,
+                               std::move(value));
 }
 
 void HostContentSettingsMap::SetWebsiteSettingDefaultScope(
diff --git a/components/content_settings/core/browser/website_settings_info.cc b/components/content_settings/core/browser/website_settings_info.cc
index 1a0ae71..f5cba1dc 100644
--- a/components/content_settings/core/browser/website_settings_info.cc
+++ b/components/content_settings/core/browser/website_settings_info.cc
@@ -27,14 +27,13 @@
 
 namespace content_settings {
 
-WebsiteSettingsInfo::WebsiteSettingsInfo(
-    ContentSettingsType type,
-    const std::string& name,
-    std::unique_ptr<base::Value> initial_default_value,
-    SyncStatus sync_status,
-    LossyStatus lossy_status,
-    ScopingType scoping_type,
-    IncognitoBehavior incognito_behavior)
+WebsiteSettingsInfo::WebsiteSettingsInfo(ContentSettingsType type,
+                                         const std::string& name,
+                                         base::Value initial_default_value,
+                                         SyncStatus sync_status,
+                                         LossyStatus lossy_status,
+                                         ScopingType scoping_type,
+                                         IncognitoBehavior incognito_behavior)
     : type_(type),
       name_(name),
       pref_name_(GetPreferenceName(name, kPrefPrefix)),
@@ -44,13 +43,14 @@
       lossy_status_(lossy_status),
       scoping_type_(scoping_type),
       incognito_behavior_(incognito_behavior) {
-  // For legacy reasons the default value is currently restricted to be an int.
+  // For legacy reasons the default value is currently restricted to be an int
+  // or none.
   // TODO(raymes): We should migrate the underlying pref to be a dictionary
   // rather than an int.
-  DCHECK(!initial_default_value_ || initial_default_value_->is_int());
+  DCHECK(initial_default_value_.is_none() || initial_default_value_.is_int());
 }
 
-WebsiteSettingsInfo::~WebsiteSettingsInfo() {}
+WebsiteSettingsInfo::~WebsiteSettingsInfo() = default;
 
 uint32_t WebsiteSettingsInfo::GetPrefRegistrationFlags() const {
   uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS;
diff --git a/components/content_settings/core/browser/website_settings_info.h b/components/content_settings/core/browser/website_settings_info.h
index 52e58be..858cdb7 100644
--- a/components/content_settings/core/browser/website_settings_info.h
+++ b/components/content_settings/core/browser/website_settings_info.h
@@ -10,12 +10,9 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 
-namespace base {
-class Value;
-}  // namespace base
-
 namespace content_settings {
 
 // This class stores the properties related to a website setting.
@@ -68,7 +65,7 @@
 
   WebsiteSettingsInfo(ContentSettingsType type,
                       const std::string& name,
-                      std::unique_ptr<base::Value> initial_default_value,
+                      base::Value initial_default_value,
                       SyncStatus sync_status,
                       LossyStatus lossy_status,
                       ScopingType scoping_type,
@@ -86,8 +83,8 @@
   const std::string& default_value_pref_name() const {
     return default_value_pref_name_;
   }
-  const base::Value* initial_default_value() const {
-    return initial_default_value_.get();
+  const base::Value& initial_default_value() const {
+    return initial_default_value_;
   }
 
   uint32_t GetPrefRegistrationFlags() const;
@@ -103,7 +100,7 @@
 
   const std::string pref_name_;
   const std::string default_value_pref_name_;
-  const std::unique_ptr<base::Value> initial_default_value_;
+  const base::Value initial_default_value_;
   const SyncStatus sync_status_;
   const LossyStatus lossy_status_;
   const ScopingType scoping_type_;
diff --git a/components/content_settings/core/browser/website_settings_registry.cc b/components/content_settings/core/browser/website_settings_registry.cc
index 99e460e..c196b5f 100644
--- a/components/content_settings/core/browser/website_settings_registry.cc
+++ b/components/content_settings/core/browser/website_settings_registry.cc
@@ -30,7 +30,7 @@
   Init();
 }
 
-WebsiteSettingsRegistry::~WebsiteSettingsRegistry() {}
+WebsiteSettingsRegistry::~WebsiteSettingsRegistry() = default;
 
 void WebsiteSettingsRegistry::ResetForTest() {
   website_settings_info_.clear();
@@ -57,13 +57,12 @@
 const WebsiteSettingsInfo* WebsiteSettingsRegistry::Register(
     ContentSettingsType type,
     const std::string& name,
-    std::unique_ptr<base::Value> initial_default_value,
+    base::Value initial_default_value,
     WebsiteSettingsInfo::SyncStatus sync_status,
     WebsiteSettingsInfo::LossyStatus lossy_status,
     WebsiteSettingsInfo::ScopingType scoping_type,
     Platforms platform,
     WebsiteSettingsInfo::IncognitoBehavior incognito_behavior) {
-
 #if defined(OS_WIN)
   if (!(platform & PLATFORM_WINDOWS))
     return nullptr;
@@ -122,60 +121,62 @@
 
   // Website settings.
   Register(ContentSettingsType::AUTO_SELECT_CERTIFICATE,
-           "auto-select-certificate", nullptr, WebsiteSettingsInfo::UNSYNCABLE,
-           WebsiteSettingsInfo::NOT_LOSSY,
+           "auto-select-certificate", base::Value(),
+           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            ALL_PLATFORMS, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  Register(ContentSettingsType::SSL_CERT_DECISIONS, "ssl-cert-decisions",
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
+           WebsiteSettingsInfo::NOT_LOSSY,
+           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
+           DESKTOP | PLATFORM_ANDROID,
+           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  Register(ContentSettingsType::APP_BANNER, "app-banner", base::Value(),
+           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
+           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
+           DESKTOP | PLATFORM_ANDROID,
+           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   Register(
-      ContentSettingsType::SSL_CERT_DECISIONS, "ssl-cert-decisions", nullptr,
-      WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+      ContentSettingsType::SITE_ENGAGEMENT, "site-engagement", base::Value(),
+      WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
       WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
       DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::APP_BANNER, "app-banner", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
-           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
-           DESKTOP | PLATFORM_ANDROID,
-           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::SITE_ENGAGEMENT, "site-engagement", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
-           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
-           DESKTOP | PLATFORM_ANDROID,
-           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::USB_CHOOSER_DATA, "usb-chooser-data", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
-           WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
-           DESKTOP | PLATFORM_ANDROID,
-           WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
+  Register(
+      ContentSettingsType::USB_CHOOSER_DATA, "usb-chooser-data", base::Value(),
+      WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+      WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP | PLATFORM_ANDROID,
+      WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::IMPORTANT_SITE_INFO, "important-site-info",
-           nullptr, WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
+           WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            DESKTOP | PLATFORM_ANDROID,
            WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::PERMISSION_AUTOBLOCKER_DATA,
-           "permission-autoblocking-data", nullptr,
+           "permission-autoblocking-data", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            DESKTOP | PLATFORM_ANDROID,
            WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::PASSWORD_PROTECTION, "password-protection",
-           nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
            WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            ALL_PLATFORMS, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   // Set when an origin is activated for subresource filtering and the
   // associated UI is shown to the user. Cleared when a site is de-activated or
   // the first URL matching the origin is removed from history.
-  Register(ContentSettingsType::ADS_DATA, "subresource-filter-data", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
-           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
-           DESKTOP | PLATFORM_ANDROID,
-           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::MEDIA_ENGAGEMENT, "media-engagement", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
-           WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
-           DESKTOP | PLATFORM_ANDROID,
-           WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::CLIENT_HINTS, "client-hints", nullptr,
+  Register(
+      ContentSettingsType::ADS_DATA, "subresource-filter-data", base::Value(),
+      WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+      WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
+      DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  Register(
+      ContentSettingsType::MEDIA_ENGAGEMENT, "media-engagement", base::Value(),
+      WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
+      WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
+      DESKTOP | PLATFORM_ANDROID, WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  Register(ContentSettingsType::CLIENT_HINTS, "client-hints", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            DESKTOP | PLATFORM_ANDROID,
@@ -183,73 +184,75 @@
   // Set to keep track of dismissals without user's interaction for intent
   // picker UI.
   Register(ContentSettingsType::INTENT_PICKER_DISPLAY,
-           "intent-picker-auto-display", nullptr,
+           "intent-picker-auto-display", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            DESKTOP, WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::SERIAL_CHOOSER_DATA, "serial-chooser-data",
-           nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
            WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::HID_CHOOSER_DATA, "hid-chooser-data", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+  Register(ContentSettingsType::HID_CHOOSER_DATA, "hid-chooser-data",
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
+           WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::INSTALLED_WEB_APP_METADATA,
-           "installed-web-app-metadata", nullptr,
+           "installed-web-app-metadata", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(
       ContentSettingsType::BLUETOOTH_CHOOSER_DATA, "bluetooth-chooser-data",
-      /*initial_default_value=*/nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+      /*initial_default_value=*/base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
       WebsiteSettingsInfo::NOT_LOSSY,
       WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP | PLATFORM_ANDROID,
       WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::SAFE_BROWSING_URL_CHECK_DATA,
-           "safe-browsing-url-check-data", nullptr,
+           "safe-browsing-url-check-data", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::PERMISSION_AUTOREVOCATION_DATA,
-           "permission-autorevocation-data", nullptr,
+           "permission-autorevocation-data", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
            DESKTOP | PLATFORM_ANDROID,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::FILE_SYSTEM_ACCESS_CHOOSER_DATA,
-           "file-system-access-chooser-data", nullptr,
+           "file-system-access-chooser-data", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::FILE_SYSTEM_LAST_PICKED_DIRECTORY,
-           "file-system-last-picked-directory", nullptr,
+           "file-system-last-picked-directory", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::FEDERATED_IDENTITY_SHARING, "webid-share",
-           nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
            WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::FEDERATED_IDENTITY_REQUEST, "webid-request",
-           nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
            WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::HTTP_ALLOWED, "http-allowed", nullptr,
+  Register(ContentSettingsType::HTTP_ALLOWED, "http-allowed", base::Value(),
            WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_WITH_EMBEDDED_EXCEPTIONS_SCOPE,
            DESKTOP | PLATFORM_ANDROID,
            WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
-  Register(ContentSettingsType::FORMFILL_METADATA, "formfill-metadata", nullptr,
-           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::LOSSY,
+  Register(ContentSettingsType::FORMFILL_METADATA, "formfill-metadata",
+           base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
+           WebsiteSettingsInfo::LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   Register(ContentSettingsType::FEDERATED_IDENTITY_ACTIVE_SESSION,
-           "webid-active-session", nullptr, WebsiteSettingsInfo::UNSYNCABLE,
-           WebsiteSettingsInfo::NOT_LOSSY,
+           "webid-active-session", base::Value(),
+           WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
            WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
            WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
 }
diff --git a/components/content_settings/core/browser/website_settings_registry.h b/components/content_settings/core/browser/website_settings_registry.h
index 6805e29..cac992b 100644
--- a/components/content_settings/core/browser/website_settings_registry.h
+++ b/components/content_settings/core/browser/website_settings_registry.h
@@ -71,7 +71,7 @@
   const WebsiteSettingsInfo* Register(
       ContentSettingsType type,
       const std::string& name,
-      std::unique_ptr<base::Value> initial_default_value,
+      base::Value initial_default_value,
       WebsiteSettingsInfo::SyncStatus sync_status,
       WebsiteSettingsInfo::LossyStatus lossy_status,
       WebsiteSettingsInfo::ScopingType scoping_type,
diff --git a/components/content_settings/core/browser/website_settings_registry_unittest.cc b/components/content_settings/core/browser/website_settings_registry_unittest.cc
index 89200b97..3e3bfdb 100644
--- a/components/content_settings/core/browser/website_settings_registry_unittest.cc
+++ b/components/content_settings/core/browser/website_settings_registry_unittest.cc
@@ -48,8 +48,8 @@
             info);
 
   // Register a new setting.
-  registry()->Register(static_cast<ContentSettingsType>(10), "test", nullptr,
-                       WebsiteSettingsInfo::UNSYNCABLE,
+  registry()->Register(static_cast<ContentSettingsType>(10), "test",
+                       base::Value(), WebsiteSettingsInfo::UNSYNCABLE,
                        WebsiteSettingsInfo::LOSSY,
                        WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
                        WebsiteSettingsRegistry::ALL_PLATFORMS,
@@ -83,24 +83,24 @@
             info->pref_name());
   EXPECT_EQ("profile.default_content_setting_values.auto_select_certificate",
             info->default_value_pref_name());
-  ASSERT_FALSE(info->initial_default_value());
+  ASSERT_TRUE(info->initial_default_value().is_none());
   EXPECT_EQ(PrefRegistry::NO_REGISTRATION_FLAGS,
             info->GetPrefRegistrationFlags());
 
   // Register a new setting.
-  registry()->Register(
-      static_cast<ContentSettingsType>(10), "test",
-      std::make_unique<base::Value>(999), WebsiteSettingsInfo::SYNCABLE,
-      WebsiteSettingsInfo::LOSSY, WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
-      WebsiteSettingsRegistry::ALL_PLATFORMS,
-      WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  registry()->Register(static_cast<ContentSettingsType>(10), "test",
+                       base::Value(999), WebsiteSettingsInfo::SYNCABLE,
+                       WebsiteSettingsInfo::LOSSY,
+                       WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
+                       WebsiteSettingsRegistry::ALL_PLATFORMS,
+                       WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
   info = registry()->Get(static_cast<ContentSettingsType>(10));
   ASSERT_TRUE(info);
   EXPECT_EQ("profile.content_settings.exceptions.test", info->pref_name());
   EXPECT_EQ("profile.default_content_setting_values.test",
             info->default_value_pref_name());
-  ASSERT_TRUE(info->initial_default_value()->is_int());
-  EXPECT_EQ(999, info->initial_default_value()->GetInt());
+  ASSERT_TRUE(info->initial_default_value().is_int());
+  EXPECT_EQ(999, info->initial_default_value().GetInt());
 #if defined(OS_ANDROID) || defined(OS_IOS)
   EXPECT_EQ(PrefRegistry::LOSSY_PREF, info->GetPrefRegistrationFlags());
 #else
@@ -115,12 +115,12 @@
 }
 
 TEST_F(WebsiteSettingsRegistryTest, Iteration) {
-  registry()->Register(
-      static_cast<ContentSettingsType>(10), "test",
-      std::make_unique<base::Value>(999), WebsiteSettingsInfo::SYNCABLE,
-      WebsiteSettingsInfo::LOSSY, WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
-      WebsiteSettingsRegistry::ALL_PLATFORMS,
-      WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
+  registry()->Register(static_cast<ContentSettingsType>(10), "test",
+                       base::Value(999), WebsiteSettingsInfo::SYNCABLE,
+                       WebsiteSettingsInfo::LOSSY,
+                       WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
+                       WebsiteSettingsRegistry::ALL_PLATFORMS,
+                       WebsiteSettingsInfo::INHERIT_IN_INCOGNITO);
 
   bool found = false;
   for (const WebsiteSettingsInfo* info : *registry()) {
diff --git a/components/crash/android/BUILD.gn b/components/crash/android/BUILD.gn
index a7d77bd..415e5269 100644
--- a/components/crash/android/BUILD.gn
+++ b/components/crash/android/BUILD.gn
@@ -24,6 +24,7 @@
   deps = [
     "//base:base_java",
     "//components/minidump_uploader:minidump_uploader_java",
+    "//components/version_info/android:version_constants_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
@@ -31,10 +32,24 @@
   sources = [
     "java/src/org/chromium/components/crash/LogcatCrashExtractor.java",
     "java/src/org/chromium/components/crash/MinidumpLogcatPrepender.java",
+    "java/src/org/chromium/components/crash/PureJavaExceptionReporter.java",
   ]
   sources += _jni_sources
 }
 
+android_library("javatests") {
+  testonly = true
+  sources = [ "javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java" ]
+  deps = [
+    ":java",
+    "//base:base_java_test_support",
+    "//components/minidump_uploader:minidump_uploader_java_test_support",
+    "//content/public/test/android:content_java_test_support",
+    "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/junit",
+  ]
+}
+
 java_library("junit") {
   # Skip platform checks since Robolectric depends on requires_android targets.
   bypass_platform_checks = true
diff --git a/components/crash/android/DEPS b/components/crash/android/DEPS
index 61ccef5..1023fa8 100644
--- a/components/crash/android/DEPS
+++ b/components/crash/android/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/crash/android/jni_headers",
   "+components/minidump_uploader/android",
+  "+components/version_info/android",
   "+third_party/crashpad",
 ]
diff --git a/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java b/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java
new file mode 100644
index 0000000..0b4b743
--- /dev/null
+++ b/components/crash/android/java/src/org/chromium/components/crash/PureJavaExceptionReporter.java
@@ -0,0 +1,199 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.crash;
+
+import android.annotation.SuppressLint;
+import android.os.Build;
+import android.util.Log;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.base.BuildInfo;
+import org.chromium.base.CommandLine;
+import org.chromium.base.ContextUtils;
+import org.chromium.base.PiiElider;
+import org.chromium.base.StrictModeContext;
+import org.chromium.base.annotations.MainDex;
+import org.chromium.components.version_info.VersionInfo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+/**
+ * Creates a crash report and uploads it to crash server if there is a Java exception.
+ *
+ * This class is written in pure Java, so it can handle exception happens before native is loaded.
+ */
+@MainDex
+public abstract class PureJavaExceptionReporter
+        implements PureJavaExceptionHandler.JavaExceptionReporter {
+    // report fields, please keep the name sync with MIME blocks in breakpad_linux.cc
+    public static final String CHANNEL = "channel";
+    public static final String VERSION = "ver";
+    public static final String PRODUCT = "prod";
+    public static final String ANDROID_BUILD_ID = "android_build_id";
+    public static final String ANDROID_BUILD_FP = "android_build_fp";
+    public static final String SDK = "sdk";
+    public static final String DEVICE = "device";
+    public static final String GMS_CORE_VERSION = "gms_core_version";
+    public static final String INSTALLER_PACKAGE_NAME = "installer_package_name";
+    public static final String ABI_NAME = "abi_name";
+    public static final String PACKAGE = "package";
+    public static final String MODEL = "model";
+    public static final String BRAND = "brand";
+    public static final String BOARD = "board";
+    public static final String EXCEPTION_INFO = "exception_info";
+    public static final String PROCESS_TYPE = "ptype";
+    public static final String EARLY_JAVA_EXCEPTION = "early_java_exception";
+    public static final String CUSTOM_THEMES = "custom_themes";
+    public static final String RESOURCES_VERSION = "resources_version";
+
+    private static final String DUMP_LOCATION_SWITCH = "breakpad-dump-location";
+    private static final String CRASH_DUMP_DIR = "Crash Reports";
+    private static final String FILE_PREFIX = "chromium-browser-minidump-";
+    private static final String FILE_SUFFIX = ".dmp";
+    private static final String RN = "\r\n";
+    private static final String FORM_DATA_MESSAGE = "Content-Disposition: form-data; name=\"";
+
+    private boolean mUpload;
+    protected File mMinidumpFile;
+    private FileOutputStream mMinidumpFileStream;
+    private final String mLocalId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
+    private final String mBoundary = "------------" + UUID.randomUUID() + RN;
+
+    @Override
+    public void createAndUploadReport(Throwable javaException) {
+        // It is OK to do IO in main thread when we know there is a crash happens.
+        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
+            createReport(javaException);
+            flushToFile();
+            uploadReport();
+        }
+    }
+
+    private void addPairedString(String messageType, String messageData) {
+        addString(mBoundary);
+        addString(FORM_DATA_MESSAGE + messageType + "\"");
+        addString(RN + RN + messageData + RN);
+    }
+
+    private void addString(String s) {
+        try {
+            mMinidumpFileStream.write(ApiCompatibilityUtils.getBytesUtf8(s));
+        } catch (IOException e) {
+            // Nothing we can do here.
+        }
+    }
+
+    @SuppressLint("WrongConstant")
+    private void createReport(Throwable javaException) {
+        try {
+            String minidumpFileName = FILE_PREFIX + mLocalId + FILE_SUFFIX;
+            File minidumpDir =
+                    new File(ContextUtils.getApplicationContext().getCacheDir(), CRASH_DUMP_DIR);
+            // Tests disable minidump uploading by not creating the minidump directory.
+            mUpload = minidumpDir.exists();
+            String overrideMinidumpDirPath =
+                    CommandLine.getInstance().getSwitchValue(DUMP_LOCATION_SWITCH);
+            if (overrideMinidumpDirPath != null) {
+                minidumpDir = new File(overrideMinidumpDirPath);
+                minidumpDir.mkdirs();
+            }
+            mMinidumpFile = new File(minidumpDir, minidumpFileName);
+            mMinidumpFileStream = new FileOutputStream(mMinidumpFile);
+        } catch (FileNotFoundException e) {
+            mMinidumpFile = null;
+            mMinidumpFileStream = null;
+            return;
+        }
+
+        String processName = ContextUtils.getProcessName();
+        if (processName == null || !processName.contains(":")) {
+            processName = "browser";
+        }
+
+        BuildInfo buildInfo = BuildInfo.getInstance();
+        addPairedString(PRODUCT, getProductName());
+        addPairedString(PROCESS_TYPE, processName);
+        addPairedString(DEVICE, Build.DEVICE);
+        addPairedString(VERSION, VersionInfo.getProductVersion());
+        addPairedString(CHANNEL, getChannel());
+        addPairedString(ANDROID_BUILD_ID, Build.ID);
+        addPairedString(MODEL, Build.MODEL);
+        addPairedString(BRAND, Build.BRAND);
+        addPairedString(BOARD, Build.BOARD);
+        addPairedString(ANDROID_BUILD_FP, buildInfo.androidBuildFingerprint);
+        addPairedString(SDK, String.valueOf(Build.VERSION.SDK_INT));
+        addPairedString(GMS_CORE_VERSION, buildInfo.gmsVersionCode);
+        addPairedString(INSTALLER_PACKAGE_NAME, buildInfo.installerPackageName);
+        addPairedString(ABI_NAME, buildInfo.abiString);
+        addPairedString(EXCEPTION_INFO,
+                PiiElider.sanitizeStacktrace(Log.getStackTraceString(javaException)));
+        addPairedString(EARLY_JAVA_EXCEPTION, "true");
+        addPairedString(PACKAGE,
+                String.format("%s v%s (%s)", BuildInfo.getFirebaseAppId(), buildInfo.versionCode,
+                        buildInfo.versionName));
+        addPairedString(CUSTOM_THEMES, buildInfo.customThemes);
+        addPairedString(RESOURCES_VERSION, buildInfo.resourcesVersion);
+
+        AtomicReferenceArray<String> values = CrashKeys.getInstance().getValues();
+        for (int i = 0; i < values.length(); i++) {
+            String value = values.get(i);
+            if (value != null) addPairedString(CrashKeys.getKey(i), value);
+        }
+
+        addString(mBoundary);
+    }
+
+    private void flushToFile() {
+        if (mMinidumpFileStream == null) {
+            return;
+        }
+        try {
+            mMinidumpFileStream.flush();
+            mMinidumpFileStream.close();
+        } catch (Throwable e) {
+            mMinidumpFile = null;
+        } finally {
+            mMinidumpFileStream = null;
+        }
+    }
+
+    private static String getChannel() {
+        if (VersionInfo.isCanaryBuild()) {
+            return "canary";
+        }
+        if (VersionInfo.isDevBuild()) {
+            return "dev";
+        }
+        if (VersionInfo.isBetaBuild()) {
+            return "beta";
+        }
+        // An empty string indicates the stable channel.
+        return "";
+    }
+
+    private void uploadReport() {
+        if (mMinidumpFile == null || !mUpload) return;
+        LogcatCrashExtractor logcatExtractor = new LogcatCrashExtractor();
+        mMinidumpFile = logcatExtractor.attachLogcatToMinidump(mMinidumpFile);
+        uploadMinidump(mMinidumpFile);
+    }
+
+    /**
+     * @return the product name to be used in the crash report.
+     */
+    protected abstract String getProductName();
+
+    /**
+     * Attempt uploading the given {@code minidump} report immediately.
+     *
+     * @param minidump the minidump file to be uploaded.
+     */
+    protected abstract void uploadMinidump(File minidump);
+}
diff --git a/components/crash/android/javatests/src/org/chromium/components/crash/DEPS b/components/crash/android/javatests/src/org/chromium/components/crash/DEPS
new file mode 100644
index 0000000..877e2a4
--- /dev/null
+++ b/components/crash/android/javatests/src/org/chromium/components/crash/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+content/public/test/android",
+]
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporterTest.java b/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java
similarity index 88%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporterTest.java
rename to components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java
index 9588892..6e0cfbf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporterTest.java
+++ b/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.crash;
+package org.chromium.components.crash;
 
 import androidx.test.filters.SmallTest;
 
@@ -12,9 +12,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.components.crash.CrashKeyIndex;
-import org.chromium.components.crash.CrashKeys;
-import org.chromium.components.crash.LogcatCrashExtractor;
 import org.chromium.components.minidump_uploader.CrashTestRule;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -32,21 +29,27 @@
     public CrashTestRule mTestRule = new CrashTestRule();
 
     private static class TestPureJavaExceptionReporter extends PureJavaExceptionReporter {
-        boolean mReportUploaded;
+        private boolean mReportUploaded;
+        private File mMinidump;
 
         @Override
-        public void uploadReport() {
-            if (mMinidumpFile == null) {
-                mReportUploaded = false;
-                return;
-            }
-            mMinidumpFile = new LogcatCrashExtractor().attachLogcatToMinidump(mMinidumpFile);
-            mReportUploaded = true;
+        protected String getProductName() {
+            return "Test";
+        }
+
+        @Override
+        protected void uploadMinidump(File minidump) {
+            mMinidump = minidump;
+            mReportUploaded = (minidump != null);
         }
 
         public boolean reportUploaded() {
             return mReportUploaded;
         }
+
+        public File getMinidumpFile() {
+            return mMinidump;
+        }
     }
 
     private static final String EXCEPTION_NAME = "EXCEPTION_NAME";
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn
index b570939..a64489c 100644
--- a/components/password_manager/core/browser/BUILD.gn
+++ b/components/password_manager/core/browser/BUILD.gn
@@ -108,6 +108,8 @@
     "leak_detection_dialog_utils.h",
     "login_database.cc",
     "login_database.h",
+    "login_database_async_helper.cc",
+    "login_database_async_helper.h",
     "manage_passwords_referrer.h",
     "move_password_to_account_store_helper.cc",
     "move_password_to_account_store_helper.h",
diff --git a/components/password_manager/core/browser/login_database_async_helper.cc b/components/password_manager/core/browser/login_database_async_helper.cc
new file mode 100644
index 0000000..34791b4
--- /dev/null
+++ b/components/password_manager/core/browser/login_database_async_helper.cc
@@ -0,0 +1,450 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/login_database_async_helper.h"
+
+#include "base/bind.h"
+#include "base/task/sequenced_task_runner.h"
+#include "components/password_manager/core/browser/login_database.h"
+#include "components/password_manager/core/browser/sync/password_sync_bridge.h"
+#include "components/sync/model/client_tag_based_model_type_processor.h"
+#include "components/sync/model/model_type_controller_delegate.h"
+
+namespace password_manager {
+
+namespace {
+
+constexpr base::TimeDelta kSyncTaskTimeout = base::Seconds(30);
+
+}  // namespace
+
+LoginDatabaseAsyncHelper::LoginDatabaseAsyncHelper(
+    std::unique_ptr<LoginDatabase> login_db,
+    std::unique_ptr<UnsyncedCredentialsDeletionNotifier> notifier,
+    scoped_refptr<base::SequencedTaskRunner> main_task_runner)
+    : login_db_(std::move(login_db)),
+      deletion_notifier_(std::move(notifier)),
+      main_task_runner_(std::move(main_task_runner)) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+  DCHECK(login_db_);
+  DCHECK(main_task_runner_);
+}
+
+LoginDatabaseAsyncHelper::~LoginDatabaseAsyncHelper() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+bool LoginDatabaseAsyncHelper::Initialize(
+    PasswordStoreBackend::RemoteChangesReceived remote_form_changes_received,
+    base::RepeatingClosure sync_enabled_or_disabled_cb) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  remote_forms_changes_received_callback_ =
+      std::move(remote_form_changes_received);
+
+  bool success = true;
+  if (!login_db_->Init()) {
+    login_db_.reset();
+    // The initialization should be continued, because PasswordSyncBridge
+    // has to be initialized even if database initialization failed.
+    success = false;
+    LOG(ERROR) << "Could not create/open login database.";
+  }
+  if (success) {
+    login_db_->SetDeletionsHaveSyncedCallback(base::BindRepeating(
+        &LoginDatabaseAsyncHelper::NotifyDeletionsHaveSynced,
+        weak_ptr_factory_.GetWeakPtr()));
+
+    // Delay the actual reporting by 30 seconds, to ensure it doesn't happen
+    // during the "hot phase" of Chrome startup.
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&LoginDatabaseAsyncHelper::ReportMetrics,
+                       weak_ptr_factory_.GetWeakPtr()),
+        base::Seconds(30));
+  }
+
+  sync_bridge_ = std::make_unique<PasswordSyncBridge>(
+      std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
+          syncer::PASSWORDS, base::DoNothing()),
+      static_cast<PasswordStoreSync*>(this),
+      std::move(sync_enabled_or_disabled_cb));
+
+  return success;
+}
+
+LoginsResult LoginDatabaseAsyncHelper::GetAllLogins() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  PrimaryKeyToFormMap key_to_form_map;
+
+  if (!login_db_ || login_db_->GetAllLogins(&key_to_form_map) !=
+                        FormRetrievalResult::kSuccess)
+    return {};
+
+  std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
+  obtained_forms.reserve(key_to_form_map.size());
+  for (auto& pair : key_to_form_map) {
+    obtained_forms.push_back(std::move(pair.second));
+  }
+  return obtained_forms;
+}
+
+LoginsResult LoginDatabaseAsyncHelper::GetAutofillableLogins() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  std::vector<std::unique_ptr<PasswordForm>> results;
+  if (!login_db_ || !login_db_->GetAutofillableLogins(&results))
+    return {};
+  return results;
+}
+
+LoginsResult LoginDatabaseAsyncHelper::FillMatchingLogins(
+    const std::vector<PasswordFormDigest>& forms,
+    bool include_psl) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  std::vector<std::unique_ptr<PasswordForm>> results;
+  for (const auto& form : forms) {
+    std::vector<std::unique_ptr<PasswordForm>> matched_forms;
+    if (login_db_ && !login_db_->GetLogins(form, include_psl, &matched_forms))
+      continue;
+    results.insert(results.end(),
+                   std::make_move_iterator(matched_forms.begin()),
+                   std::make_move_iterator(matched_forms.end()));
+  }
+  return results;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::AddLogin(
+    const PasswordForm& form) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BeginTransaction();
+  PasswordStoreChangeList changes = AddLoginSync(form, /*error=*/nullptr);
+  if (sync_bridge_ && !changes.empty())
+    sync_bridge_->ActOnPasswordStoreChanges(changes);
+  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
+  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
+  // because sync codebase needs to update metadata atomically together with
+  // the login data.
+  CommitTransaction();
+  return changes;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::UpdateLogin(
+    const PasswordForm& form) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BeginTransaction();
+  PasswordStoreChangeList changes = UpdateLoginSync(form, /*error=*/nullptr);
+  if (sync_bridge_ && !changes.empty())
+    sync_bridge_->ActOnPasswordStoreChanges(changes);
+  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
+  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
+  // because sync codebase needs to update metadata atomically together with
+  // the login data.
+  CommitTransaction();
+  return changes;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::RemoveLogin(
+    const PasswordForm& form) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BeginTransaction();
+  PasswordStoreChangeList changes;
+  if (login_db_ && login_db_->RemoveLogin(form, &changes)) {
+    if (sync_bridge_ && !changes.empty())
+      sync_bridge_->ActOnPasswordStoreChanges(changes);
+  }
+  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
+  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
+  // because sync codebase needs to update metadata atomically together with
+  // the login data.
+  CommitTransaction();
+  return changes;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::RemoveLoginsCreatedBetween(
+    base::Time delete_begin,
+    base::Time delete_end) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BeginTransaction();
+  PasswordStoreChangeList changes;
+  if (login_db_ && login_db_->RemoveLoginsCreatedBetween(
+                       delete_begin, delete_end, &changes)) {
+    if (sync_bridge_ && !changes.empty())
+      sync_bridge_->ActOnPasswordStoreChanges(changes);
+  }
+  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
+  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
+  // because sync codebase needs to update metadata atomically together with
+  // the login data.
+  CommitTransaction();
+  return changes;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::RemoveLoginsByURLAndTime(
+    const base::RepeatingCallback<bool(const GURL&)>& url_filter,
+    base::Time delete_begin,
+    base::Time delete_end,
+    base::OnceCallback<void(bool)> sync_completion) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  BeginTransaction();
+  PrimaryKeyToFormMap key_to_form_map;
+  PasswordStoreChangeList changes;
+  if (login_db_ && login_db_->GetLoginsCreatedBetween(delete_begin, delete_end,
+                                                      &key_to_form_map)) {
+    for (const auto& pair : key_to_form_map) {
+      PasswordForm* form = pair.second.get();
+      PasswordStoreChangeList remove_changes;
+      if (url_filter.Run(form->url) &&
+          login_db_->RemoveLogin(*form, &remove_changes)) {
+        std::move(remove_changes.begin(), remove_changes.end(),
+                  std::back_inserter(changes));
+      }
+    }
+  }
+  if (sync_bridge_ && !changes.empty())
+    sync_bridge_->ActOnPasswordStoreChanges(changes);
+  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
+  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
+  // because sync codebase needs to update metadata atomically together with
+  // the login data.
+  CommitTransaction();
+
+  if (sync_completion) {
+    deletions_have_synced_callbacks_.push_back(std::move(sync_completion));
+    // Start a timeout for sync, or restart it if it was already running.
+    deletions_have_synced_timeout_.Reset(
+        base::BindOnce(&LoginDatabaseAsyncHelper::NotifyDeletionsHaveSynced,
+                       weak_ptr_factory_.GetWeakPtr(),
+                       /*success=*/false));
+    base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, deletions_have_synced_timeout_.callback(), kSyncTaskTimeout);
+
+    // Do an immediate check for the case where there are already no unsynced
+    // deletions.
+    if (!GetMetadataStore()->HasUnsyncedDeletions())
+      NotifyDeletionsHaveSynced(/*success=*/true);
+  }
+  return changes;
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::DisableAutoSignInForOrigins(
+    const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  PrimaryKeyToFormMap key_to_form_map;
+  PasswordStoreChangeList changes;
+  if (!login_db_ || !login_db_->GetAutoSignInLogins(&key_to_form_map))
+    return changes;
+
+  std::set<GURL> origins_to_update;
+  for (const auto& pair : key_to_form_map) {
+    if (origin_filter.Run(pair.second->url))
+      origins_to_update.insert(pair.second->url);
+  }
+
+  std::set<GURL> origins_updated;
+  for (const GURL& origin : origins_to_update) {
+    if (login_db_->DisableAutoSignInForOrigin(origin))
+      origins_updated.insert(origin);
+  }
+
+  for (const auto& pair : key_to_form_map) {
+    if (origins_updated.count(pair.second->url)) {
+      changes.emplace_back(PasswordStoreChange::UPDATE, *pair.second,
+                           FormPrimaryKey(pair.first));
+    }
+  }
+  return changes;
+}
+
+// Synchronous implementation for manipulating with statistics.
+void LoginDatabaseAsyncHelper::AddSiteStats(const InteractionsStats& stats) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    login_db_->stats_table().AddRow(stats);
+}
+
+void LoginDatabaseAsyncHelper::RemoveSiteStats(const GURL& origin_domain) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    login_db_->stats_table().RemoveRow(origin_domain);
+}
+
+std::vector<InteractionsStats> LoginDatabaseAsyncHelper::GetSiteStats(
+    const GURL& origin_domain) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return login_db_ ? login_db_->stats_table().GetRows(origin_domain)
+                   : std::vector<InteractionsStats>();
+}
+
+void LoginDatabaseAsyncHelper::RemoveStatisticsByOriginAndTime(
+    const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
+    base::Time delete_begin,
+    base::Time delete_end) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_) {
+    login_db_->stats_table().RemoveStatsByOriginAndTime(
+        origin_filter, delete_begin, delete_end);
+  }
+}
+
+// Synchronous implementation for manipulating with field info.
+void LoginDatabaseAsyncHelper::AddFieldInfo(const FieldInfo& field_info) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    login_db_->field_info_table().AddRow(field_info);
+}
+
+std::vector<FieldInfo> LoginDatabaseAsyncHelper::GetAllFieldInfo() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return login_db_ ? login_db_->field_info_table().GetAllRows()
+                   : std::vector<FieldInfo>();
+}
+
+void LoginDatabaseAsyncHelper::RemoveFieldInfoByTime(base::Time remove_begin,
+                                                     base::Time remove_end) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    login_db_->field_info_table().RemoveRowsByTime(remove_begin, remove_end);
+}
+
+base::WeakPtr<syncer::ModelTypeControllerDelegate>
+LoginDatabaseAsyncHelper::GetSyncControllerDelegate() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return sync_bridge_->change_processor()->GetControllerDelegate();
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::AddLoginSync(
+    const PasswordForm& form,
+    AddLoginError* error) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!login_db_) {
+    if (error) {
+      *error = AddLoginError::kDbNotAvailable;
+    }
+    return PasswordStoreChangeList();
+  }
+  return login_db_->AddLogin(form, error);
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::UpdateLoginSync(
+    const PasswordForm& form,
+    UpdateLoginError* error) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!login_db_) {
+    if (error) {
+      *error = UpdateLoginError::kDbNotAvailable;
+    }
+    return PasswordStoreChangeList();
+  }
+  return login_db_->UpdateLogin(form, error);
+}
+
+void LoginDatabaseAsyncHelper::NotifyLoginsChanged(
+    const PasswordStoreChangeList& changes) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!remote_forms_changes_received_callback_)
+    return;
+  main_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(remote_forms_changes_received_callback_, changes));
+}
+
+void LoginDatabaseAsyncHelper::NotifyDeletionsHaveSynced(bool success) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // Either all deletions have been committed to the Sync server, or Sync is
+  // telling us that it won't commit them (because Sync was turned off
+  // permanently). In either case, run the corresponding callbacks now (on the
+  // main task runner).
+  DCHECK(!success || !GetMetadataStore()->HasUnsyncedDeletions());
+  for (auto& callback : deletions_have_synced_callbacks_) {
+    main_task_runner_->PostTask(FROM_HERE,
+                                base::BindOnce(std::move(callback), success));
+  }
+  deletions_have_synced_timeout_.Cancel();
+  deletions_have_synced_callbacks_.clear();
+}
+
+void LoginDatabaseAsyncHelper::NotifyUnsyncedCredentialsWillBeDeleted(
+    std::vector<PasswordForm> unsynced_credentials) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(IsAccountStore());
+  // |deletion_notifier_| only gets set for desktop.
+  if (deletion_notifier_) {
+    main_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&UnsyncedCredentialsDeletionNotifier::Notify,
+                                  deletion_notifier_->GetWeakPtr(),
+                                  std::move(unsynced_credentials)));
+  }
+}
+
+bool LoginDatabaseAsyncHelper::BeginTransaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    return login_db_->BeginTransaction();
+  return false;
+}
+
+void LoginDatabaseAsyncHelper::RollbackTransaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    login_db_->RollbackTransaction();
+}
+
+bool LoginDatabaseAsyncHelper::CommitTransaction() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (login_db_)
+    return login_db_->CommitTransaction();
+  return false;
+}
+
+FormRetrievalResult LoginDatabaseAsyncHelper::ReadAllLogins(
+    PrimaryKeyToFormMap* key_to_form_map) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!login_db_)
+    return FormRetrievalResult::kDbError;
+  return login_db_->GetAllLogins(key_to_form_map);
+}
+
+PasswordStoreChangeList LoginDatabaseAsyncHelper::RemoveLoginByPrimaryKeySync(
+    FormPrimaryKey primary_key) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  PasswordStoreChangeList changes;
+  if (login_db_ && login_db_->RemoveLoginByPrimaryKey(primary_key, &changes)) {
+    return changes;
+  }
+  return PasswordStoreChangeList();
+}
+
+PasswordStoreSync::MetadataStore* LoginDatabaseAsyncHelper::GetMetadataStore() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return login_db_.get();
+}
+
+bool LoginDatabaseAsyncHelper::IsAccountStore() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return login_db_ && login_db_->is_account_store();
+}
+
+bool LoginDatabaseAsyncHelper::DeleteAndRecreateDatabaseFile() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return login_db_ && login_db_->DeleteAndRecreateDatabaseFile();
+}
+
+DatabaseCleanupResult LoginDatabaseAsyncHelper::DeleteUndecryptableLogins() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!login_db_)
+    return DatabaseCleanupResult::kDatabaseUnavailable;
+  return login_db_->DeleteUndecryptableLogins();
+}
+
+// Reports password store metrics that aren't reported by the
+// StoreMetricsReporter. Namely, metrics related to inaccessible passwords,
+// and bubble statistics.
+void LoginDatabaseAsyncHelper::ReportMetrics() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!login_db_)
+    return;
+  login_db_->ReportMetrics();
+}
+
+}  // namespace password_manager
diff --git a/components/password_manager/core/browser/login_database_async_helper.h b/components/password_manager/core/browser/login_database_async_helper.h
new file mode 100644
index 0000000..9843e57
--- /dev/null
+++ b/components/password_manager/core/browser/login_database_async_helper.h
@@ -0,0 +1,149 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LOGIN_DATABASE_ASYNC_HELPER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LOGIN_DATABASE_ASYNC_HELPER_H_
+
+#include "base/cancelable_callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "components/password_manager/core/browser/password_store_backend.h"
+#include "components/password_manager/core/browser/password_store_sync.h"
+
+namespace syncer {
+class ModelTypeControllerDelegate;
+}  // namespace syncer
+
+namespace password_manager {
+
+class LoginDatabase;
+class PasswordSyncBridge;
+class UnsyncedCredentialsDeletionNotifier;
+
+struct FieldInfo;
+struct InteractionsStats;
+
+// Class which interacts directly with LoginDatabase. It is also responsible to
+// sync passwords. Works only on background sequence.
+class LoginDatabaseAsyncHelper : private PasswordStoreSync {
+ public:
+  LoginDatabaseAsyncHelper(
+      std::unique_ptr<LoginDatabase> login_db,
+      std::unique_ptr<UnsyncedCredentialsDeletionNotifier> notifier,
+      scoped_refptr<base::SequencedTaskRunner> main_task_runner);
+
+  ~LoginDatabaseAsyncHelper() override;
+
+  // Opens |login_db_| and creates |sync_bridge_|.
+  bool Initialize(
+      PasswordStoreBackend::RemoteChangesReceived remote_form_changes_received,
+      base::RepeatingClosure sync_enabled_or_disabled_cb);
+
+  // Synchronous implementation of PasswordStoreBackend interface.
+  LoginsResult GetAllLogins();
+  LoginsResult GetAutofillableLogins();
+  LoginsResult FillMatchingLogins(const std::vector<PasswordFormDigest>& forms,
+                                  bool include_psl);
+  PasswordStoreChangeList AddLogin(const PasswordForm& form);
+  PasswordStoreChangeList UpdateLogin(const PasswordForm& form);
+  PasswordStoreChangeList RemoveLogin(const PasswordForm& form);
+  PasswordStoreChangeList RemoveLoginsCreatedBetween(base::Time delete_begin,
+                                                     base::Time delete_end);
+  PasswordStoreChangeList RemoveLoginsByURLAndTime(
+      const base::RepeatingCallback<bool(const GURL&)>& url_filter,
+      base::Time delete_begin,
+      base::Time delete_end,
+      base::OnceCallback<void(bool)> sync_completion);
+  PasswordStoreChangeList DisableAutoSignInForOrigins(
+      const base::RepeatingCallback<bool(const GURL&)>& origin_filter);
+
+  // Synchronous implementation of SmartBubbleStatsStore interface.
+  void AddSiteStats(const InteractionsStats& stats);
+  void RemoveSiteStats(const GURL& origin_domain);
+  std::vector<InteractionsStats> GetSiteStats(const GURL& origin_domain);
+  void RemoveStatisticsByOriginAndTime(
+      const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
+      base::Time delete_begin,
+      base::Time delete_end);
+
+  // Synchronous implementation of FieldInfoStore.
+  void AddFieldInfo(const FieldInfo& field_info);
+  std::vector<FieldInfo> GetAllFieldInfo();
+  void RemoveFieldInfoByTime(base::Time remove_begin, base::Time remove_end);
+
+  // Instantiates a proxy controller delegate to react to sync events.
+  base::WeakPtr<syncer::ModelTypeControllerDelegate>
+  GetSyncControllerDelegate();
+
+ private:
+  // Implements PasswordStoreSync interface.
+  PasswordStoreChangeList AddLoginSync(const PasswordForm& form,
+                                       AddLoginError* error) override;
+  PasswordStoreChangeList UpdateLoginSync(const PasswordForm& form,
+                                          UpdateLoginError* error) override;
+  void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override;
+  void NotifyDeletionsHaveSynced(bool success) override;
+  void NotifyUnsyncedCredentialsWillBeDeleted(
+      std::vector<PasswordForm> unsynced_credentials) override;
+  bool BeginTransaction() override;
+  void RollbackTransaction() override;
+  bool CommitTransaction() override;
+  FormRetrievalResult ReadAllLogins(
+      PrimaryKeyToFormMap* key_to_form_map) override;
+  PasswordStoreChangeList RemoveLoginByPrimaryKeySync(
+      FormPrimaryKey primary_key) override;
+  PasswordStoreSync::MetadataStore* GetMetadataStore() override;
+  bool IsAccountStore() const override;
+  bool DeleteAndRecreateDatabaseFile() override;
+  DatabaseCleanupResult DeleteUndecryptableLogins() override;
+
+  // Reports password store metrics that aren't reported by the
+  // StoreMetricsReporter. Namely, metrics related to inaccessible passwords,
+  // and bubble statistics.
+  void ReportMetrics();
+
+  // Ensures that all methods, excluding construction, are called on the same
+  // sequence.
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  // The login SQL database. The LoginDatabase instance is received via the
+  // constructor. It is passed in an uninitialized state, to allow injecting
+  // mocks. It will be initilaized by calling Initialize. If opening the DB
+  // fails, |login_db_| will be reset and stay NULL for the lifetime of |this|.
+  std::unique_ptr<LoginDatabase> login_db_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  std::unique_ptr<PasswordSyncBridge> sync_bridge_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Whenever 'sync_bridge_'receive remote changes this callback is used to
+  // notify PasswordStore observers about them. Called on a main sequence from
+  // the 'NotifyLoginsChanged'.
+  PasswordStoreBackend::RemoteChangesReceived
+      remote_forms_changes_received_callback_
+          GUARDED_BY_CONTEXT(sequence_checker_);
+
+  std::unique_ptr<UnsyncedCredentialsDeletionNotifier> deletion_notifier_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // A list of callbacks that should be run once all pending deletions have been
+  // sent to the Sync server. Note that the vector itself lives on the
+  // background thread, but the callbacks must be run on the main thread!
+  std::vector<base::OnceCallback<void(bool)>> deletions_have_synced_callbacks_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  // Timeout closure that runs if sync takes too long to propagate deletions.
+  base::CancelableOnceClosure deletions_have_synced_timeout_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_
+      GUARDED_BY_CONTEXT(sequence_checker_);
+
+  base::WeakPtrFactory<LoginDatabaseAsyncHelper> weak_ptr_factory_
+      GUARDED_BY_CONTEXT(sequence_checker_){this};
+};
+
+}  // namespace password_manager
+
+#endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_LOGIN_DATABASE_ASYNC_HELPER_H_
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index c8563d2..ff0fddb9 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -50,6 +50,15 @@
 
 class PasswordStoreConsumer;
 
+// Used to notify that unsynced credentials are about to be deleted.
+class UnsyncedCredentialsDeletionNotifier {
+ public:
+  // Should be called from the UI thread.
+  virtual void Notify(std::vector<PasswordForm>) = 0;
+  virtual ~UnsyncedCredentialsDeletionNotifier() = default;
+  virtual base::WeakPtr<UnsyncedCredentialsDeletionNotifier> GetWeakPtr() = 0;
+};
+
 // Partial, cross-platform implementation for storing form passwords.
 // The login request/manipulation API is not threadsafe and must be used
 // from the UI thread.
@@ -57,15 +66,6 @@
 // needs to access these methods.
 class PasswordStore : public PasswordStoreInterface {
  public:
-  // Used to notify that unsynced credentials are about to be deleted.
-  class UnsyncedCredentialsDeletionNotifier {
-   public:
-    // Should be called from the UI thread.
-    virtual void Notify(std::vector<PasswordForm>) = 0;
-    virtual ~UnsyncedCredentialsDeletionNotifier() = default;
-    virtual base::WeakPtr<UnsyncedCredentialsDeletionNotifier> GetWeakPtr() = 0;
-  };
-
   explicit PasswordStore(std::unique_ptr<PasswordStoreBackend> backend);
 
   PasswordStore(const PasswordStore&) = delete;
diff --git a/components/password_manager/core/browser/password_store_built_in_backend.cc b/components/password_manager/core/browser/password_store_built_in_backend.cc
index eab741d..008fccc8 100644
--- a/components/password_manager/core/browser/password_store_built_in_backend.cc
+++ b/components/password_manager/core/browser/password_store_built_in_backend.cc
@@ -4,265 +4,43 @@
 
 #include "components/password_manager/core/browser/password_store_built_in_backend.h"
 
-#include <iterator>
-#include <memory>
-#include <set>
-#include <utility>
-
 #include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
-#include "build/build_config.h"
-#include "components/password_manager/core/browser/field_info_table.h"
 #include "components/password_manager/core/browser/login_database.h"
-#include "components/password_manager/core/browser/password_store_backend.h"
-#include "components/password_manager/core/browser/password_store_change.h"
-#include "components/password_manager/core/browser/password_store_consumer.h"
-#include "components/password_manager/core/browser/sync/password_sync_bridge.h"
-#include "components/prefs/pref_service.h"
-#include "components/sync/model/client_tag_based_model_type_processor.h"
-#include "components/sync/model/model_type_controller_delegate.h"
+#include "components/password_manager/core/browser/login_database_async_helper.h"
 #include "components/sync/model/proxy_model_type_controller_delegate.h"
 
 namespace password_manager {
 
-namespace {
-
-constexpr base::TimeDelta kSyncTaskTimeout = base::Seconds(30);
-
-}  // namespace
-
 PasswordStoreBuiltInBackend::PasswordStoreBuiltInBackend(
-    std::unique_ptr<LoginDatabase> login_db)
-    : login_db_(std::move(login_db)) {
-  main_task_runner_ = base::SequencedTaskRunnerHandle::Get();
-  DCHECK(main_task_runner_);
+    std::unique_ptr<LoginDatabase> login_db,
+    std::unique_ptr<UnsyncedCredentialsDeletionNotifier> notifier) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   background_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
       {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
   DCHECK(background_task_runner_);
+  helper_ = std::make_unique<LoginDatabaseAsyncHelper>(
+      std::move(login_db), std::move(notifier),
+      base::SequencedTaskRunnerHandle::Get());
 }
 
-PasswordStoreBuiltInBackend::PasswordStoreBuiltInBackend(
-    std::unique_ptr<LoginDatabase> login_db,
-    std::unique_ptr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
-        notifier)
-    : PasswordStoreBuiltInBackend(std::move(login_db)) {
-  DCHECK(notifier);
-  deletion_notifier_ = std::move(notifier);
+PasswordStoreBuiltInBackend::~PasswordStoreBuiltInBackend() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-PasswordStoreBuiltInBackend::~PasswordStoreBuiltInBackend() = default;
-
 void PasswordStoreBuiltInBackend::Shutdown(
     base::OnceClosure shutdown_completed) {
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
-  was_shutdown_ = true;
-  background_task_runner_->PostTaskAndReply(
-      FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::DestroyOnBackgroundSequence,
-                     weak_ptr_factory_.GetWeakPtr()),
-      std::move(shutdown_completed));
-}
-
-PasswordStoreChangeList
-PasswordStoreBuiltInBackend::DisableAutoSignInForOriginsImpl(
-    const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
-  PrimaryKeyToFormMap key_to_form_map;
-  PasswordStoreChangeList changes;
-  if (!login_db_ || !login_db_->GetAutoSignInLogins(&key_to_form_map))
-    return changes;
-
-  std::set<GURL> origins_to_update;
-  for (const auto& pair : key_to_form_map) {
-    if (origin_filter.Run(pair.second->url))
-      origins_to_update.insert(pair.second->url);
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  if (helper_) {
+    background_task_runner_->DeleteSoon(FROM_HERE, std::move(helper_));
   }
-
-  std::set<GURL> origins_updated;
-  for (const GURL& origin : origins_to_update) {
-    if (login_db_->DisableAutoSignInForOrigin(origin))
-      origins_updated.insert(origin);
-  }
-
-  for (const auto& pair : key_to_form_map) {
-    if (origins_updated.count(pair.second->url)) {
-      changes.emplace_back(PasswordStoreChange::UPDATE, *pair.second,
-                           FormPrimaryKey(pair.first));
-    }
-  }
-
-  return changes;
-}
-
-DatabaseCleanupResult PasswordStoreBuiltInBackend::DeleteUndecryptableLogins() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (!login_db_)
-    return DatabaseCleanupResult::kDatabaseUnavailable;
-  return login_db_->DeleteUndecryptableLogins();
-}
-
-void PasswordStoreBuiltInBackend::AddSiteStatsInternal(
-    const InteractionsStats& stats) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (login_db_)
-    login_db_->stats_table().AddRow(stats);
-}
-
-void PasswordStoreBuiltInBackend::RemoveSiteStatsInternal(
-    const GURL& origin_domain) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (login_db_)
-    login_db_->stats_table().RemoveRow(origin_domain);
-}
-
-std::vector<InteractionsStats>
-PasswordStoreBuiltInBackend::GetSiteStatsInternal(const GURL& origin_domain) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  return login_db_ ? login_db_->stats_table().GetRows(origin_domain)
-                   : std::vector<InteractionsStats>();
-}
-
-void PasswordStoreBuiltInBackend::RemoveStatisticsByOriginAndTimeInternal(
-    const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
-    base::Time delete_begin,
-    base::Time delete_end) {
-  if (login_db_) {
-    login_db_->stats_table().RemoveStatsByOriginAndTime(
-        origin_filter, delete_begin, delete_end);
-  }
-}
-
-base::WeakPtr<syncer::ModelTypeControllerDelegate>
-PasswordStoreBuiltInBackend::GetSyncControllerDelegateOnBackgroundSequence() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  DCHECK(sync_bridge_);
-  return sync_bridge_->change_processor()->GetControllerDelegate();
-}
-
-void PasswordStoreBuiltInBackend::ReportMetrics() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (!login_db_)
-    return;
-  login_db_->ReportMetrics();
-}
-
-PasswordStoreChangeList PasswordStoreBuiltInBackend::AddLoginSync(
-    const PasswordForm& form,
-    AddLoginError* error) {
-  if (!login_db_) {
-    if (error) {
-      *error = AddLoginError::kDbNotAvailable;
-    }
-    return PasswordStoreChangeList();
-  }
-  return login_db_->AddLogin(form, error);
-}
-
-PasswordStoreChangeList PasswordStoreBuiltInBackend::UpdateLoginSync(
-    const PasswordForm& form,
-    UpdateLoginError* error) {
-  if (!login_db_) {
-    if (error) {
-      *error = UpdateLoginError::kDbNotAvailable;
-    }
-    return PasswordStoreChangeList();
-  }
-  return login_db_->UpdateLogin(form, error);
-}
-
-void PasswordStoreBuiltInBackend::NotifyLoginsChanged(
-    const PasswordStoreChangeList& changes) {
-  if (!remote_forms_changes_received_callback_)
-    return;
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(remote_forms_changes_received_callback_, changes));
-}
-
-void PasswordStoreBuiltInBackend::NotifyDeletionsHaveSynced(bool success) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  // Either all deletions have been committed to the Sync server, or Sync is
-  // telling us that it won't commit them (because Sync was turned off
-  // permanently). In either case, run the corresponding callbacks now (on the
-  // main task runner).
-  DCHECK(!success || !GetMetadataStore()->HasUnsyncedDeletions());
-  for (auto& callback : deletions_have_synced_callbacks_) {
-    main_task_runner_->PostTask(FROM_HERE,
-                                base::BindOnce(std::move(callback), success));
-  }
-  deletions_have_synced_timeout_.Cancel();
-  deletions_have_synced_callbacks_.clear();
-}
-
-void PasswordStoreBuiltInBackend::NotifyUnsyncedCredentialsWillBeDeleted(
-    std::vector<PasswordForm> unsynced_credentials) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  DCHECK(IsAccountStore());
-  // |deletion_notifier_| only gets set for desktop.
-  if (deletion_notifier_) {
-    main_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &PasswordStore::UnsyncedCredentialsDeletionNotifier::Notify,
-            deletion_notifier_->GetWeakPtr(), std::move(unsynced_credentials)));
-  }
-}
-
-bool PasswordStoreBuiltInBackend::BeginTransaction() {
-  if (login_db_)
-    return login_db_->BeginTransaction();
-  return false;
-}
-
-void PasswordStoreBuiltInBackend::RollbackTransaction() {
-  if (login_db_)
-    login_db_->RollbackTransaction();
-}
-
-bool PasswordStoreBuiltInBackend::CommitTransaction() {
-  if (login_db_)
-    return login_db_->CommitTransaction();
-  return false;
-}
-
-FormRetrievalResult PasswordStoreBuiltInBackend::ReadAllLogins(
-    PrimaryKeyToFormMap* key_to_form_map) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  if (!login_db_)
-    return FormRetrievalResult::kDbError;
-  return login_db_->GetAllLogins(key_to_form_map);
-}
-
-PasswordStoreChangeList
-PasswordStoreBuiltInBackend::RemoveLoginByPrimaryKeySync(
-    FormPrimaryKey primary_key) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  PasswordStoreChangeList changes;
-  if (login_db_ && login_db_->RemoveLoginByPrimaryKey(primary_key, &changes)) {
-    return changes;
-  }
-  return PasswordStoreChangeList();
-}
-
-PasswordStoreSync::MetadataStore*
-PasswordStoreBuiltInBackend::GetMetadataStore() {
-  return login_db_.get();
-}
-
-bool PasswordStoreBuiltInBackend::IsAccountStore() const {
-  return login_db_ && login_db_->is_account_store();
-}
-
-bool PasswordStoreBuiltInBackend::DeleteAndRecreateDatabaseFile() {
-  return login_db_ && login_db_->DeleteAndRecreateDatabaseFile();
 }
 
 base::WeakPtr<PasswordStoreBackend> PasswordStoreBuiltInBackend::GetWeakPtr() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return weak_ptr_factory_.GetWeakPtr();
 }
 
@@ -270,37 +48,39 @@
     RemoteChangesReceived remote_form_changes_received,
     base::RepeatingClosure sync_enabled_or_disabled_cb,
     base::OnceCallback<void(bool)> completion) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::InitOnBackgroundSequence,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     std::move(remote_form_changes_received),
-                     std::move(sync_enabled_or_disabled_cb)),
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::Initialize,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
+          std::move(remote_form_changes_received),
+          std::move(sync_enabled_or_disabled_cb)),
       std::move(completion));
 }
 
 void PasswordStoreBuiltInBackend::GetAllLoginsAsync(
     LoginsOrErrorReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::GetAllLoginsInternal,
-                     base::Unretained(this)),  // Safe until `Shutdown()`.
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::GetAllLogins,
+          base::Unretained(helper_.get())),  // Safe until `Shutdown()`.
       std::move(callback));
 }
 
 void PasswordStoreBuiltInBackend::GetAutofillableLoginsAsync(
     LoginsOrErrorReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(
-          &PasswordStoreBuiltInBackend::GetAutofillableLoginsInternal,
-          base::Unretained(this)),  // Safe until `Shutdown()`.
+          &LoginDatabaseAsyncHelper::GetAutofillableLogins,
+          base::Unretained(helper_.get())),  // Safe until `Shutdown()`.
       std::move(callback));
 }
 
@@ -308,8 +88,8 @@
     LoginsReply callback,
     bool include_psl,
     const std::vector<PasswordFormDigest>& forms) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   if (forms.empty()) {
     std::move(callback).Run({});
     return;
@@ -317,48 +97,48 @@
 
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::FillMatchingLoginsInternal,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     forms, include_psl),
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::FillMatchingLogins,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
+          forms, include_psl),
       std::move(callback));
 }
 
 void PasswordStoreBuiltInBackend::AddLoginAsync(
     const PasswordForm& form,
     PasswordStoreChangeListReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::AddLoginInternal,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     form),
+      base::BindOnce(&LoginDatabaseAsyncHelper::AddLogin,
+                     base::Unretained(helper_.get()), form),
       std::move(callback));
 }
 
 void PasswordStoreBuiltInBackend::UpdateLoginAsync(
     const PasswordForm& form,
     PasswordStoreChangeListReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::UpdateLoginInternal,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     form),
+      base::BindOnce(&LoginDatabaseAsyncHelper::UpdateLogin,
+                     base::Unretained(helper_.get()), form),
       std::move(callback));
 }
 
 void PasswordStoreBuiltInBackend::RemoveLoginAsync(
     const PasswordForm& form,
     PasswordStoreChangeListReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::RemoveLoginInternal,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     form),
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::RemoveLogin,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
+          form),
       std::move(callback));
 }
 
@@ -366,13 +146,13 @@
     base::Time delete_begin,
     base::Time delete_end,
     PasswordStoreChangeListReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(
-          &PasswordStoreBuiltInBackend::RemoveLoginsCreatedBetweenInternal,
-          base::Unretained(this),  // Safe until `Shutdown()`.
+          &LoginDatabaseAsyncHelper::RemoveLoginsCreatedBetween,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
           delete_begin, delete_end),
       std::move(callback));
 }
@@ -383,13 +163,13 @@
     base::Time delete_end,
     base::OnceCallback<void(bool)> sync_completion,
     PasswordStoreChangeListReply callback) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(
-          &PasswordStoreBuiltInBackend::RemoveLoginsByURLAndTimeInternal,
-          base::Unretained(this),  // Safe until `Shutdown()`.
+          &LoginDatabaseAsyncHelper::RemoveLoginsByURLAndTime,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
           url_filter, delete_begin, delete_end, std::move(sync_completion)),
       std::move(callback));
 }
@@ -397,14 +177,14 @@
 void PasswordStoreBuiltInBackend::DisableAutoSignInForOriginsAsync(
     const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
     base::OnceClosure completion) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReply(
       FROM_HERE,
       base::BindOnce(
           base::IgnoreResult(
-              &PasswordStoreBuiltInBackend::DisableAutoSignInForOriginsImpl),
-          base::Unretained(this),  // Safe until `Shutdown()`.
+              &LoginDatabaseAsyncHelper::DisableAutoSignInForOrigins),
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
           origin_filter),
       std::move(completion));
 }
@@ -419,24 +199,18 @@
 
 std::unique_ptr<syncer::ProxyModelTypeControllerDelegate>
 PasswordStoreBuiltInBackend::CreateSyncControllerDelegate() {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   // Note that a callback is bound for
-  // GetSyncControllerDelegateOnBackgroundSequence() because this getter itself
+  // GetSyncControllerDelegate() because this getter itself
   // must also run in the backend sequence, and the proxy object below will take
   // care of that.
   // Since the controller delegate can (only in theory) invoke the factory after
   // `Shutdown` was called, it only returns nullptr then to prevent a UAF.
   return std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
       background_task_runner_,
-      base::BindRepeating(
-          [](base::WeakPtr<PasswordStoreBuiltInBackend> backend) {
-            if (!backend)
-              return base::WeakPtr<syncer::ModelTypeControllerDelegate>(
-                  nullptr);
-            return backend->GetSyncControllerDelegateOnBackgroundSequence();
-          },
-          weak_ptr_factory_.GetWeakPtr()));
+      base::BindRepeating(&LoginDatabaseAsyncHelper::GetSyncControllerDelegate,
+                          base::Unretained(helper_.get())));
 }
 
 void PasswordStoreBuiltInBackend::ClearAllLocalPasswords() {
@@ -444,33 +218,33 @@
 }
 
 void PasswordStoreBuiltInBackend::AddSiteStats(const InteractionsStats& stats) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::AddSiteStatsInternal,
-                     weak_ptr_factory_.GetWeakPtr(), stats));
+      FROM_HERE, base::BindOnce(&LoginDatabaseAsyncHelper::AddSiteStats,
+                                base::Unretained(helper_.get()), stats));
 }
 
 void PasswordStoreBuiltInBackend::RemoveSiteStats(const GURL& origin_domain) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::RemoveSiteStatsInternal,
-                     weak_ptr_factory_.GetWeakPtr(), origin_domain));
+      base::BindOnce(&LoginDatabaseAsyncHelper::RemoveSiteStats,
+                     base::Unretained(helper_.get()), origin_domain));
 }
 
 void PasswordStoreBuiltInBackend::GetSiteStats(
     const GURL& origin_domain,
     base::WeakPtr<PasswordStoreConsumer> consumer) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
       background_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::GetSiteStatsInternal,
-                     base::Unretained(this),  // Safe until `Shutdown()`.
-                     origin_domain),
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::GetSiteStats,
+          base::Unretained(helper_.get()),  // Safe until `Shutdown()`.
+          origin_domain),
       base::BindOnce(&PasswordStoreConsumer::OnGetSiteStatistics, consumer));
 }
 
@@ -479,34 +253,33 @@
     base::Time delete_begin,
     base::Time delete_end,
     base::OnceClosure completion) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::BindOnce(
-          &PasswordStoreBuiltInBackend::RemoveStatisticsByOriginAndTimeInternal,
-          weak_ptr_factory_.GetWeakPtr(), origin_filter, delete_begin,
-          delete_end),
+      base::BindOnce(&LoginDatabaseAsyncHelper::RemoveStatisticsByOriginAndTime,
+                     base::Unretained(helper_.get()), origin_filter,
+                     delete_begin, delete_end),
       std::move(completion));
 }
 
 void PasswordStoreBuiltInBackend::AddFieldInfo(const FieldInfo& field_info) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::AddFieldInfoInternal,
-                     weak_ptr_factory_.GetWeakPtr(), field_info));
+      FROM_HERE, base::BindOnce(&LoginDatabaseAsyncHelper::AddFieldInfo,
+                                base::Unretained(helper_.get()), field_info));
 }
 
 void PasswordStoreBuiltInBackend::GetAllFieldInfo(
     base::WeakPtr<PasswordStoreConsumer> consumer) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   consumer->cancelable_task_tracker()->PostTaskAndReplyWithResult(
       background_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&PasswordStoreBuiltInBackend::GetAllFieldInfoInternal,
-                     base::Unretained(this)),  // Safe until `Shutdown()`.
+      base::BindOnce(
+          &LoginDatabaseAsyncHelper::GetAllFieldInfo,
+          base::Unretained(helper_.get())),  // Safe until `Shutdown()`.
       base::BindOnce(&PasswordStoreConsumer::OnGetAllFieldInfo, consumer));
 }
 
@@ -514,235 +287,13 @@
     base::Time remove_begin,
     base::Time remove_end,
     base::OnceClosure completion) {
-  DCHECK(!was_shutdown_);
-  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(helper_);
   background_task_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::BindOnce(
-          &PasswordStoreBuiltInBackend::RemoveFieldInfoByTimeInternal,
-          weak_ptr_factory_.GetWeakPtr(), remove_begin, remove_end),
+      base::BindOnce(&LoginDatabaseAsyncHelper::RemoveFieldInfoByTime,
+                     base::Unretained(helper_.get()), remove_begin, remove_end),
       std::move(completion));
 }
 
-bool PasswordStoreBuiltInBackend::InitOnBackgroundSequence(
-    RemoteChangesReceived remote_form_changes_received,
-    base::RepeatingClosure sync_enabled_or_disabled_cb) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-
-  remote_forms_changes_received_callback_ =
-      std::move(remote_form_changes_received);
-
-  DCHECK(login_db_);
-  bool success = true;
-  if (!login_db_->Init()) {
-    login_db_.reset();
-    // The initialization should be continued, because PasswordSyncBridge
-    // has to be initialized even if database initialization failed.
-    success = false;
-    LOG(ERROR) << "Could not create/open login database.";
-  }
-  if (success) {
-    login_db_->SetDeletionsHaveSyncedCallback(base::BindRepeating(
-        &PasswordStoreBuiltInBackend::NotifyDeletionsHaveSynced,
-        weak_ptr_factory_.GetWeakPtr()));
-
-    // Delay the actual reporting by 30 seconds, to ensure it doesn't happen
-    // during the "hot phase" of Chrome startup.
-    background_task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&PasswordStoreBuiltInBackend::ReportMetrics,
-                       weak_ptr_factory_.GetWeakPtr()),
-        base::Seconds(30));
-  }
-
-  sync_bridge_ = base::WrapUnique(new PasswordSyncBridge(
-      std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
-          syncer::PASSWORDS, base::DoNothing()),
-      /*password_store_sync=*/this, sync_enabled_or_disabled_cb));
-
-  return success;
-}
-
-void PasswordStoreBuiltInBackend::DestroyOnBackgroundSequence() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  remote_forms_changes_received_callback_.Reset();
-  weak_ptr_factory_.InvalidateWeakPtrs();
-  login_db_.reset();
-  sync_bridge_.reset();
-  // No task should be running on (or send to) the background runner.
-  background_task_runner_.reset();
-  main_task_runner_.reset();
-}
-
-LoginsResult PasswordStoreBuiltInBackend::GetAllLoginsInternal() {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  PrimaryKeyToFormMap key_to_form_map;
-
-  if (!login_db_ || login_db_->GetAllLogins(&key_to_form_map) !=
-                        FormRetrievalResult::kSuccess)
-    return {};
-
-  std::vector<std::unique_ptr<PasswordForm>> obtained_forms;
-  for (auto& pair : key_to_form_map) {
-    obtained_forms.push_back(std::move(pair.second));
-  }
-  return obtained_forms;
-}
-
-LoginsResult PasswordStoreBuiltInBackend::GetAutofillableLoginsInternal() {
-  std::vector<std::unique_ptr<PasswordForm>> results;
-  if (!login_db_ || !login_db_->GetAutofillableLogins(&results))
-    return {};
-  return results;
-}
-
-LoginsResult PasswordStoreBuiltInBackend::FillMatchingLoginsInternal(
-    const std::vector<PasswordFormDigest>& forms,
-    bool include_psl) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-
-  std::vector<std::unique_ptr<PasswordForm>> results;
-  for (const auto& form : forms) {
-    std::vector<std::unique_ptr<PasswordForm>> matched_forms;
-    if (login_db_ && !login_db_->GetLogins(form, include_psl, &matched_forms))
-      continue;
-    results.insert(results.end(),
-                   std::make_move_iterator(matched_forms.begin()),
-                   std::make_move_iterator(matched_forms.end()));
-  }
-  return results;
-}
-
-PasswordStoreChangeList PasswordStoreBuiltInBackend::AddLoginInternal(
-    const PasswordForm& form) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  BeginTransaction();
-  PasswordStoreChangeList changes = AddLoginSync(form, /*error=*/nullptr);
-  if (sync_bridge_ && !changes.empty())
-    sync_bridge_->ActOnPasswordStoreChanges(changes);
-  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
-  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
-  // because sync codebase needs to update metadata atomically together with the
-  // login data.
-  CommitTransaction();
-  return changes;
-}
-
-PasswordStoreChangeList PasswordStoreBuiltInBackend::UpdateLoginInternal(
-    const PasswordForm& form) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  BeginTransaction();
-  PasswordStoreChangeList changes = UpdateLoginSync(form, /*error=*/nullptr);
-  if (sync_bridge_ && !changes.empty())
-    sync_bridge_->ActOnPasswordStoreChanges(changes);
-  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
-  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
-  // because sync codebase needs to update metadata atomically together with the
-  // login data.
-  CommitTransaction();
-  return changes;
-}
-
-PasswordStoreChangeList PasswordStoreBuiltInBackend::RemoveLoginInternal(
-    const PasswordForm& form) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  BeginTransaction();
-  PasswordStoreChangeList changes;
-  if (login_db_ && login_db_->RemoveLogin(form, &changes)) {
-    if (sync_bridge_ && !changes.empty())
-      sync_bridge_->ActOnPasswordStoreChanges(changes);
-  }
-  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
-  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
-  // because sync codebase needs to update metadata atomically together with the
-  // login data.
-  CommitTransaction();
-  return changes;
-}
-
-PasswordStoreChangeList
-PasswordStoreBuiltInBackend::RemoveLoginsCreatedBetweenInternal(
-    base::Time delete_begin,
-    base::Time delete_end) {
-  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
-  BeginTransaction();
-  PasswordStoreChangeList changes;
-  if (login_db_ && login_db_->RemoveLoginsCreatedBetween(
-                       delete_begin, delete_end, &changes)) {
-    if (sync_bridge_ && !changes.empty())
-      sync_bridge_->ActOnPasswordStoreChanges(changes);
-  }
-  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
-  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
-  // because sync codebase needs to update metadata atomically together with the
-  // login data.
-  CommitTransaction();
-  return changes;
-}
-
-PasswordStoreChangeList
-PasswordStoreBuiltInBackend::RemoveLoginsByURLAndTimeInternal(
-    const base::RepeatingCallback<bool(const GURL&)>& url_filter,
-    base::Time delete_begin,
-    base::Time delete_end,
-    base::OnceCallback<void(bool)> sync_completion) {
-  BeginTransaction();
-  PrimaryKeyToFormMap key_to_form_map;
-  PasswordStoreChangeList changes;
-  if (login_db_ && login_db_->GetLoginsCreatedBetween(delete_begin, delete_end,
-                                                      &key_to_form_map)) {
-    for (const auto& pair : key_to_form_map) {
-      PasswordForm* form = pair.second.get();
-      PasswordStoreChangeList remove_changes;
-      if (url_filter.Run(form->url) &&
-          login_db_->RemoveLogin(*form, &remove_changes)) {
-        std::move(remove_changes.begin(), remove_changes.end(),
-                  std::back_inserter(changes));
-      }
-    }
-  }
-  if (sync_bridge_ && !changes.empty())
-    sync_bridge_->ActOnPasswordStoreChanges(changes);
-  // Sync metadata get updated in ActOnPasswordStoreChanges(). Therefore,
-  // CommitTransaction() must be called after ActOnPasswordStoreChanges(),
-  // because sync codebase needs to update metadata atomically together with the
-  // login data.
-  CommitTransaction();
-
-  if (sync_completion) {
-    deletions_have_synced_callbacks_.push_back(std::move(sync_completion));
-    // Start a timeout for sync, or restart it if it was already running.
-    deletions_have_synced_timeout_.Reset(
-        base::BindOnce(&PasswordStoreBuiltInBackend::NotifyDeletionsHaveSynced,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       /*success=*/false));
-    background_task_runner_->PostDelayedTask(
-        FROM_HERE, deletions_have_synced_timeout_.callback(), kSyncTaskTimeout);
-
-    // Do an immediate check for the case where there are already no unsynced
-    // deletions.
-    if (!GetMetadataStore()->HasUnsyncedDeletions())
-      NotifyDeletionsHaveSynced(/*success=*/true);
-  }
-  return changes;
-}
-
-void PasswordStoreBuiltInBackend::AddFieldInfoInternal(
-    const FieldInfo& field_info) {
-  if (login_db_)
-    login_db_->field_info_table().AddRow(field_info);
-}
-
-std::vector<FieldInfo> PasswordStoreBuiltInBackend::GetAllFieldInfoInternal() {
-  return login_db_ ? login_db_->field_info_table().GetAllRows()
-                   : std::vector<FieldInfo>();
-}
-
-void PasswordStoreBuiltInBackend::RemoveFieldInfoByTimeInternal(
-    base::Time remove_begin,
-    base::Time remove_end) {
-  if (login_db_)
-    login_db_->field_info_table().RemoveRowsByTime(remove_begin, remove_end);
-}
-
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_built_in_backend.h b/components/password_manager/core/browser/password_store_built_in_backend.h
index 2729462..7223f76d 100644
--- a/components/password_manager/core/browser/password_store_built_in_backend.h
+++ b/components/password_manager/core/browser/password_store_built_in_backend.h
@@ -12,13 +12,9 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "components/password_manager/core/browser/insecure_credentials_table.h"
-#include "components/password_manager/core/browser/login_database.h"
-#include "components/password_manager/core/browser/password_store.h"
-
-namespace syncer {
-class ModelTypeControllerDelegate;
-}  // namespace syncer
+#include "components/password_manager/core/browser/field_info_store.h"
+#include "components/password_manager/core/browser/password_store_backend.h"
+#include "components/password_manager/core/browser/smart_bubble_stats_store.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -26,58 +22,27 @@
 
 namespace password_manager {
 
-class PasswordSyncBridge;
+class LoginDatabase;
+class LoginDatabaseAsyncHelper;
+class UnsyncedCredentialsDeletionNotifier;
 
 struct FieldInfo;
 
 // Simple password store implementation that delegates everything to
-// the LoginDatabase.
-class PasswordStoreBuiltInBackend : protected PasswordStoreSync,
-                                    public PasswordStoreBackend,
+// the LoginDatabaseAsyncHelper. Works only on the main sequence.
+class PasswordStoreBuiltInBackend : public PasswordStoreBackend,
                                     public SmartBubbleStatsStore,
                                     protected FieldInfoStore {
  public:
   // The |login_db| must not have been Init()-ed yet. It will be initialized in
   // a deferred manner on the background sequence.
-  explicit PasswordStoreBuiltInBackend(std::unique_ptr<LoginDatabase> login_db);
-
   PasswordStoreBuiltInBackend(
       std::unique_ptr<LoginDatabase> login_db,
-      std::unique_ptr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
-          notifier);
+      std::unique_ptr<UnsyncedCredentialsDeletionNotifier> notifier = nullptr);
 
   ~PasswordStoreBuiltInBackend() override;
 
- protected:
-  // Implements PasswordStore interface.
-  PasswordStoreChangeList DisableAutoSignInForOriginsImpl(
-      const base::RepeatingCallback<bool(const GURL&)>& origin_filter);
-  DatabaseCleanupResult DeleteUndecryptableLogins() override;
-
-  // Implements PasswordStoreSync interface.
-  PasswordStoreChangeList AddLoginSync(const PasswordForm& form,
-                                       AddLoginError* error) override;
-  PasswordStoreChangeList UpdateLoginSync(const PasswordForm& form,
-                                          UpdateLoginError* error) override;
-  void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override;
-  void NotifyDeletionsHaveSynced(bool success) override;
-  void NotifyUnsyncedCredentialsWillBeDeleted(
-      std::vector<PasswordForm> unsynced_credentials) override;
-  bool BeginTransaction() override;
-  void RollbackTransaction() override;
-  bool CommitTransaction() override;
-  FormRetrievalResult ReadAllLogins(
-      PrimaryKeyToFormMap* key_to_form_map) override;
-  PasswordStoreChangeList RemoveLoginByPrimaryKeySync(
-      FormPrimaryKey primary_key) override;
-  PasswordStoreSync::MetadataStore* GetMetadataStore() override;
-  bool IsAccountStore() const override;
-  bool DeleteAndRecreateDatabaseFile() override;
-
  private:
-  FRIEND_TEST_ALL_PREFIXES(PasswordStoreTest,
-                           UpdatePasswordsStoredForAffiliatedWebsites);
-
   // Implements PasswordStoreBackend interface.
   base::WeakPtr<PasswordStoreBackend> GetWeakPtr() override;
   void InitBackend(RemoteChangesReceived remote_form_changes_received,
@@ -133,96 +98,22 @@
                              base::Time remove_end,
                              base::OnceClosure completion) override;
 
-  // Opens |login_db_| and creates |sync_bridge_| on the background sequence.
-  bool InitOnBackgroundSequence(
-      RemoteChangesReceived remote_form_changes_received,
-      base::RepeatingClosure sync_enabled_or_disabled_cb);
+  // Ensures that all methods are called on the main sequence.
+  SEQUENCE_CHECKER(sequence_checker_);
 
-  // Resets all members on the background sequence but ensures that the
-  // backend deletion is happening on the given `main_task_runner` after the
-  // backend work is concluded.
-  void DestroyOnBackgroundSequence();
-
-  // Synchronous implementation of GetAllLoginsAsync.
-  LoginsResult GetAllLoginsInternal();
-
-  // Synchronous implementation of GetAutofillableLoginsAsync.
-  LoginsResult GetAutofillableLoginsInternal();
-
-  // Synchronous implementation of FillMatchingLoginsAsync.
-  LoginsResult FillMatchingLoginsInternal(
-      const std::vector<PasswordFormDigest>& forms,
-      bool include_psl);
-
-  PasswordStoreChangeList AddLoginInternal(const PasswordForm& form);
-  PasswordStoreChangeList UpdateLoginInternal(const PasswordForm& form);
-  PasswordStoreChangeList RemoveLoginInternal(const PasswordForm& form);
-  PasswordStoreChangeList RemoveLoginsCreatedBetweenInternal(
-      base::Time delete_begin,
-      base::Time delete_end);
-  PasswordStoreChangeList RemoveLoginsByURLAndTimeInternal(
-      const base::RepeatingCallback<bool(const GURL&)>& url_filter,
-      base::Time delete_begin,
-      base::Time delete_end,
-      base::OnceCallback<void(bool)> sync_completion);
-
-  // Synchronous implementation for manipulating with statistics.
-  void AddSiteStatsInternal(const InteractionsStats& stats);
-  void RemoveSiteStatsInternal(const GURL& origin_domain);
-  std::vector<InteractionsStats> GetSiteStatsInternal(
-      const GURL& origin_domain);
-  void RemoveStatisticsByOriginAndTimeInternal(
-      const base::RepeatingCallback<bool(const GURL&)>& origin_filter,
-      base::Time delete_begin,
-      base::Time delete_end);
-
-  // Synchronous implementation for manipulating with field info.
-  void AddFieldInfoInternal(const FieldInfo& field_info);
-  std::vector<FieldInfo> GetAllFieldInfoInternal();
-  void RemoveFieldInfoByTimeInternal(base::Time remove_begin,
-                                     base::Time remove_end);
-
-  base::WeakPtr<syncer::ModelTypeControllerDelegate>
-  GetSyncControllerDelegateOnBackgroundSequence();
-
-  // Reports password store metrics that aren't reported by the
-  // StoreMetricsReporter. Namely, metrics related to inaccessible passwords,
-  // and bubble statistics.
-  void ReportMetrics();
-
-  // Used to trigger DCHECKs if tasks are posted after shut down.
-  bool was_shutdown_{false};
-
-  // The login SQL database. The LoginDatabase instance is received via the
-  // in an uninitialized state, so as to allow injecting mocks, then Init() is
-  // called on the background sequence in a deferred manner. If opening the DB
-  // fails, |login_db_| will be reset and stay NULL for the lifetime of |this|.
-  std::unique_ptr<LoginDatabase> login_db_;
-
-  std::unique_ptr<PasswordSyncBridge> sync_bridge_;
-
-  // Whenever 'sync_bridge_'receive remote changes this callback is used to
-  // notify PasswordStore observers about them. Called on a main sequence from
-  // the 'NotifyLoginsChanged'.
-  RemoteChangesReceived remote_forms_changes_received_callback_;
-
-  std::unique_ptr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
-      deletion_notifier_;
-
-  // A list of callbacks that should be run once all pending deletions have been
-  // sent to the Sync server. Note that the vector itself lives on the
-  // background thread, but the callbacks must be run on the main thread!
-  std::vector<base::OnceCallback<void(bool)>> deletions_have_synced_callbacks_;
-  // Timeout closure that runs if sync takes too long to propagate deletions.
-  base::CancelableOnceClosure deletions_have_synced_timeout_;
-
-  // TaskRunner for tasks that run on the main sequence (usually the UI thread).
-  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
+  // The helper, owned by this backend instance, but
+  // living on the |background_task_runner_|. It will be deleted asynchronously
+  // during shutdown on the |background_task_runner_|, so it will outlive |this|
+  // along with all its in-flight tasks.
+  std::unique_ptr<LoginDatabaseAsyncHelper> helper_
+      GUARDED_BY_CONTEXT(sequence_checker_);
 
   // TaskRunner for all the background operations.
-  scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> background_task_runner_
+      GUARDED_BY_CONTEXT(sequence_checker_);
 
-  base::WeakPtrFactory<PasswordStoreBuiltInBackend> weak_ptr_factory_{this};
+  base::WeakPtrFactory<PasswordStoreBuiltInBackend> GUARDED_BY_CONTEXT(
+      sequence_checker_) weak_ptr_factory_{this};
 };
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc
index b310e60..6872600 100644
--- a/components/password_manager/core/browser/password_store_unittest.cc
+++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -24,6 +24,7 @@
 #include "components/password_manager/core/browser/android_affiliation/mock_affiliated_match_helper.h"
 #include "components/password_manager/core/browser/fake_password_store_backend.h"
 #include "components/password_manager/core/browser/form_parsing/form_parser.h"
+#include "components/password_manager/core/browser/login_database.h"
 #include "components/password_manager/core/browser/mock_password_store_backend.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
@@ -124,64 +125,6 @@
   base::WeakPtrFactory<MockPasswordStoreConsumer> weak_ptr_factory_{this};
 };
 
-class MockPasswordStoreSigninNotifier : public PasswordStoreSigninNotifier {
- public:
-  MOCK_METHOD(void,
-              SubscribeToSigninEvents,
-              (PasswordReuseManager * manager),
-              (override));
-  MOCK_METHOD(void, UnsubscribeFromSigninEvents, (), (override));
-};
-
-class MockMetadataStore : public PasswordStoreSync::MetadataStore {
- public:
-  MOCK_METHOD(void, DeleteAllSyncMetadata, (), (override));
-  MOCK_METHOD(void,
-              SetDeletionsHaveSyncedCallback,
-              (base::RepeatingCallback<void(bool)> callback),
-              (override));
-  MOCK_METHOD(bool, HasUnsyncedDeletions, (), (override));
-
-  std::unique_ptr<syncer::MetadataBatch> GetAllSyncMetadata() override {
-    return std::make_unique<syncer::MetadataBatch>();
-  }
-
-  bool UpdateSyncMetadata(syncer::ModelType model_type,
-                          const std::string& storage_key,
-                          const sync_pb::EntityMetadata& metadata) override {
-    return true;
-  }
-
-  bool ClearSyncMetadata(syncer::ModelType model_type,
-                         const std::string& storage_key) override {
-    return true;
-  }
-
-  bool UpdateModelTypeState(
-      syncer::ModelType model_type,
-      const sync_pb::ModelTypeState& model_type_state) override {
-    return true;
-  }
-
-  bool ClearModelTypeState(syncer::ModelType model_type) override {
-    return true;
-  }
-};
-
-class BackendImplWithMockedMetadataStore : public PasswordStoreBuiltInBackend {
- public:
-  explicit BackendImplWithMockedMetadataStore(
-      std::unique_ptr<LoginDatabase> login_database)
-      : PasswordStoreBuiltInBackend(std::move(login_database)) {}
-
-  PasswordStoreSync::MetadataStore* GetMetadataStore() override {
-    return &metadata_store_;
-  }
-
- private:
-  MockMetadataStore metadata_store_;
-};
-
 PasswordForm MakePasswordForm(const std::string& signon_realm) {
   PasswordForm form;
   form.url = GURL("http://www.origin.com");
@@ -286,14 +229,6 @@
             password_manager::IsAccountStore(false))));
   }
 
-  scoped_refptr<PasswordStore> CreatePasswordStoreWithMockedMetaData() {
-    return base::MakeRefCounted<PasswordStore>(
-        std::make_unique<BackendImplWithMockedMetadataStore>(
-            std::make_unique<LoginDatabase>(
-                test_login_db_file_path(),
-                password_manager::IsAccountStore(false))));
-  }
-
   TestingPrefServiceSimple* pref_service() { return &pref_service_; }
 
  protected:
@@ -1494,7 +1429,7 @@
 }
 
 TEST_F(PasswordStoreTest, TestUnblockListEmptyStore) {
-  scoped_refptr<PasswordStore> store = CreatePasswordStoreWithMockedMetaData();
+  scoped_refptr<PasswordStore> store = CreatePasswordStore();
   store->Init(/*prefs=*/nullptr, /*affiliated_match_helper=*/nullptr);
   WaitForPasswordStore();
 
diff --git a/components/policy/core/browser/policy_pref_mapping_test.cc b/components/policy/core/browser/policy_pref_mapping_test.cc
index 41f8ff2..8d08de61 100644
--- a/components/policy/core/browser/policy_pref_mapping_test.cc
+++ b/components/policy/core/browser/policy_pref_mapping_test.cc
@@ -153,9 +153,9 @@
 
     pref_ = name;
     if (value)
-      value_ = value->CreateDeepCopy();
+      value_ = value->Clone();
     if (default_value)
-      default_value_ = default_value->CreateDeepCopy();
+      default_value_ = default_value->Clone();
 
     if (value && default_value) {
       ADD_FAILURE()
@@ -170,8 +170,16 @@
 
   const std::string& pref() const { return pref_; }
 
-  const base::Value* value() const { return value_.get(); }
-  const base::Value* default_value() const { return default_value_.get(); }
+  const base::Value* value() const {
+    if (value_.is_none())
+      return nullptr;
+    return &value_;
+  }
+  const base::Value* default_value() const {
+    if (default_value_.is_none())
+      return nullptr;
+    return &default_value_;
+  }
 
   PrefLocation location() const { return location_; }
 
@@ -185,8 +193,8 @@
   bool check_for_recommended_;
 
   // At most one of these will be set.
-  std::unique_ptr<base::Value> value_;
-  std::unique_ptr<base::Value> default_value_;
+  base::Value value_;
+  base::Value default_value_;
 };
 
 // Contains the testing details for a single pref affected by a policy. This is
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 00b8ed2..582d28fb 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -19531,7 +19531,7 @@
     },
     {
       'name': 'SharedArrayBufferUnrestrictedAccessAllowed',
-      'owners': ['bbudge@chromium.org', 'vahl@chromium.org'],
+      'owners': ['arthursonzogni@chromium.org', 'vahl@chromium.org'],
       'type': 'main',
       'schema': { 'type': 'boolean' },
       'supported_on': ['chrome.*:91-', 'chrome_os:91-'],
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
index 35e78412..e0c8b8c 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
@@ -22,6 +22,7 @@
 #include "ui/accelerated_widget_mac/ca_transaction_observer.h"
 #include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
 #include "ui/base/cocoa/command_dispatcher.h"
+#include "ui/base/cocoa/weak_ptr_nsobject.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/display/display_observer.h"
 
@@ -253,6 +254,7 @@
   void ReleaseCapture() override;
   void RedispatchKeyEvent(
       const std::vector<uint8_t>& native_event_data) override;
+  void SetLocalEventMonitorEnabled(bool enable) override;
   void CreateWindowControlsOverlayNSView(
       const mojom::WindowControlsOverlayNSViewType overlay_type) override;
   void UpdateWindowControlsOverlayNSView(
@@ -326,6 +328,7 @@
   std::unique_ptr<CocoaWindowMoveLoop> window_move_loop_;
   ui::ModalType modal_type_ = ui::MODAL_TYPE_NONE;
   bool is_translucent_window_ = false;
+  id key_down_event_monitor_ = nil;
 
   // Intended for PWAs with window controls overlay display override. These two
   // NSViews are added on top of the non client area to route events to the
@@ -399,6 +402,8 @@
 
   mojo::AssociatedReceiver<remote_cocoa::mojom::NativeWidgetNSWindow>
       bridge_mojo_receiver_{this};
+
+  ui::WeakPtrNSObjectFactory<NativeWidgetNSWindowBridge> ns_weak_factory_;
 };
 
 }  // namespace remote_cocoa
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 2cb46846..1db44af 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -313,12 +313,15 @@
     : id_(bridged_native_widget_id),
       host_(host),
       host_helper_(host_helper),
-      text_input_host_(text_input_host) {
+      text_input_host_(text_input_host),
+      ns_weak_factory_(this) {
   DCHECK(GetIdToWidgetImplMap().find(id_) == GetIdToWidgetImplMap().end());
   GetIdToWidgetImplMap().insert(std::make_pair(id_, this));
 }
 
 NativeWidgetNSWindowBridge::~NativeWidgetNSWindowBridge() {
+  SetLocalEventMonitorEnabled(false);
+  DCHECK(!key_down_event_monitor_);
   GetPendingWindowTitleMap().erase(window_.get());
   // The delegate should be cleared already. Note this enforces the precondition
   // that -[NSWindow close] is invoked on the hosted window before the
@@ -796,6 +799,38 @@
   return mouse_capture_ && mouse_capture_->IsActive();
 }
 
+void NativeWidgetNSWindowBridge::SetLocalEventMonitorEnabled(bool enabled) {
+  if (enabled) {
+    // Create the event montitor if it does not exist yet.
+    if (key_down_event_monitor_)
+      return;
+
+    // Capture a WeakPtr via NSObject. This allows the block to detect another
+    // event monitor for the same event deleting `this`.
+    WeakPtrNSObject* handle = ns_weak_factory_.handle();
+    auto block = ^NSEvent*(NSEvent* event) {
+      auto* bridge =
+          ui::WeakPtrNSObjectFactory<NativeWidgetNSWindowBridge>::Get(handle);
+      if (!bridge)
+        return event;
+      std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event);
+      bool event_handled = false;
+      bridge->host_->DispatchMonitorEvent(std::move(ui_event), &event_handled);
+      return event_handled ? nil : event;
+    };
+    key_down_event_monitor_ =
+        [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
+                                              handler:block];
+  } else {
+    // Destroy the event monitor if it exists.
+    if (!key_down_event_monitor_)
+      return;
+
+    [NSEvent removeMonitor:key_down_event_monitor_];
+    key_down_event_monitor_ = nil;
+  }
+}
+
 bool NativeWidgetNSWindowBridge::HasWindowRestorationData() {
   return !pending_restoration_data_.empty();
 }
diff --git a/components/remote_cocoa/common/native_widget_ns_window.mojom b/components/remote_cocoa/common/native_widget_ns_window.mojom
index b82f559f..0353678 100644
--- a/components/remote_cocoa/common/native_widget_ns_window.mojom
+++ b/components/remote_cocoa/common/native_widget_ns_window.mojom
@@ -8,6 +8,7 @@
 import "mojo/public/mojom/base/string16.mojom";
 import "services/network/public/mojom/network_param.mojom";
 import "ui/base/mojom/ui_base_types.mojom";
+import "ui/events/mojom/event_constants.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 import "ui/gfx/mojom/ca_layer_params.mojom";
 
@@ -226,6 +227,9 @@
   // Redispatch a keyboard event using the widget's window's CommandDispatcher.
   RedispatchKeyEvent(array<uint8> native_event_data);
 
+  // Enable or disable this widget's local event monitor.
+  SetLocalEventMonitorEnabled(bool enabled);
+
   // Add the overlay NSView for a PWA with window controls overlay
   // display override given a |overlay_type|.
   CreateWindowControlsOverlayNSView(
diff --git a/components/remote_cocoa/common/native_widget_ns_window_host.mojom b/components/remote_cocoa/common/native_widget_ns_window_host.mojom
index 50daf00..e7d68ea 100644
--- a/components/remote_cocoa/common/native_widget_ns_window_host.mojom
+++ b/components/remote_cocoa/common/native_widget_ns_window_host.mojom
@@ -89,6 +89,11 @@
   DispatchKeyEventToMenuControllerRemote(ui.mojom.Event event) =>
       (bool event_swallowed, bool event_handled);
 
+  // Called when the NSEvent monitor observes an event. If `event_handled` is
+  // true, then do not continue dispatching the event.
+  [Sync]
+  DispatchMonitorEvent(ui.mojom.Event event) => (bool event_handled);
+
   // Synchronously return in  |has_menu_controller| whether or not a menu
   // controller exists for this widget.
   [Sync]
diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h
index d034cb14..48543083 100644
--- a/components/user_manager/user_manager_base.h
+++ b/components/user_manager/user_manager_base.h
@@ -155,6 +155,7 @@
   // not full initialized yet" flag.
   virtual void SetIsCurrentUserNew(bool is_new);
 
+  // TODO(crbug.com/1187062): Refactor this to remove use of ListValue.
   // Helper function that converts users from |users_list| to |users_vector| and
   // |users_set|. Duplicates and users already present in |existing_users| are
   // skipped.
diff --git a/components/viz/common/gpu/dawn_context_provider.cc b/components/viz/common/gpu/dawn_context_provider.cc
index 1810315..979c4c4c 100644
--- a/components/viz/common/gpu/dawn_context_provider.cc
+++ b/components/viz/common/gpu/dawn_context_provider.cc
@@ -17,14 +17,14 @@
 
 namespace {
 
-dawn_native::BackendType GetDefaultBackendType() {
+wgpu::BackendType GetDefaultBackendType() {
 #if defined(OS_WIN)
-  return dawn_native::BackendType::D3D12;
+  return wgpu::BackendType::D3D12;
 #elif defined(OS_LINUX) || defined(OS_CHROMEOS)
-  return dawn_native::BackendType::Vulkan;
+  return wgpu::BackendType::Vulkan;
 #else
   NOTREACHED();
-  return dawn_native::BackendType::Null;
+  return wgpu::BackendType::Null;
 #endif
 }
 
@@ -49,7 +49,7 @@
 
 DawnContextProvider::~DawnContextProvider() = default;
 
-wgpu::Device DawnContextProvider::CreateDevice(dawn_native::BackendType type) {
+wgpu::Device DawnContextProvider::CreateDevice(wgpu::BackendType type) {
   instance_.DiscoverDefaultAdapters();
   DawnProcTable backend_procs = dawn_native::GetProcs();
   dawnProcSetProcs(&backend_procs);
@@ -65,7 +65,9 @@
 
   std::vector<dawn_native::Adapter> adapters = instance_.GetAdapters();
   for (dawn_native::Adapter adapter : adapters) {
-    if (adapter.GetBackendType() == type)
+    wgpu::AdapterProperties properties;
+    adapter.GetProperties(&properties);
+    if (properties.backendType == type)
       return adapter.CreateDevice(&descriptor);
   }
   return nullptr;
diff --git a/components/viz/common/gpu/dawn_context_provider.h b/components/viz/common/gpu/dawn_context_provider.h
index f360ad7..2d911a6 100644
--- a/components/viz/common/gpu/dawn_context_provider.h
+++ b/components/viz/common/gpu/dawn_context_provider.h
@@ -31,7 +31,7 @@
  private:
   DawnContextProvider();
 
-  wgpu::Device CreateDevice(dawn_native::BackendType type);
+  wgpu::Device CreateDevice(wgpu::BackendType type);
 
   dawn_native::Instance instance_;
   wgpu::Device device_;
diff --git a/components/webapps/browser/android/add_to_homescreen_data_fetcher.h b/components/webapps/browser/android/add_to_homescreen_data_fetcher.h
index e5031bc..9eb6e68 100644
--- a/components/webapps/browser/android/add_to_homescreen_data_fetcher.h
+++ b/components/webapps/browser/android/add_to_homescreen_data_fetcher.h
@@ -50,7 +50,7 @@
 
   // Initialize the fetcher by requesting the information about the page from
   // the renderer process. The initialization is asynchronous and
-  // OnDidGetWebApplicationInfo is expected to be called when finished.
+  // OnDidGetWebAppInstallInfo is expected to be called when finished.
   // |observer| must outlive AddToHomescreenDataFetcher.
   AddToHomescreenDataFetcher(content::WebContents* web_contents,
                              int data_timeout_ms,
diff --git a/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc b/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
index 3bda3494..801c5b6b 100644
--- a/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
+++ b/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
@@ -38,7 +38,7 @@
 
 namespace {
 
-const char* kWebApplicationInfoTitle = "Meta Title";
+const char* kWebAppInstallInfoTitle = "Meta Title";
 const char* kDefaultManifestUrl = "https://www.example.com/manifest.json";
 const char* kDefaultIconUrl = "https://www.example.com/icon.png";
 const char* kDefaultManifestName = "Default Name";
@@ -253,7 +253,7 @@
     webapps::mojom::WebPageMetadataPtr web_page_metadata(
         webapps::mojom::WebPageMetadata::New());
     web_page_metadata->application_name =
-        base::ASCIIToUTF16(kWebApplicationInfoTitle);
+        base::ASCIIToUTF16(kWebAppInstallInfoTitle);
 
     fetcher->OnDidGetWebPageMetadata(
         mojo::AssociatedRemote<webapps::mojom::WebPageMetadataAgent>(),
@@ -329,7 +329,7 @@
   base::HistogramTester histograms;
   ObserverWaiter waiter;
   std::unique_ptr<AddToHomescreenDataFetcher> fetcher = BuildFetcher(&waiter);
-  RunFetcher(fetcher.get(), waiter, kWebApplicationInfoTitle,
+  RunFetcher(fetcher.get(), waiter, kWebAppInstallInfoTitle,
              blink::mojom::DisplayMode::kBrowser, false);
   CheckHistograms(histograms);
 }
@@ -366,7 +366,7 @@
   base::HistogramTester histograms;
   ObserverWaiter waiter;
   std::unique_ptr<AddToHomescreenDataFetcher> fetcher = BuildFetcher(&waiter);
-  RunFetcher(fetcher.get(), waiter, kWebApplicationInfoTitle,
+  RunFetcher(fetcher.get(), waiter, kWebAppInstallInfoTitle,
              blink::mojom::DisplayMode::kBrowser, false);
   CheckHistograms(histograms);
 
@@ -384,7 +384,7 @@
   base::HistogramTester histograms;
   ObserverWaiter waiter;
   std::unique_ptr<AddToHomescreenDataFetcher> fetcher = BuildFetcher(&waiter);
-  RunFetcher(fetcher.get(), waiter, kWebApplicationInfoTitle,
+  RunFetcher(fetcher.get(), waiter, kWebAppInstallInfoTitle,
              blink::mojom::DisplayMode::kBrowser, false);
   CheckHistograms(histograms);
 
@@ -401,7 +401,7 @@
   base::HistogramTester histograms;
   ObserverWaiter waiter;
   std::unique_ptr<AddToHomescreenDataFetcher> fetcher = BuildFetcher(&waiter);
-  RunFetcher(fetcher.get(), waiter, kWebApplicationInfoTitle,
+  RunFetcher(fetcher.get(), waiter, kWebAppInstallInfoTitle,
              blink::mojom::DisplayMode::kBrowser, false);
   NavigateAndCommit(GURL("about:blank"));
   CheckHistograms(histograms);
@@ -570,7 +570,7 @@
   // Test that when the manifest does not provide either Manifest::short_name
   // nor Manifest::name that:
   //  - The page is not WebAPK compatible.
-  //  - WebApplicationInfo::title is used as the "name".
+  //  - WebAppInstallInfo::title is used as the "name".
   //  - We still use the icons from the manifest.
   blink::mojom::ManifestPtr manifest = BuildDefaultManifest();
   manifest->name = absl::nullopt;
@@ -580,13 +580,13 @@
   SetManifest(std::move(manifest));
   ObserverWaiter waiter;
   std::unique_ptr<AddToHomescreenDataFetcher> fetcher = BuildFetcher(&waiter);
-  RunFetcher(fetcher.get(), waiter, kWebApplicationInfoTitle,
+  RunFetcher(fetcher.get(), waiter, kWebAppInstallInfoTitle,
              blink::mojom::DisplayMode::kStandalone, false);
 
   EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().name,
-                                kWebApplicationInfoTitle));
+                                kWebAppInstallInfoTitle));
   EXPECT_TRUE(base::EqualsASCII(fetcher->shortcut_info().short_name,
-                                kWebApplicationInfoTitle));
+                                kWebAppInstallInfoTitle));
   EXPECT_FALSE(fetcher->primary_icon().drawsNothing());
   EXPECT_EQ(fetcher->shortcut_info().best_primary_icon_url,
             GURL(kDefaultIconUrl));
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 04a7566..f9a60227 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -286,6 +286,7 @@
   PMM_SUBSCRIBE_INVALID_ORIGIN = 259,
   PMM_UNSUBSCRIBE_INVALID_ORIGIN = 260,
   PMM_GET_SUBSCRIPTION_INVALID_ORIGIN = 261,
+  RFH_INACTIVE_CHECK_FROM_PENDING_COMMIT_RFH = 262,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc
index a23e53b..5fda70eb 100644
--- a/content/browser/devtools/protocol/tracing_handler.cc
+++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -86,30 +86,24 @@
   return out_str;
 }
 
-std::unique_ptr<base::Value> ConvertDictKeyStyle(const base::Value& value) {
-  const base::DictionaryValue* dict = nullptr;
-  if (value.GetAsDictionary(&dict)) {
-    std::unique_ptr<base::DictionaryValue> out_dict(
-        new base::DictionaryValue());
-    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
-         it.Advance()) {
-      out_dict->SetKey(
-          ConvertFromCamelCase(it.key(), '_'),
-          base::Value::FromUniquePtrValue(ConvertDictKeyStyle(it.value())));
+base::Value ConvertDictKeyStyle(const base::Value& value) {
+  if (value.is_dict()) {
+    base::Value out(base::Value::Type::DICTIONARY);
+    for (auto kv : value.DictItems()) {
+      out.SetKey(ConvertFromCamelCase(kv.first, '_'),
+                 ConvertDictKeyStyle(kv.second));
     }
-    return std::move(out_dict);
+    return out;
   }
 
   if (value.is_list()) {
-    base::Value::ListStorage out_list_storage;
-    base::Value out_list(std::move(out_list_storage));
-    for (const auto& key : value.GetList())
-      out_list.Append(
-          base::Value::FromUniquePtrValue(ConvertDictKeyStyle(key)));
-    return base::Value::ToUniquePtrValue(out_list.Clone());
+    base::Value out(base::Value::Type::LIST);
+    for (const auto& v : value.GetList())
+      out.Append(ConvertDictKeyStyle(v));
+    return out;
   }
 
-  return base::Value::ToUniquePtrValue(value.Clone());
+  return value.Clone();
 }
 
 class DevToolsTraceEndpointProxy : public TracingController::TraceDataEndpoint {
@@ -734,8 +728,7 @@
               .get(),
           1000);
       if (value && value->is_dict()) {
-        browser_config = GetTraceConfigFromDevToolsConfig(
-            *static_cast<base::DictionaryValue*>(value.get()));
+        browser_config = GetTraceConfigFromDevToolsConfig(*value.get());
       }
     } else if (categories.isJust() || options.isJust()) {
       browser_config = base::trace_event::TraceConfig(categories.fromMaybe(""),
@@ -1151,17 +1144,11 @@
 
 // static
 base::trace_event::TraceConfig TracingHandler::GetTraceConfigFromDevToolsConfig(
-    const base::DictionaryValue& devtools_config) {
-  std::unique_ptr<base::Value> value = ConvertDictKeyStyle(devtools_config);
-  DCHECK(value && value->is_dict());
-  std::unique_ptr<base::DictionaryValue> tracing_dict(
-      static_cast<base::DictionaryValue*>(value.release()));
-
-  std::string mode;
-  if (tracing_dict->GetString(kRecordModeParam, &mode))
-    tracing_dict->SetString(kRecordModeParam, ConvertFromCamelCase(mode, '-'));
-
-  return base::trace_event::TraceConfig(*tracing_dict);
+    const base::Value& devtools_config) {
+  base::Value config = ConvertDictKeyStyle(devtools_config);
+  if (std::string* mode = config.FindStringPath(kRecordModeParam))
+    config.SetStringPath(kRecordModeParam, ConvertFromCamelCase(*mode, '-'));
+  return base::trace_event::TraceConfig(config);
 }
 
 }  // namespace protocol
diff --git a/content/browser/devtools/protocol/tracing_handler.h b/content/browser/devtools/protocol/tracing_handler.h
index b0c6b73..48ecb286 100644
--- a/content/browser/devtools/protocol/tracing_handler.h
+++ b/content/browser/devtools/protocol/tracing_handler.h
@@ -24,13 +24,12 @@
 #include "third_party/perfetto/include/perfetto/tracing/tracing.h"
 
 namespace base {
-class DictionaryValue;
 
 namespace trace_event {
 class TraceConfig;
 }
 class RepeatingTimer;
-}
+}  // namespace base
 
 namespace media {
 class VideoFrame;
@@ -131,8 +130,7 @@
   void EmitFrameTree();
   static bool IsStartupTracingActive();
   CONTENT_EXPORT static base::trace_event::TraceConfig
-      GetTraceConfigFromDevToolsConfig(
-          const base::DictionaryValue& devtools_config);
+  GetTraceConfigFromDevToolsConfig(const base::Value& devtools_config);
   perfetto::TraceConfig CreatePerfettoConfiguration(
       const base::trace_event::TraceConfig& browser_config,
       bool return_as_stream,
diff --git a/content/browser/devtools/protocol/tracing_handler_unittest.cc b/content/browser/devtools/protocol/tracing_handler_unittest.cc
index 7530a42..7bee9d33 100644
--- a/content/browser/devtools/protocol/tracing_handler_unittest.cc
+++ b/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -91,13 +91,11 @@
 };
 
 TEST_F(TracingHandlerTest, GetTraceConfigFromDevToolsConfig) {
-  std::unique_ptr<base::Value> value =
-      base::JSONReader::ReadDeprecated(kCustomTraceConfigStringDevToolsStyle);
-  std::unique_ptr<base::DictionaryValue> devtools_style_dict(
-      static_cast<base::DictionaryValue*>(value.release()));
+  base::Value devtools_config =
+      base::JSONReader::Read(kCustomTraceConfigStringDevToolsStyle).value();
 
   base::trace_event::TraceConfig trace_config =
-      TracingHandler::GetTraceConfigFromDevToolsConfig(*devtools_style_dict);
+      TracingHandler::GetTraceConfigFromDevToolsConfig(devtools_config);
 
   EXPECT_STREQ(kCustomTraceConfigString, trace_config.ToString().c_str());
 }
diff --git a/content/browser/find_request_manager_browsertest.cc b/content/browser/find_request_manager_browsertest.cc
index aec081de..ea2c920 100644
--- a/content/browser/find_request_manager_browsertest.cc
+++ b/content/browser/find_request_manager_browsertest.cc
@@ -956,7 +956,9 @@
 }  // namespace
 
 // Tests activating the find match nearest to a given point.
-IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, ActivateNearestFindMatch) {
+// TODO(crbug.com/1285135): Fix flaky failures.
+IN_PROC_BROWSER_TEST_P(FindRequestManagerTest,
+                       DISABLED_ActivateNearestFindMatch) {
   LoadAndWait("/find_in_page.html");
   bool test_with_oopif = GetParam();
   if (test_with_oopif)
diff --git a/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc b/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
index e67c6ef5..0b4079f 100644
--- a/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
@@ -5,7 +5,6 @@
 #include "base/memory/raw_ptr.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
 #include "content/browser/picture_in_picture/picture_in_picture_service_impl.h"
 #include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
 #include "content/public/browser/content_browser_client.h"
@@ -148,6 +147,11 @@
 
 class PictureInPictureContentBrowserTest : public ContentBrowserTest {
  public:
+  ~PictureInPictureContentBrowserTest() override {
+    if (old_browser_client_.has_value())
+      SetBrowserClientForTesting(old_browser_client_.value());
+  }
+
   void SetUpCommandLine(base::CommandLine* command_line) override {
     ContentBrowserTest::SetUpCommandLine(command_line);
 
@@ -166,12 +170,6 @@
     shell()->web_contents()->SetDelegate(web_contents_delegate_.get());
   }
 
-  void TearDownOnMainThread() override {
-    SetBrowserClientForTesting(old_browser_client_);
-
-    ContentBrowserTest::TearDownOnMainThread();
-  }
-
   void WaitForPlaybackState(OverlayWindow::PlaybackState playback_state,
                             const base::Location& location = FROM_HERE) {
     if (overlay_window()->playback_state() == playback_state)
@@ -210,7 +208,7 @@
 
  private:
   std::unique_ptr<TestWebContentsDelegate> web_contents_delegate_;
-  raw_ptr<ContentBrowserClient> old_browser_client_ = nullptr;
+  absl::optional<raw_ptr<ContentBrowserClient>> old_browser_client_;
   TestContentBrowserClient content_browser_client_;
 };
 
@@ -539,15 +537,8 @@
 // Tests Media Session action availability upon reaching the end of stream by
 // verifying that the "nexttrack" action can be invoked after playing through
 // to the end of media.
-#if defined(OS_LINUX) && defined(THREAD_SANITIZER)
-#define MAYBE_ActionAvailableAfterEndOfStreamAndSrcUpdate \
-  DISABLED_ActionAvailableAfterEndOfStreamAndSrcUpdate
-#else
-#define MAYBE_ActionAvailableAfterEndOfStreamAndSrcUpdate \
-  ActionAvailableAfterEndOfStreamAndSrcUpdate
-#endif
 IN_PROC_BROWSER_TEST_F(MediaSessionPictureInPictureContentBrowserTest,
-                       MAYBE_ActionAvailableAfterEndOfStreamAndSrcUpdate) {
+                       ActionAvailableAfterEndOfStreamAndSrcUpdate) {
   ASSERT_TRUE(NavigateToURL(
       shell(), GetTestUrl("media/picture_in_picture", "one-video.html")));
 
diff --git a/content/browser/portal/portal_navigation_throttle.cc b/content/browser/portal/portal_navigation_throttle.cc
index 2fd4309..c850a1e 100644
--- a/content/browser/portal/portal_navigation_throttle.cc
+++ b/content/browser/portal/portal_navigation_throttle.cc
@@ -32,8 +32,11 @@
 std::unique_ptr<PortalNavigationThrottle>
 PortalNavigationThrottle::MaybeCreateThrottleFor(
     NavigationHandle* navigation_handle) {
-  if (!Portal::IsEnabled() || !navigation_handle->IsInMainFrame())
+  if (!Portal::IsEnabled() || !navigation_handle->IsInMainFrame() ||
+      navigation_handle->GetNavigatingFrameType() ==
+          FrameType::kFencedFrameRoot) {
     return nullptr;
+  }
 
   return base::WrapUnique(new PortalNavigationThrottle(navigation_handle));
 }
@@ -66,6 +69,9 @@
   if (!portal)
     return PROCEED;
 
+  DCHECK_NE(navigation_handle()->GetNavigatingFrameType(),
+            FrameType::kFencedFrameRoot);
+
   GURL url = navigation_handle()->GetURL();
   CHECK(!HasWebUIScheme(url))
       << "Portals should not even be able to attempt to reach WebUI";
diff --git a/content/browser/portal/portal_navigation_throttle_browsertest.cc b/content/browser/portal/portal_navigation_throttle_browsertest.cc
index 134fefe..072e471 100644
--- a/content/browser/portal/portal_navigation_throttle_browsertest.cc
+++ b/content/browser/portal/portal_navigation_throttle_browsertest.cc
@@ -15,6 +15,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/content_browser_test.h"
+#include "content/public/test/fenced_frame_test_util.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/portal/portal_activated_observer.h"
@@ -46,7 +47,7 @@
  protected:
   virtual bool ShouldEnableCrossOriginPortals() const { return false; }
 
-  void SetUp() override {
+  PortalNavigationThrottleBrowserTest() {
     if (ShouldEnableCrossOriginPortals()) {
       scoped_feature_list_.InitWithFeatures(
           /*enabled_features=*/{blink::features::kPortals,
@@ -57,7 +58,6 @@
           /*enabled_features=*/{blink::features::kPortals},
           /*disabled_features=*/{blink::features::kPortalsCrossOrigin});
     }
-    ContentBrowserTest::SetUp();
   }
 
   void SetUpOnMainThread() override {
@@ -392,5 +392,42 @@
   }
 }
 
+class PortalNavigationThrottleFencedFrameBrowserTest
+    : public PortalNavigationThrottleBrowserTest {
+ public:
+  PortalNavigationThrottleFencedFrameBrowserTest() = default;
+  ~PortalNavigationThrottleFencedFrameBrowserTest() override = default;
+  PortalNavigationThrottleFencedFrameBrowserTest(
+      const PortalNavigationThrottleFencedFrameBrowserTest&) = delete;
+
+  PortalNavigationThrottleFencedFrameBrowserTest& operator=(
+      const PortalNavigationThrottleFencedFrameBrowserTest&) = delete;
+
+  content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
+    return fenced_frame_helper_;
+  }
+
+ private:
+  content::test::FencedFrameTestHelper fenced_frame_helper_;
+};
+
+IN_PROC_BROWSER_TEST_F(PortalNavigationThrottleFencedFrameBrowserTest,
+                       SameOriginInitialNavigation) {
+  ASSERT_TRUE(NavigateToURL(
+      GetWebContents(),
+      embedded_test_server()->GetURL("portal.test", "/title1.html")));
+  Portal* portal = InsertAndWaitForPortal(
+      embedded_test_server()->GetURL("portal.test", "/title2.html"));
+  EXPECT_NE(portal, nullptr);
+
+  // Create a fenced frame.
+  GURL fenced_frame_url = embedded_test_server()->GetURL(
+      "fencedframe.test", "/fenced_frames/title1.html");
+  content::RenderFrameHost* fenced_frame_host =
+      fenced_frame_test_helper().CreateFencedFrame(
+          portal->GetPortalContents()->GetMainFrame(), fenced_frame_url);
+  EXPECT_NE(nullptr, fenced_frame_host);
+}
+
 }  // namespace
 }  // namespace content
diff --git a/content/browser/push_messaging/push_messaging_manager.cc b/content/browser/push_messaging/push_messaging_manager.cc
index 6f803d61..36af35e6 100644
--- a/content/browser/push_messaging/push_messaging_manager.cc
+++ b/content/browser/push_messaging/push_messaging_manager.cc
@@ -132,7 +132,7 @@
   RegisterData();
   RegisterData(RegisterData&& other) = default;
 
-  GURL requesting_origin;
+  url::Origin requesting_origin;
   int64_t service_worker_registration_id;
   absl::optional<std::string> existing_subscription_id;
   blink::mojom::PushSubscriptionOptionsPtr options;
@@ -193,10 +193,11 @@
     return;
   }
 
-  GURL origin = service_worker_registration->scope().DeprecatedGetOriginAsURL();
+  url::Origin origin =
+      url::Origin::Create(service_worker_registration->scope());
 
   if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
-          render_process_host_.GetID(), url::Origin::Create(origin))) {
+          render_process_host_.GetID(), origin)) {
     bad_message::ReceivedBadMessage(&render_process_host_,
                                     bad_message::PMM_SUBSCRIBE_INVALID_ORIGIN);
     return;
@@ -330,12 +331,12 @@
           // Request notifications permission (which will fail, since
           // notifications aren't supported in incognito), so the website can't
           // detect whether incognito is active.
-          GURL requesting_origin = data.requesting_origin;
+          url::Origin requesting_origin = data.requesting_origin;
           bool user_gesture = data.user_gesture;
           PermissionControllerImpl::FromBrowserContext(browser_context)
               ->RequestPermission(
                   PermissionType::NOTIFICATIONS, render_frame_host,
-                  requesting_origin, user_gesture,
+                  requesting_origin.GetURL(), user_gesture,
                   base::BindOnce(
                       &PushMessagingManager::DidRequestPermissionInIncognito,
                       AsWeakPtr(), std::move(data)));
@@ -346,19 +347,20 @@
   }
 
   int64_t registration_id = data.service_worker_registration_id;
-  GURL requesting_origin = data.requesting_origin;
+  url::Origin requesting_origin = data.requesting_origin;
   bool user_gesture = data.user_gesture;
 
   auto options = data.options->Clone();
   if (IsRequestFromDocument(render_frame_id_)) {
     push_service->SubscribeFromDocument(
-        requesting_origin, registration_id, render_process_host_.GetID(),
-        render_frame_id_, std::move(options), user_gesture,
+        requesting_origin.GetURL(), registration_id,
+        render_process_host_.GetID(), render_frame_id_, std::move(options),
+        user_gesture,
         base::BindOnce(&PushMessagingManager::DidRegister, AsWeakPtr(),
                        std::move(data)));
   } else {
     push_service->SubscribeFromWorker(
-        requesting_origin, registration_id, std::move(options),
+        requesting_origin.GetURL(), registration_id, std::move(options),
         base::BindOnce(&PushMessagingManager::DidRegister, AsWeakPtr(),
                        std::move(data)));
   }
@@ -420,14 +422,14 @@
     const std::vector<uint8_t>& auth,
     blink::mojom::PushRegistrationStatus status) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  url::Origin requesting_origin = url::Origin::Create(data.requesting_origin);
+  blink::StorageKey storage_key = blink::StorageKey(data.requesting_origin);
   int64_t registration_id = data.service_worker_registration_id;
   std::string application_server_key(
       std::string(data.options->application_server_key.begin(),
                   data.options->application_server_key.end()));
 
   service_worker_context_->StoreRegistrationUserData(
-      registration_id, blink::StorageKey(requesting_origin),
+      registration_id, std::move(storage_key),
       {{kPushRegistrationIdServiceWorkerKey, push_subscription_id},
        {kPushSenderIdServiceWorkerKey, application_server_key}},
       base::BindOnce(&PushMessagingManager::DidPersistRegistration,
@@ -503,10 +505,11 @@
     return;
   }
 
-  GURL origin = service_worker_registration->scope().DeprecatedGetOriginAsURL();
+  url::Origin origin =
+      url::Origin::Create(service_worker_registration->scope());
 
   if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
-          render_process_host_.GetID(), url::Origin::Create(origin))) {
+          render_process_host_.GetID(), origin)) {
     bad_message::ReceivedBadMessage(
         &render_process_host_, bad_message::PMM_UNSUBSCRIBE_INVALID_ORIGIN);
     return;
@@ -522,7 +525,7 @@
 void PushMessagingManager::UnsubscribeHavingGottenSenderId(
     UnsubscribeCallback callback,
     int64_t service_worker_registration_id,
-    const GURL& requesting_origin,
+    const url::Origin& requesting_origin,
     const std::vector<std::string>& sender_ids,
     blink::ServiceWorkerStatusCode service_worker_status) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -545,8 +548,8 @@
   }
 
   push_service->Unsubscribe(
-      blink::mojom::PushUnregistrationReason::JAVASCRIPT_API, requesting_origin,
-      service_worker_registration_id, sender_id,
+      blink::mojom::PushUnregistrationReason::JAVASCRIPT_API,
+      requesting_origin.GetURL(), service_worker_registration_id, sender_id,
       base::BindOnce(&PushMessagingManager::DidUnregister, AsWeakPtr(),
                      std::move(callback)));
 }
@@ -595,10 +598,10 @@
       service_worker_context_->GetLiveRegistration(
           service_worker_registration_id);
   if (registration) {
-    const GURL origin = registration->scope().DeprecatedGetOriginAsURL();
+    url::Origin origin = url::Origin::Create(registration->scope());
 
     if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin(
-            render_process_host_.GetID(), url::Origin::Create(origin))) {
+            render_process_host_.GetID(), std::move(origin))) {
       bad_message::ReceivedBadMessage(
           &render_process_host_,
           bad_message::PMM_GET_SUBSCRIPTION_INVALID_ORIGIN);
@@ -649,7 +652,7 @@
         break;
       }
 
-      const GURL origin = registration->scope().DeprecatedGetOriginAsURL();
+      const url::Origin origin = url::Origin::Create(registration->scope());
 
       GetSubscriptionInfo(
           origin, service_worker_registration_id, application_server_key,
@@ -701,7 +704,7 @@
 
 void PushMessagingManager::GetSubscriptionDidGetInfo(
     GetSubscriptionCallback callback,
-    const GURL& origin,
+    const url::Origin& origin,
     int64_t service_worker_registration_id,
     const std::string& application_server_key,
     bool is_valid,
@@ -751,7 +754,7 @@
     push_service->Unsubscribe(
         blink::mojom::PushUnregistrationReason::
             GET_SUBSCRIPTION_STORAGE_CORRUPT,
-        origin, service_worker_registration_id, application_server_key,
+        origin.GetURL(), service_worker_registration_id, application_server_key,
         base::BindOnce(&PushMessagingManager::GetSubscriptionDidUnsubscribe,
                        AsWeakPtr(), std::move(callback), status));
 
@@ -768,7 +771,7 @@
 }
 
 void PushMessagingManager::GetSubscriptionInfo(
-    const GURL& origin,
+    const url::Origin& origin,
     int64_t service_worker_registration_id,
     const std::string& sender_id,
     const std::string& push_subscription_id,
@@ -783,9 +786,9 @@
     return;
   }
 
-  push_service->GetSubscriptionInfo(origin, service_worker_registration_id,
-                                    sender_id, push_subscription_id,
-                                    std::move(callback));
+  push_service->GetSubscriptionInfo(origin.GetURL(),
+                                    service_worker_registration_id, sender_id,
+                                    push_subscription_id, std::move(callback));
 }
 
 PushMessagingService* PushMessagingManager::GetService() {
diff --git a/content/browser/push_messaging/push_messaging_manager.h b/content/browser/push_messaging/push_messaging_manager.h
index cdb9a91..2c79c4a 100644
--- a/content/browser/push_messaging/push_messaging_manager.h
+++ b/content/browser/push_messaging/push_messaging_manager.h
@@ -28,6 +28,10 @@
 }  // namespace mojom
 }  // namespace blink
 
+namespace url {
+class Origin;
+}  // namespace url
+
 namespace content {
 
 class RenderProcessHost;
@@ -127,7 +131,7 @@
 
   void GetSubscriptionDidGetInfo(
       GetSubscriptionCallback callback,
-      const GURL& origin,
+      const url::Origin& origin,
       int64_t service_worker_registration_id,
       const std::string& application_server_key,
       bool is_valid,
@@ -137,7 +141,7 @@
       const std::vector<uint8_t>& auth);
 
   void GetSubscriptionInfo(
-      const GURL& origin,
+      const url::Origin& origin,
       int64_t service_worker_registration_id,
       const std::string& sender_id,
       const std::string& push_subscription_id,
@@ -146,7 +150,7 @@
   void UnsubscribeHavingGottenSenderId(
       UnsubscribeCallback callback,
       int64_t service_worker_registration_id,
-      const GURL& requesting_origin,
+      const url::Origin& requesting_origin,
       const std::vector<std::string>& sender_id,
       blink::ServiceWorkerStatusCode service_worker_status);
 
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 4d44187a..074b73ed 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -5836,16 +5836,20 @@
       CancelPrerendering(PrerenderHost::FinalStatus::kDestroyed);
       return true;
     case LifecycleStateImpl::kSpeculative:
-    case LifecycleStateImpl::kPendingCommit:
       // We do not expect speculative or pending commit RenderFrameHosts to
       // generate events that require an active/inactive check. Don't crash the
       // browser process in case it comes from a compromised renderer, but kill
       // the renderer to avoid further confusion.
+      bad_message::ReceivedBadMessage(
+          GetProcess(), bad_message::RFH_INACTIVE_CHECK_FROM_SPECULATIVE_RFH);
+      return false;
+    case LifecycleStateImpl::kPendingCommit:
       // TODO(https://crbug.com/1191469): Understand the expected behaviour to
       // disallow activation for kPendingCommit RenderFrameHosts and update
       // accordingly.
       bad_message::ReceivedBadMessage(
-          GetProcess(), bad_message::RFH_INACTIVE_CHECK_FROM_SPECULATIVE_RFH);
+          GetProcess(),
+          bad_message::RFH_INACTIVE_CHECK_FROM_PENDING_COMMIT_RFH);
       return false;
     case LifecycleStateImpl::kActive:
       return false;
diff --git a/extensions/common/extension.h b/extensions/common/extension.h
index 3600b4aa..05a0a14b 100644
--- a/extensions/common/extension.h
+++ b/extensions/common/extension.h
@@ -321,7 +321,7 @@
   bool from_webstore() const { return (creation_flags_ & FROM_WEBSTORE) != 0; }
   // TODO(crbug.com/1065748): Retire this function when there are no old
   // entries.
-  bool from_desprecated_bookmark() const {
+  bool from_deprecated_bookmark() const {
     return (creation_flags_ & FROM_BOOKMARK) != 0;
   }
   bool may_be_untrusted() const {
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index 84c2f8c..134f292 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -572,9 +572,6 @@
     "//build/config/fuchsia/test/vulkan_capabilities.test-cmx",
   ]
   additional_manifests = [
-    # Required by ContextProvider to determine the services list.
-    "web_instance.cmx",
-
     # Required by ContextProvider unit-tests to launch the FakeContext process.
     "$target_gen_dir/web_engine_unittests_fake_instance.cmx",
   ]
@@ -620,9 +617,6 @@
     "//build/config/fuchsia/test/web_engine_required_capabilities.test-cmx",
     "//build/config/fuchsia/test/web_instance_host_capabilities.test-cmx",
   ]
-
-  # Required by web_instance_host.
-  additional_manifests = [ "//fuchsia/engine/web_instance.cmx" ]
 }
 
 cr_fuchsia_package("web_engine_shell_pkg") {
diff --git a/fuchsia/engine/web_engine_debug_integration_test.cc b/fuchsia/engine/web_engine_debug_integration_test.cc
index 71b11a7f..52769be 100644
--- a/fuchsia/engine/web_engine_debug_integration_test.cc
+++ b/fuchsia/engine/web_engine_debug_integration_test.cc
@@ -133,6 +133,7 @@
       return;
 
     fuchsia::web::CreateContextParams create_params;
+    create_params.set_features(fuchsia::web::ContextFeatureFlags::NETWORK);
     create_params.set_service_directory(std::move(directory));
     if (user_mode_debugging == UserModeDebugging::kEnabled)
       create_params.set_remote_debugging_port(0);
diff --git a/fuchsia/engine/web_engine_integration_logging_test.cc b/fuchsia/engine/web_engine_integration_logging_test.cc
index b93a496..04d6d15 100644
--- a/fuchsia/engine/web_engine_integration_logging_test.cc
+++ b/fuchsia/engine/web_engine_integration_logging_test.cc
@@ -119,9 +119,9 @@
   log_listener.ListenToLog(log(), nullptr);
 
   // Create the Context & Frame with all log severities enabled.
+  CreateContext(TestContextParams());
   fuchsia::web::CreateFrameParams frame_params;
   frame_params.set_debug_name(kFrameLogTag);
-  CreateContext(TestContextParams());
   CreateFrameWithParams(std::move(frame_params));
   frame_->SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel::DEBUG);
 
diff --git a/fuchsia/engine/web_engine_integration_test.cc b/fuchsia/engine/web_engine_integration_test.cc
index 8a3933f..e96519a 100644
--- a/fuchsia/engine/web_engine_integration_test.cc
+++ b/fuchsia/engine/web_engine_integration_test.cc
@@ -78,7 +78,8 @@
   fuchsia::web::CreateContextParams ContextParamsWithAudioAndTestData() {
     fuchsia::web::CreateContextParams create_params =
         TestContextParamsWithTestData();
-    create_params.set_features(fuchsia::web::ContextFeatureFlags::AUDIO);
+    *create_params.mutable_features() |=
+        fuchsia::web::ContextFeatureFlags::AUDIO;
     return create_params;
   }
 
@@ -533,7 +534,8 @@
 TEST_F(MAYBE_VulkanWebEngineIntegrationTest,
        WebGLContextPresentWithVulkanFeature) {
   fuchsia::web::CreateContextParams create_params = TestContextParams();
-  create_params.set_features(fuchsia::web::ContextFeatureFlags::VULKAN);
+  *create_params.mutable_features() |=
+      fuchsia::web::ContextFeatureFlags::VULKAN;
   CreateContextAndFrame(std::move(create_params));
 
   ASSERT_NO_FATAL_FAILURE(LoadUrlAndExpectResponse(
@@ -609,10 +611,9 @@
   // The VULKAN flag is required for hardware video decoders to be available.
   fuchsia::web::CreateContextParams create_params =
       ContextParamsWithAudioAndTestData();
-  create_params.set_features(
+  *create_params.mutable_features() |=
       fuchsia::web::ContextFeatureFlags::VULKAN |
-      fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER |
-      fuchsia::web::ContextFeatureFlags::AUDIO);
+      fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER;
   CreateContextAndFrame(std::move(create_params));
 
   static const uint16_t kTestMediaSessionId = 1;
diff --git a/fuchsia/engine/web_engine_integration_test_base.cc b/fuchsia/engine/web_engine_integration_test_base.cc
index f830f33d..cba804c 100644
--- a/fuchsia/engine/web_engine_integration_test_base.cc
+++ b/fuchsia/engine/web_engine_integration_test_base.cc
@@ -73,6 +73,10 @@
 fuchsia::web::CreateContextParams
 WebEngineIntegrationTestBase::TestContextParams() {
   fuchsia::web::CreateContextParams create_params;
+
+  // Most integration tests require networking, to load test web content.
+  create_params.set_features(fuchsia::web::ContextFeatureFlags::NETWORK);
+
   zx_status_t status = filtered_service_directory_.ConnectClient(
       create_params.mutable_service_directory()->NewRequest());
   ZX_CHECK(status == ZX_OK, status)
diff --git a/fuchsia/engine/web_instance_host/web_instance_host.cc b/fuchsia/engine/web_instance_host/web_instance_host.cc
index 1fccbd7..e5a5170 100644
--- a/fuchsia/engine/web_instance_host/web_instance_host.cc
+++ b/fuchsia/engine/web_instance_host/web_instance_host.cc
@@ -27,12 +27,9 @@
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
 #include "base/fuchsia/file_utils.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/process_context.h"
-#include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/process/process.h"
 #include "base/strings/strcat.h"
@@ -71,9 +68,6 @@
 
 namespace {
 
-// Path to the definition file for web Component instances.
-constexpr char kWebInstanceComponentPath[] = "/pkg/meta/web_instance.cmx";
-
 // Test-only URL for web hosting Component instances with WebUI resources.
 const char kWebInstanceWithWebUiComponentUrl[] =
     "fuchsia-pkg://fuchsia.com/web_engine_with_webui#meta/web_instance.cmx";
@@ -443,15 +437,105 @@
 #endif
 }
 
-std::vector<std::string> LoadWebInstanceSandboxServices() {
-  std::string cmx;
-  CHECK(ReadFileToString(base::FilePath(kWebInstanceComponentPath), &cmx));
-  absl::optional<base::Value> json = base::JSONReader::Read(cmx);
-  const base::Value* services = json->FindListPath("sandbox.services");
-  std::vector<std::string> result;
-  for (auto& entry : services->GetList())
-    result.push_back(std::move(entry.GetString()));
-  return result;
+// Returns the names of all services required by a web_instance.cmx component
+// instance configured with the specified set of feature flags. The caller is
+// responsible for verifying that |params| specifies a valid combination of
+// settings, before calling this function.
+std::vector<std::string> GetRequiredServicesForConfig(
+    const fuchsia::web::CreateContextParams& params) {
+  // All web_instance.cmx instances require a common set of services, described
+  // at:
+  //   https://fuchsia.dev/reference/fidl/fuchsia.web#CreateContextParams.service_directory
+  std::vector<std::string> services{
+      "fuchsia.device.NameProvider",     "fuchsia.fonts.Provider",
+      "fuchsia.intl.PropertyProvider",   "fuchsia.logger.LogSink",
+      "fuchsia.memorypressure.Provider", "fuchsia.process.Launcher",
+      "fuchsia.settings.Display",  // Used if preferred theme is DEFAULT.
+      "fuchsia.sysmem.Allocator"};
+
+  // TODO(crbug.com/1209031): Provide these conditionally, once corresponding
+  // ContextFeatureFlags have been defined.
+  services.insert(services.end(), {"fuchsia.camera3.DeviceWatcher",
+                                   "fuchsia.media.ProfileProvider"});
+
+  // Additional services are required depending on particular configuration
+  // parameters.
+  if (params.has_playready_key_system()) {
+    services.emplace_back("fuchsia.media.drm.PlayReady");
+  }
+
+  // Additional services are required dependent on the set of features specified
+  // for the instance, as described at:
+  //   https://fuchsia.dev/reference/fidl/fuchsia.web#ContextFeatureFlags
+  // Features are listed here in order of their enum value.
+  fuchsia::web::ContextFeatureFlags features = {};
+  if (params.has_features())
+    features = params.features();
+
+  // TODO(crbug.com/1020273): Allow access to network services only if the
+  // NETWORK feature flag is set.
+  services.insert(services.end(), {
+                                      "fuchsia.net.interfaces.State",
+                                      "fuchsia.net.name.Lookup",
+                                      "fuchsia.posix.socket.Provider",
+                                  });
+
+  if ((features & fuchsia::web::ContextFeatureFlags::AUDIO) ==
+      fuchsia::web::ContextFeatureFlags::AUDIO) {
+    services.insert(services.end(),
+                    {
+                        "fuchsia.media.Audio",
+                        "fuchsia.media.AudioDeviceEnumerator",
+                        "fuchsia.media.SessionAudioConsumerFactory",
+                    });
+  }
+
+  if ((features & fuchsia::web::ContextFeatureFlags::VULKAN) ==
+      fuchsia::web::ContextFeatureFlags::VULKAN) {
+    services.emplace_back("fuchsia.vulkan.loader.Loader");
+  }
+
+  if ((features & fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER) ==
+      fuchsia::web::ContextFeatureFlags::HARDWARE_VIDEO_DECODER) {
+    services.emplace_back("fuchsia.mediacodec.CodecFactory");
+  }
+
+  // HARDWARE_VIDEO_DECODER_ONLY does not require any additional services.
+
+  if ((features & fuchsia::web::ContextFeatureFlags::WIDEVINE_CDM) ==
+      fuchsia::web::ContextFeatureFlags::WIDEVINE_CDM) {
+    services.emplace_back("fuchsia.media.drm.Widevine");
+  }
+
+  // HEADLESS instances cannot create Views and therefore do not require access
+  // to any View-based services.
+  if ((features & fuchsia::web::ContextFeatureFlags::HEADLESS) !=
+      fuchsia::web::ContextFeatureFlags::HEADLESS) {
+    services.insert(services.end(),
+                    {
+                        "fuchsia.accessibility.semantics.SemanticsManager",
+                        "fuchsia.ui.composition.Allocator",
+                        "fuchsia.ui.composition.Flatland",
+                        "fuchsia.ui.scenic.Scenic",
+                    });
+  }
+
+  if ((features & fuchsia::web::ContextFeatureFlags::LEGACYMETRICS) ==
+      fuchsia::web::ContextFeatureFlags::LEGACYMETRICS) {
+    services.emplace_back("fuchsia.legacymetrics.MetricsRecorder");
+  }
+
+  if ((features & fuchsia::web::ContextFeatureFlags::KEYBOARD) ==
+      fuchsia::web::ContextFeatureFlags::KEYBOARD) {
+    services.emplace_back("fuchsia.ui.input3.Keyboard");
+  }
+
+  if ((features & fuchsia::web::ContextFeatureFlags::VIRTUAL_KEYBOARD) ==
+      fuchsia::web::ContextFeatureFlags::VIRTUAL_KEYBOARD) {
+    services.emplace_back("fuchsia.input.virtualkeyboard.ControllerCreator");
+  }
+
+  return services;
 }
 
 }  // namespace
@@ -513,16 +597,21 @@
     return ZX_ERR_INTERNAL;
   }
 
+  fuchsia::web::ContextFeatureFlags features = {};
+  if (params.has_features())
+    features = params.features();
+
   if (params.has_remote_debugging_port()) {
+    if ((features & fuchsia::web::ContextFeatureFlags::NETWORK) !=
+        fuchsia::web::ContextFeatureFlags::NETWORK) {
+      LOG(ERROR) << "Enabling remote debugging port requires NETWORK feature.";
+      return ZX_ERR_INVALID_ARGS;
+    }
     launch_args.AppendSwitchNative(
         switches::kRemoteDebuggingPort,
         base::NumberToString(params.remote_debugging_port()));
   }
 
-  fuchsia::web::ContextFeatureFlags features = {};
-  if (params.has_features())
-    features = params.features();
-
   const bool is_headless =
       (features & fuchsia::web::ContextFeatureFlags::HEADLESS) ==
       fuchsia::web::ContextFeatureFlags::HEADLESS;
@@ -550,8 +639,8 @@
     // VULKAN is required for DRM-protected video playback. Allow DRM to also be
     // enabled for HEADLESS Contexts, since Vulkan is never required for audio.
     if (!enable_vulkan && !is_headless) {
-      DLOG(ERROR) << "WIDEVINE_CDM and PLAYREADY_CDM features require VULKAN "
-                     " or HEADLESS.";
+      LOG(ERROR) << "WIDEVINE_CDM and PLAYREADY_CDM features require VULKAN "
+                    " or HEADLESS.";
       return ZX_ERR_NOT_SUPPORTED;
     }
     if (!params.has_cdm_data_directory()) {
@@ -717,12 +806,12 @@
   // Pass on the caller's service-directory request.
   launch_info.directory_request = services_request.TakeChannel();
 
-  // Set |additional_services| to redirect requests for all services specified
-  // in the web instance component manifest to be satisfied by the caller-
-  // supplied service directory. This ensures that the instance cannot access
-  // any services outside those provided by the caller.
+  // Set |additional_services| to redirect requests for only those services
+  // required for the specified |params|, to be satisfied by the caller-
+  // supplied service directory. This reduces the risk of an instance being
+  // able to somehow exploit services other than those that it should be using.
   launch_info.additional_services = fuchsia::sys::ServiceList::New();
-  launch_info.additional_services->names = LoadWebInstanceSandboxServices();
+  launch_info.additional_services->names = GetRequiredServicesForConfig(params);
   launch_info.additional_services->host_directory =
       service_directory.TakeChannel();
 
diff --git a/fuchsia/engine/web_instance_host_integration_test.cc b/fuchsia/engine/web_instance_host_integration_test.cc
index 5eacb5ef..5f4c7a1d 100644
--- a/fuchsia/engine/web_instance_host_integration_test.cc
+++ b/fuchsia/engine/web_instance_host_integration_test.cc
@@ -63,6 +63,7 @@
  protected:
   fuchsia::web::CreateContextParams TestContextParams() {
     fuchsia::web::CreateContextParams create_params;
+    create_params.set_features(fuchsia::web::ContextFeatureFlags::NETWORK);
     zx_status_t status = filtered_service_directory_.ConnectClient(
         create_params.mutable_service_directory()->NewRequest());
     ZX_CHECK(status == ZX_OK, status)
diff --git a/fuchsia/runners/BUILD.gn b/fuchsia/runners/BUILD.gn
index a7be37d..b57b9823 100644
--- a/fuchsia/runners/BUILD.gn
+++ b/fuchsia/runners/BUILD.gn
@@ -159,8 +159,6 @@
   package_name = "cast_runner"
   manifest = "cast/cast_runner.cmx"
 
-  # Required by web_instance_host.
-  additional_manifests = [ "//fuchsia/engine/web_instance.cmx" ]
   excluded_files = _web_instance_host_deps_files_to_exclude
 }
 
@@ -292,8 +290,6 @@
   package_name = "web_runner"
   manifest = "web/web_runner.cmx"
 
-  # Required by web_instance_host.
-  additional_manifests = [ "//fuchsia/engine/web_instance.cmx" ]
   excluded_files = _web_instance_host_deps_files_to_exclude
 }
 
diff --git a/fuchsia/runners/cast/cast_runner.cc b/fuchsia/runners/cast/cast_runner.cc
index c90534f..eddd7458 100644
--- a/fuchsia/runners/cast/cast_runner.cc
+++ b/fuchsia/runners/cast/cast_runner.cc
@@ -603,6 +603,7 @@
     std::vector<fuchsia::web::ContentDirectoryProvider> content_directories) {
   fuchsia::web::CreateContextParams params = GetCommonContextParams();
   EnsureSoftwareVideoDecodersAreDisabled(params.mutable_features());
+  *params.mutable_features() |= fuchsia::web::ContextFeatureFlags::NETWORK;
   params.set_remote_debugging_port(kEphemeralRemoteDebuggingPort);
   params.set_content_directories(std::move(content_directories));
   zx_status_t status = isolated_services_->ConnectClient(
diff --git a/gpu/command_buffer/service/external_vk_image_factory_unittest.cc b/gpu/command_buffer/service/external_vk_image_factory_unittest.cc
index 7644657..ce496f881 100644
--- a/gpu/command_buffer/service/external_vk_image_factory_unittest.cc
+++ b/gpu/command_buffer/service/external_vk_image_factory_unittest.cc
@@ -96,7 +96,9 @@
     std::vector<dawn_native::Adapter> adapters = dawn_instance_.GetAdapters();
     auto adapter_it = std::find_if(
         adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-          return adapter.GetBackendType() == dawn_native::BackendType::Vulkan;
+          wgpu::AdapterProperties properties;
+          adapter.GetProperties(&properties);
+          return properties.backendType == wgpu::BackendType::Vulkan;
         });
     ASSERT_NE(adapter_it, adapters.end());
 
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
index 186aa077..98aaecf 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_d3d_unittest.cc
@@ -601,7 +601,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::D3D12;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::D3D12;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -744,7 +746,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::D3D12;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::D3D12;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -834,7 +838,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::D3D12;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::D3D12;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -1104,7 +1110,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::D3D12;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::D3D12;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -1232,7 +1240,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::D3D12;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::D3D12;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc
index 42af1f4..73ed228 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_iosurface_unittest.cc
@@ -378,7 +378,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::Metal;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::Metal;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -527,7 +529,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::Metal;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::Metal;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
@@ -615,7 +619,9 @@
   std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
   auto adapter_it = std::find_if(
       adapters.begin(), adapters.end(), [](dawn_native::Adapter adapter) {
-        return adapter.GetBackendType() == dawn_native::BackendType::Metal;
+        wgpu::AdapterProperties properties;
+        adapter.GetProperties(&properties);
+        return properties.backendType == wgpu::BackendType::Metal;
       });
   ASSERT_NE(adapter_it, adapters.end());
 
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 39f2652..309aea2 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -124,41 +124,22 @@
   return true;
 }
 
-dawn_native::DeviceType PowerPreferenceToDawnDeviceType(
+WGPUAdapterType PowerPreferenceToDawnAdapterType(
     PowerPreference power_preference) {
   switch (power_preference) {
     case PowerPreference::kLowPower:
-      return dawn_native::DeviceType::IntegratedGPU;
+      return WGPUAdapterType_IntegratedGPU;
     case PowerPreference::kHighPerformance:
     // Currently for simplicity we always choose discrete GPU as the device
     // related to default power preference.
     case PowerPreference::kDefault:
-      return dawn_native::DeviceType::DiscreteGPU;
+      return WGPUAdapterType_DiscreteGPU;
     default:
       NOTREACHED();
-      return dawn_native::DeviceType::CPU;
+      return WGPUAdapterType_CPU;
   }
 }
 
-WGPUBackendType ToWGPUBackendType(dawn_native::BackendType type) {
-  switch (type) {
-    case dawn_native::BackendType::D3D12:
-      return WGPUBackendType_D3D12;
-    case dawn_native::BackendType::Metal:
-      return WGPUBackendType_Metal;
-    case dawn_native::BackendType::Null:
-      return WGPUBackendType_Null;
-    case dawn_native::BackendType::OpenGL:
-      return WGPUBackendType_OpenGL;
-    case dawn_native::BackendType::OpenGLES:
-      return WGPUBackendType_OpenGLES;
-    case dawn_native::BackendType::Vulkan:
-      return WGPUBackendType_Vulkan;
-  }
-  DCHECK(false);
-  return WGPUBackendType_Null;
-}
-
 }  // namespace
 
 class WebGPUDecoderImpl final : public WebGPUDecoder {
@@ -702,9 +683,9 @@
     // will be checked in PerformPollingWork to tick all the live devices and
     // remove all the dead ones.
     known_devices_.emplace_back(device_id, device_generation);
-    dawn_native::BackendType type =
-        dawn_adapters_[requested_adapter_index].GetBackendType();
-    device_backend_types_[device_id] = ToWGPUBackendType(type);
+    WGPUAdapterProperties adapterProperties = {};
+    dawn_adapters_[requested_adapter_index].GetProperties(&adapterProperties);
+    device_backend_types_[device_id] = adapterProperties.backendType;
   }
 
   size_t error_message_size =
@@ -785,12 +766,15 @@
     if (!adapter.SupportsExternalImages()) {
       continue;
     }
+
+    WGPUAdapterProperties adapterProperties = {};
+    adapter.GetProperties(&adapterProperties);
     if (force_webgpu_compat_) {
-      if (adapter.GetBackendType() == dawn_native::BackendType::OpenGLES) {
+      if (adapterProperties.backendType == WGPUBackendType_OpenGLES) {
         dawn_adapters_.push_back(adapter);
       }
-    } else if (adapter.GetBackendType() != dawn_native::BackendType::Null &&
-               adapter.GetBackendType() != dawn_native::BackendType::OpenGL) {
+    } else if (adapterProperties.backendType != WGPUBackendType_Null &&
+               adapterProperties.backendType != WGPUBackendType_OpenGL) {
       dawn_adapters_.push_back(adapter);
     }
   }
@@ -798,8 +782,8 @@
 
 int32_t WebGPUDecoderImpl::GetPreferredAdapterIndex(
     PowerPreference power_preference) const {
-  dawn_native::DeviceType preferred_device_type =
-      PowerPreferenceToDawnDeviceType(power_preference);
+  WGPUAdapterType preferred_adapter_type =
+      PowerPreferenceToDawnAdapterType(power_preference);
 
   int32_t discrete_gpu_adapter_index = -1;
   int32_t integrated_gpu_adapter_index = -1;
@@ -808,20 +792,23 @@
 
   for (int32_t i = 0; i < static_cast<int32_t>(dawn_adapters_.size()); ++i) {
     const dawn_native::Adapter& adapter = dawn_adapters_[i];
-    if (adapter.GetDeviceType() == preferred_device_type) {
+    WGPUAdapterProperties adapterProperties = {};
+    adapter.GetProperties(&adapterProperties);
+
+    if (adapterProperties.adapterType == preferred_adapter_type) {
       return i;
     }
-    switch (adapter.GetDeviceType()) {
-      case dawn_native::DeviceType::DiscreteGPU:
+    switch (adapterProperties.adapterType) {
+      case WGPUAdapterType_DiscreteGPU:
         discrete_gpu_adapter_index = i;
         break;
-      case dawn_native::DeviceType::IntegratedGPU:
+      case WGPUAdapterType_IntegratedGPU:
         integrated_gpu_adapter_index = i;
         break;
-      case dawn_native::DeviceType::CPU:
+      case WGPUAdapterType_CPU:
         cpu_adapter_index = i;
         break;
-      case dawn_native::DeviceType::Unknown:
+      case WGPUAdapterType_Unknown:
         unknown_adapter_index = i;
         break;
       default:
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 8308ef71..e2aa659 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-9a5018bd5e3caf8a167982fbee9f76b84ae10249
\ No newline at end of file
+786523b0ff341f2f9287b37bd79c30c02bc9030c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index f06a3010..e40919b 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-1fa33cc898ab9e8bcae2a9128b87230b8f75b217
\ No newline at end of file
+086d17aefd00ac6b9ee21d61a18b62e254a9a168
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index a656951..04ff3aa 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-ca4d51f57be8d2cb6cc6624e788216989dda39d0
\ No newline at end of file
+bd31d512bea6b670248290d0dcb497840450ec75
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index b96adb2..a5932c9 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e7744e98df62292f0eec6e3f0f0f63136743a2b4
\ No newline at end of file
+0eb663c371d8f9159529db8ac5bad5bd3286acd2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index bb71e94..37e9669 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-dd2df2537e156acd70309214255c081ccda27d1e
\ No newline at end of file
+4c9f1f3b80030dd201fff33ce2cb96fc985e7dc1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 47ca9e5f..b1bdf6f 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-7346a52db0c8ed2a8591fa73d47f02d0b7ecebe4
\ No newline at end of file
+6ef34a3bd66c042747011899be1bea1c12cde296
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 1960c477..2d4e1af 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-1578ff307224394df44bf6a493cffda4d79670cb
\ No newline at end of file
+9a6af5b7a3455fedf5392d8ee5dc9226ff928354
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index 66effa2..c08d019bb 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-def3920a3f24fbc613199c38a9fdea9f9dfa8204
\ No newline at end of file
+cd361266de1ce39e6c464ff08c889d9587f55ae6
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 7526b13..961bcdb2 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-2ff517b1cc46ca9f5a7546e1e61bf1ad892e056e
\ No newline at end of file
+f585092e6dd3f143f2f87b5a7f0cc78e8417ab58
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 4cd3b7a..2e79ca9 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-c0ae786ef5e982691eb1361bc8612bdffbdfe74b
\ No newline at end of file
+2756fb1b81084d1f543567747428873a83cc52f6
\ No newline at end of file
diff --git a/ios/web/common/features.mm b/ios/web/common/features.mm
index 39a7fb98..8ad21ec550 100644
--- a/ios/web/common/features.mm
+++ b/ios/web/common/features.mm
@@ -50,7 +50,7 @@
     "DisableNonHTMLScreenshotOnIOS15", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kIOSSharedHighlightingColorChange{
-    "IOSSharedHighlightingColorChange", base::FEATURE_DISABLED_BY_DEFAULT};
+    "IOSSharedHighlightingColorChange", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kCreatePendingItemForPostFormSubmission{
     "CreatePendingItemForPostFormSubmission",
diff --git a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
index 7785ff39..9a5d8405 100644
--- a/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
+++ b/ios/web/text_fragments/text_fragments_manager_impl_unittest.mm
@@ -114,9 +114,10 @@
                                           bool is_same_document,
                                           bool feature_color_change,
                                           bool add_web_frame) {
-    if (feature_color_change) {
+    if (!feature_color_change) {
       feature_list_.InitWithFeatures(
-          {features::kIOSSharedHighlightingColorChange}, {});
+          /*enabled_features=*/{},
+          /*disabled_features=*/{features::kIOSSharedHighlightingColorChange});
     }
     web_state_->SetHasOpener(has_opener);
     context_.SetHasUserGesture(has_user_gesture);
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.cc b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
index 5e2883d..1d1aaf1 100644
--- a/rlz/chromeos/lib/rlz_value_store_chromeos.cc
+++ b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
@@ -4,6 +4,8 @@
 
 #include "rlz/chromeos/lib/rlz_value_store_chromeos.h"
 
+#include <tuple>
+
 #include "base/base_paths.h"
 #include "base/bind.h"
 #include "base/containers/contains.h"
@@ -11,7 +13,6 @@
 #include "base/cxx17_backports.h"
 #include "base/files/file_util.h"
 #include "base/files/important_file_writer.h"
-#include "base/ignore_result.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/lazy_instance.h"
@@ -556,7 +557,7 @@
 
   if (g_lock_depth > 0) {
     // Other locks are still using store_, so don't free it yet.
-    ignore_result(store_.release());
+    std::ignore = store_.release();
     return;
   }
 
diff --git a/rlz/lib/recursive_cross_process_lock_posix.cc b/rlz/lib/recursive_cross_process_lock_posix.cc
index 0e23302..7b3199d9 100644
--- a/rlz/lib/recursive_cross_process_lock_posix.cc
+++ b/rlz/lib/recursive_cross_process_lock_posix.cc
@@ -11,8 +11,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <tuple>
+
 #include "base/files/file_path.h"
-#include "base/ignore_result.h"
 #include "base/logging.h"
 #include "base/posix/eintr_wrapper.h"
 
@@ -72,7 +73,7 @@
 
 void RecursiveCrossProcessLock::ReleaseLock() {
   if (file_lock_ != -1) {
-    ignore_result(HANDLE_EINTR(flock(file_lock_, LOCK_UN)));
+    std::ignore = HANDLE_EINTR(flock(file_lock_, LOCK_UN));
     close(file_lock_);
     file_lock_ = -1;
   }
diff --git a/rlz/mac/lib/rlz_value_store_mac.mm b/rlz/mac/lib/rlz_value_store_mac.mm
index effae66..1369bc8 100644
--- a/rlz/mac/lib/rlz_value_store_mac.mm
+++ b/rlz/mac/lib/rlz_value_store_mac.mm
@@ -4,9 +4,10 @@
 
 #include "rlz/mac/lib/rlz_value_store_mac.h"
 
+#include <tuple>
+
 #include "base/check.h"
 #include "base/files/file_path.h"
-#include "base/ignore_result.h"
 #include "base/mac/foundation_util.h"
 #include "base/notreached.h"
 #include "base/strings/sys_string_conversions.h"
@@ -320,7 +321,7 @@
 
   if (g_lock_depth > 0) {
     // Other locks are still using store_, don't free it yet.
-    ignore_result(store_.release());
+    std::ignore = store_.release();
     return;
   }
 
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index a80e415..3bd6201a 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1752,7 +1752,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R99-14446.0.0",
+        "cros_img": "atlas-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_ATLAS_LKGM",
         "resultdb": {
           "enable": true,
@@ -1812,7 +1812,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R99-14446.0.0",
+        "cros_img": "eve-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_EVE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1917,7 +1917,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1932,7 +1932,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_HANA_LKGM",
         "resultdb": {
           "enable": true,
@@ -1947,7 +1947,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1961,7 +1961,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "ozone_unittests_HANA_LKGM",
         "resultdb": {
           "enable": true,
@@ -1975,7 +1975,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "resultdb": {
           "enable": true,
@@ -1989,7 +1989,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "viz_unittests_HANA_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 8eedc46..67a0845e 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1135,7 +1135,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14446.0.0",
+        "cros_img": "octopus-release/R99-14447.0.0",
         "name": "lacros_fyi_tast_tests_OCTOPUS_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1179,7 +1179,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R99-14446.0.0",
+        "cros_img": "octopus-release/R99-14447.0.0",
         "name": "ozone_unittests_OCTOPUS_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1227,7 +1227,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_KEVIN_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && \"dep:lacros_unstable\")",
@@ -1238,7 +1238,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "lacros_all_tast_tests_HANA_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && \"dep:lacros_unstable\")",
@@ -1249,7 +1249,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "ozone_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1259,7 +1259,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "ozone_unittests_HANA_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1269,7 +1269,7 @@
       {
         "args": [],
         "cros_board": "kevin",
-        "cros_img": "kevin-release/R99-14446.0.0",
+        "cros_img": "kevin-release/R99-14447.0.0",
         "name": "viz_unittests_KEVIN_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1279,7 +1279,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R99-14446.0.0",
+        "cros_img": "hana-release/R99-14447.0.0",
         "name": "viz_unittests_HANA_LKGM",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 214ede6..9ce8df2 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -563,8 +563,8 @@
   'CROS_ATLAS_LKGM': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '99.0.4814.0',
-      'cros_img': 'atlas-release/R99-14446.0.0',
+      'cros_chrome_version': '99.0.4815.0',
+      'cros_img': 'atlas-release/R99-14447.0.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_LKGM',
@@ -599,8 +599,8 @@
   'CROS_EVE_LKGM': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '99.0.4814.0',
-      'cros_img': 'eve-release/R99-14446.0.0',
+      'cros_chrome_version': '99.0.4815.0',
+      'cros_img': 'eve-release/R99-14447.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_LKGM',
@@ -635,8 +635,8 @@
   'CROS_KEVIN_LKGM': {
     'skylab': {
       'cros_board': 'kevin',
-      'cros_chrome_version': '99.0.4814.0',
-      'cros_img': 'kevin-release/R99-14446.0.0',
+      'cros_chrome_version': '99.0.4815.0',
+      'cros_img': 'kevin-release/R99-14447.0.0',
     },
     'enabled': True,
     'identifier': 'KEVIN_LKGM',
@@ -644,8 +644,8 @@
   'CROS_HANA_LKGM': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '99.0.4814.0',
-      'cros_img': 'hana-release/R99-14446.0.0',
+      'cros_chrome_version': '99.0.4815.0',
+      'cros_img': 'hana-release/R99-14447.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_LKGM',
@@ -653,8 +653,8 @@
   'CROS_OCTOPUS_LKGM': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '99.0.4814.0',
-      'cros_img': 'octopus-release/R99-14446.0.0',
+      'cros_chrome_version': '99.0.4815.0',
+      'cros_img': 'octopus-release/R99-14447.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_LKGM',
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 65ac5d5d..494ff2f 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3411,6 +3411,8 @@
   kHTMLObjectElementFallback = 4102,
   kSecureContextIncorrectForWorker = 4103,
   kV8UDPSocket_Close_Method = 4104,
+  kHTMLInputElementSimulatedClick = 4105,
+
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc b/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc
index 6a3fb44..a69bb9e 100644
--- a/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc
+++ b/third_party/blink/renderer/core/css/affected_by_pseudo_test.cc
@@ -483,19 +483,19 @@
   UpdateAllLifecyclePhasesForTest();
   EXPECT_TRUE(
       GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas());
-  EXPECT_TRUE(GetElementById("div2")
-                  ->GetComputedStyle()
-                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(GetElementById("div2")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
   EXPECT_FALSE(
       GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas());
-  EXPECT_TRUE(GetElementById("div3")
-                  ->GetComputedStyle()
-                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(GetElementById("div3")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
   EXPECT_FALSE(
       GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas());
-  EXPECT_TRUE(GetElementById("div4")
-                  ->GetComputedStyle()
-                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(GetElementById("div4")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
   EXPECT_TRUE(
       GetElementById("div5")->GetComputedStyle()->AffectedByPseudoInHas());
   EXPECT_TRUE(GetElementById("div5")
@@ -547,7 +547,7 @@
   UpdateAllLifecyclePhasesForTest();
   unsigned element_count =
       GetStyleEngine().StyleForElementCount() - start_count;
-  ASSERT_EQ(1U, element_count);
+  ASSERT_EQ(0U, element_count);
   GetElementById("div3")->SetHovered(false);
   UpdateAllLifecyclePhasesForTest();
 
@@ -555,7 +555,7 @@
   GetElementById("div4")->SetHovered(true);
   UpdateAllLifecyclePhasesForTest();
   element_count = GetStyleEngine().StyleForElementCount() - start_count;
-  ASSERT_EQ(1U, element_count);
+  ASSERT_EQ(0U, element_count);
   GetElementById("div4")->SetHovered(false);
   UpdateAllLifecyclePhasesForTest();
 
@@ -563,6 +563,28 @@
   GetElementById("div4")->setAttribute(html_names::kClassAttr, "b");
   UpdateAllLifecyclePhasesForTest();
   element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(3U, element_count);
+
+  EXPECT_TRUE(
+      GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div2")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div3")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div4")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetElementById("div3")->setAttribute(html_names::kClassAttr, "b");
+  UpdateAllLifecyclePhasesForTest();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
   ASSERT_EQ(1U, element_count);
 
   EXPECT_TRUE(
@@ -582,6 +604,66 @@
                   ->AncestorsAffectedByHoverInHas());
 
   start_count = GetStyleEngine().StyleForElementCount();
+  GetElementById("div3")->SetHovered(true);
+  UpdateAllLifecyclePhasesForTest();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+  GetElementById("div3")->SetHovered(false);
+  UpdateAllLifecyclePhasesForTest();
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetElementById("div4")->SetHovered(true);
+  UpdateAllLifecyclePhasesForTest();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+  GetElementById("div4")->SetHovered(false);
+  UpdateAllLifecyclePhasesForTest();
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetElementById("div3")->setAttribute(html_names::kClassAttr, "");
+  UpdateAllLifecyclePhasesForTest();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(1U, element_count);
+
+  EXPECT_TRUE(
+      GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div2")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div3")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_TRUE(GetElementById("div4")
+                  ->GetComputedStyle()
+                  ->AncestorsAffectedByHoverInHas());
+
+  start_count = GetStyleEngine().StyleForElementCount();
+  GetElementById("div4")->setAttribute(html_names::kClassAttr, "");
+  UpdateAllLifecyclePhasesForTest();
+  element_count = GetStyleEngine().StyleForElementCount() - start_count;
+  ASSERT_EQ(3U, element_count);
+
+  EXPECT_TRUE(
+      GetElementById("div2")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_FALSE(GetElementById("div2")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div3")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_FALSE(GetElementById("div3")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
+  EXPECT_FALSE(
+      GetElementById("div4")->GetComputedStyle()->AffectedByPseudoInHas());
+  EXPECT_FALSE(GetElementById("div4")
+                   ->GetComputedStyle()
+                   ->AncestorsAffectedByHoverInHas());
+
+  start_count = GetStyleEngine().StyleForElementCount();
   GetElementById("div6")->SetHovered(true);
   UpdateAllLifecyclePhasesForTest();
   element_count = GetStyleEngine().StyleForElementCount() - start_count;
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index d79959d..4da6a5e 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -1058,6 +1058,11 @@
   data_.rare_data_->selector_list_ = std::move(selector_list);
 }
 
+void CSSSelector::SetContainsPseudoInsideHasPseudoClass() {
+  CreateRareData();
+  data_.rare_data_->bits_.contains_pseudo_inside_has_pseudo_class_ = true;
+}
+
 static bool ValidateSubSelector(const CSSSelector* selector) {
   switch (selector->Match()) {
     case CSSSelector::kTag:
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index 027a42e..4ecb317 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -354,6 +354,11 @@
   const Vector<AtomicString>* PartNames() const {
     return has_rare_data_ ? data_.rare_data_->part_names_.get() : nullptr;
   }
+  bool ContainsPseudoInsideHasPseudoClass() const {
+    return has_rare_data_ ? data_.rare_data_->bits_
+                                .contains_pseudo_inside_has_pseudo_class_
+                          : false;
+  }
 
 #ifndef NDEBUG
   void Show() const;
@@ -366,6 +371,7 @@
   void SetArgument(const AtomicString&);
   void SetSelectorList(std::unique_ptr<CSSSelectorList>);
   void SetPartNames(std::unique_ptr<Vector<AtomicString>>);
+  void SetContainsPseudoInsideHasPseudoClass();
 
   void SetNth(int a, int b);
   bool MatchNth(unsigned count) const;
@@ -479,6 +485,9 @@
       } nth_;
       AttributeMatchType
           attribute_match_;  // used for attribute selector (with value)
+
+      // Used for :has() with pseudos in its argument. e.g. :has(:hover)
+      bool contains_pseudo_inside_has_pseudo_class_;
     } bits_;
     QualifiedName attribute_;  // used for attribute selector
     AtomicString argument_;    // Used for :contains, :lang, :nth-*
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
index 362d4fa..737a646 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
@@ -58,6 +58,10 @@
   selector_->SetSelectorList(std::move(selector_list));
 }
 
+void CSSParserSelector::SetContainsPseudoInsideHasPseudoClass() {
+  selector_->SetContainsPseudoInsideHasPseudoClass();
+}
+
 void CSSParserSelector::AppendTagHistory(
     CSSSelector::RelationType relation,
     std::unique_ptr<CSSParserSelector> selector) {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_selector.h b/third_party/blink/renderer/core/css/parser/css_parser_selector.h
index fff17e1..2e244c65 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_selector.h
+++ b/third_party/blink/renderer/core/css/parser/css_parser_selector.h
@@ -79,6 +79,7 @@
       Vector<std::unique_ptr<CSSParserSelector>>& selector_vector);
   void SetSelectorList(std::unique_ptr<CSSSelectorList>);
   void SetAtomics(std::unique_ptr<CSSSelectorList>);
+  void SetContainsPseudoInsideHasPseudoClass();
 
   bool IsHostPseudoSelector() const;
 
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index 50b2b92..b26a0d8 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -784,6 +784,9 @@
   bool has_arguments = token.GetType() == kFunctionToken;
   selector->UpdatePseudoType(value, *context_, has_arguments, context_->Mode());
 
+  if (UNLIKELY(is_inside_has_argument_))
+    found_pseudo_in_has_argument_ = true;
+
   if (selector->Match() == CSSSelector::kPseudoElement) {
     switch (selector->GetPseudoType()) {
       case CSSSelector::kPseudoBefore:
@@ -877,6 +880,11 @@
       DisallowPseudoElementsScope scope(this);
       base::AutoReset<bool> resist_namespace(&resist_default_namespace_, true);
 
+      base::AutoReset<bool> is_inside_has_argument(&is_inside_has_argument_,
+                                                   true);
+      base::AutoReset<bool> found_pseudo_in_has_argument(
+          &found_pseudo_in_has_argument_, false);
+
       std::unique_ptr<CSSSelectorList> selector_list =
           std::make_unique<CSSSelectorList>();
       *selector_list = ConsumeRelativeSelectorList(block);
@@ -884,6 +892,8 @@
         return nullptr;
 
       selector->SetSelectorList(std::move(selector_list));
+      if (UNLIKELY(found_pseudo_in_has_argument_))
+        selector->SetContainsPseudoInsideHasPseudoClass();
       return selector;
     }
     case CSSSelector::kPseudoNot: {
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.h b/third_party/blink/renderer/core/css/parser/css_selector_parser.h
index b2047bd..b227d97 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.h
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.h
@@ -150,6 +150,11 @@
   // the default namespace is '*' while this flag is true.
   bool ignore_default_namespace_ = false;
 
+  // The 'found_pseudo_in_has_argument flag is true when we found any pseudo in
+  // ':has()' argument while parsing.
+  bool found_pseudo_in_has_argument_ = false;
+  bool is_inside_has_argument_ = false;
+
   class DisallowPseudoElementsScope {
     STACK_ALLOCATED();
 
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc
index 7b46258f..6687068 100644
--- a/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -664,6 +664,8 @@
   sub_context.scope = context.scope;
   // sub_context.is_inside_visited_link is false (by default) to disable
   // :visited matching when it is in the :has argument
+  sub_context.is_inside_has_pseudo_class = true;
+  sub_context.pseudo_has_in_rightmost_compound = context.in_rightmost_compound;
 
   DCHECK(context.selector->SelectorList());
   for (const CSSSelector* selector = context.selector->SelectorList()->First();
@@ -815,69 +817,6 @@
   return false;
 }
 
-namespace {
-
-struct HasPseudoClassArgumentInfo {
-  bool contains_pseudo = false;
-  bool contains_hover = false;
-  bool contains_active = false;
-  bool contains_focus = false;
-  bool contains_focus_visible = false;
-
-  explicit HasPseudoClassArgumentInfo(const CSSSelectorList* selector_list) {
-    DCHECK(selector_list);
-
-    for (const CSSSelector* relative_selector = selector_list->First();
-         relative_selector;
-         relative_selector = CSSSelectorList::Next(*relative_selector)) {
-      DCHECK(relative_selector);
-
-      for (const CSSSelector* simple = relative_selector;
-           simple &&
-           simple->GetPseudoType() != CSSSelector::kPseudoRelativeLeftmost;
-           simple = simple->TagHistory()) {
-        switch (simple->GetPseudoType()) {
-          case CSSSelector::kPseudoUnknown:
-            break;
-          case CSSSelector::kPseudoHover:
-            contains_pseudo = true;
-            contains_hover = true;
-            break;
-          case CSSSelector::kPseudoActive:
-            contains_pseudo = true;
-            contains_active = true;
-            break;
-          case CSSSelector::kPseudoFocus:
-          case CSSSelector::kPseudoFocusWithin:
-            contains_pseudo = true;
-            contains_focus = true;
-            break;
-          case CSSSelector::kPseudoFocusVisible:
-            contains_pseudo = true;
-            contains_focus_visible = true;
-            break;
-          default:
-            contains_pseudo = true;
-            break;
-        }
-      }
-    }
-  }
-
-  void SetDynamicRestyleFlagsForHas(ComputedStyle* style) {
-    if (contains_hover)
-      style->SetAncestorsAffectedByHoverInHas();
-    if (contains_active)
-      style->SetAncestorsAffectedByActiveInHas();
-    if (contains_focus)
-      style->SetAncestorsAffectedByFocusInHas();
-    if (contains_focus_visible)
-      style->SetAncestorsAffectedByFocusVisibleInHas();
-  }
-};
-
-}  // namespace
-
 bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
                                        MatchResult& result) const {
   Element& element = *context.element;
@@ -1073,19 +1012,38 @@
       }
       return element.IsDragged();
     case CSSSelector::kPseudoFocus:
-      if (mode_ == kResolvingStyle && !context.in_rightmost_compound)
-        element.SetChildrenOrSiblingsAffectedByFocus();
+      if (mode_ == kResolvingStyle) {
+        if (UNLIKELY(context.is_inside_has_pseudo_class)) {
+          if (context.pseudo_has_in_rightmost_compound)
+            element_style_->SetAncestorsAffectedByFocusInHas();
+        } else {
+          if (!context.in_rightmost_compound)
+            element.SetChildrenOrSiblingsAffectedByFocus();
+        }
+      }
       return MatchesFocusPseudoClass(element);
     case CSSSelector::kPseudoFocusVisible:
-      if (mode_ == kResolvingStyle && !context.in_rightmost_compound)
-        element.SetChildrenOrSiblingsAffectedByFocusVisible();
+      if (mode_ == kResolvingStyle) {
+        if (UNLIKELY(context.is_inside_has_pseudo_class)) {
+          if (context.pseudo_has_in_rightmost_compound)
+            element_style_->SetAncestorsAffectedByFocusVisibleInHas();
+        } else {
+          if (!context.in_rightmost_compound)
+            element.SetChildrenOrSiblingsAffectedByFocusVisible();
+        }
+      }
       return MatchesFocusVisiblePseudoClass(element);
     case CSSSelector::kPseudoFocusWithin:
       if (mode_ == kResolvingStyle) {
-        if (context.in_rightmost_compound)
-          element_style_->SetAffectedByFocusWithin();
-        else
-          element.SetChildrenOrSiblingsAffectedByFocusWithin();
+        if (UNLIKELY(context.is_inside_has_pseudo_class)) {
+          if (context.pseudo_has_in_rightmost_compound)
+            element_style_->SetAncestorsAffectedByFocusInHas();
+        } else {
+          if (context.in_rightmost_compound)
+            element_style_->SetAffectedByFocusWithin();
+          else
+            element.SetChildrenOrSiblingsAffectedByFocusWithin();
+        }
       }
       probe::ForcePseudoState(&element, CSSSelector::kPseudoFocusWithin,
                               &force_pseudo_state);
@@ -1094,10 +1052,15 @@
       return element.HasFocusWithin();
     case CSSSelector::kPseudoHover:
       if (mode_ == kResolvingStyle) {
-        if (context.in_rightmost_compound)
-          element_style_->SetAffectedByHover();
-        else
-          element.SetChildrenOrSiblingsAffectedByHover();
+        if (UNLIKELY(context.is_inside_has_pseudo_class)) {
+          if (context.pseudo_has_in_rightmost_compound)
+            element_style_->SetAncestorsAffectedByHoverInHas();
+        } else {
+          if (context.in_rightmost_compound)
+            element_style_->SetAffectedByHover();
+          else
+            element.SetChildrenOrSiblingsAffectedByHover();
+        }
       }
       if (!ShouldMatchHoverOrActive(context))
         return false;
@@ -1108,10 +1071,15 @@
       return element.IsHovered();
     case CSSSelector::kPseudoActive:
       if (mode_ == kResolvingStyle) {
-        if (context.in_rightmost_compound)
-          element_style_->SetAffectedByActive();
-        else
-          element.SetChildrenOrSiblingsAffectedByActive();
+        if (UNLIKELY(context.is_inside_has_pseudo_class)) {
+          if (context.pseudo_has_in_rightmost_compound)
+            element_style_->SetAncestorsAffectedByActiveInHas();
+        } else {
+          if (context.in_rightmost_compound)
+            element_style_->SetAffectedByActive();
+          else
+            element.SetChildrenOrSiblingsAffectedByActive();
+        }
       }
       if (!ShouldMatchHoverOrActive(context))
         return false;
@@ -1321,14 +1289,8 @@
           // ':has()' selector.
           element_style_->SetAffectedByHas();
           element_style_->SetAncestorsAffectedByHas();
-
-          // TODO(blee@igalia.com) Move the logic in HasPseudoClassArgumentInfo
-          // to HasArgumentMatchContext
-          HasPseudoClassArgumentInfo argument(selector.SelectorList());
-          if (argument.contains_pseudo)
+          if (selector.ContainsPseudoInsideHasPseudoClass())
             element_style_->SetAffectedByPseudoInHas();
-          if (context.in_rightmost_compound)
-            argument.SetDynamicRestyleFlagsForHas(element_style_);
         }
         // TODO(blee@igalia.com) non-terminal ':has() is not supported yet
       }
diff --git a/third_party/blink/renderer/core/css/selector_checker.h b/third_party/blink/renderer/core/css/selector_checker.h
index 1b9deca..a42ffa2 100644
--- a/third_party/blink/renderer/core/css/selector_checker.h
+++ b/third_party/blink/renderer/core/css/selector_checker.h
@@ -108,20 +108,27 @@
     // Initial selector constructor
     explicit SelectorCheckingContext(Element* element) : element(element) {}
 
+    // Group fields by type to avoid perf test regression.
+    // https://crrev.com/c/3362008
     const CSSSelector* selector = nullptr;
+    const ContainerNode* scope = nullptr;
+
     Element* element = nullptr;
     Element* previous_element = nullptr;
-    const ContainerNode* scope = nullptr;
+    Element* vtt_originating_element = nullptr;
+    ContainerNode* relative_leftmost_element = nullptr;
+
     PseudoId pseudo_id = kPseudoIdNone;
+
     bool is_sub_selector = false;
     bool in_rightmost_compound = true;
     bool has_scrollbar_pseudo = false;
     bool has_selection_pseudo = false;
     bool treat_shadow_host_as_normal_scope = false;
-    Element* vtt_originating_element = nullptr;
     bool in_nested_complex_selector = false;
     bool is_inside_visited_link = false;
-    const ContainerNode* relative_leftmost_element = nullptr;
+    bool pseudo_has_in_rightmost_compound = true;
+    bool is_inside_has_pseudo_class = false;
   };
 
   struct MatchResult {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index b2d2ba55..2fb295d 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -394,6 +394,22 @@
   return false;
 }
 
+bool NeedsLegacyLayoutForEntireDocument(Document& document) {
+  // Fall back to legacy layout for frameset documents. The frameset itself (and
+  // the frames) can only create legacy layout objects anyway (no NG counterpart
+  // for them yet). However, the layout object for the HTML root element would
+  // be an NG one. If we'd then print the document, we'd fall back to legacy
+  // layout (because of the above check), which would re-attach all layout
+  // objects, which would cause the frameset to lose state of some sort, leaving
+  // everything blank when printed.
+  if (document.IsFrameSet()) {
+    UseCounter::Count(document, WebFeature::kLegacyLayoutByFrameSet);
+    return true;
+  }
+
+  return false;
+}
+
 bool CalculateStyleShouldForceLegacyLayout(const Element& element,
                                            const ComputedStyle& style) {
   Document& document = element.GetDocument();
@@ -426,17 +442,8 @@
     return true;
   }
 
-  // Fall back to legacy layout for frameset documents. The frameset itself (and
-  // the frames) can only create legacy layout objects anyway (no NG counterpart
-  // for them yet). However, the layout object for the HTML root element would
-  // be an NG one. If we'd then print the document, we'd fall back to legacy
-  // layout (because of the above check), which would re-attach all layout
-  // objects, which would cause the frameset to lose state of some sort, leaving
-  // everything blank when printed.
-  if (document.IsFrameSet()) {
-    UseCounter::Count(document, WebFeature::kLegacyLayoutByFrameSet);
+  if (NeedsLegacyLayoutForEntireDocument(document))
     return true;
-  }
 
   if (!RuntimeEnabledFeatures::LayoutNGTextCombineEnabled() &&
       style.HasTextCombine() && !style.IsHorizontalWritingMode()) {
@@ -3834,6 +3841,11 @@
                        : nullptr;
 }
 
+void Element::ResetForceLegacyLayoutForPrinting() {
+  SetShouldForceLegacyLayoutForChild(
+      NeedsLegacyLayoutForEntireDocument(GetDocument()));
+}
+
 void Element::SetCustomElementDefinition(CustomElementDefinition* definition) {
   DCHECK(definition);
   DCHECK(!GetCustomElementDefinition());
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 9046654..62eeca6 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -890,6 +890,8 @@
     return StyleShouldForceLegacyLayout() || ShouldForceLegacyLayoutForChild();
   }
 
+  void ResetForceLegacyLayoutForPrinting();
+
   virtual void BuildPendingResource() {}
 
   void SetCustomElementDefinition(CustomElementDefinition*);
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index a505cc44..56c9b35 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1072,6 +1072,12 @@
                                       : Document::kFinishingPrinting);
   View()->AdjustMediaTypeForPrinting(printing);
 
+  if (!printing) {
+    // Don't get stuck with the legacy engine when no longer printing.
+    if (Element* root = GetDocument()->documentElement())
+      root->ResetForceLegacyLayoutForPrinting();
+  }
+
   if (TextAutosizer* text_autosizer = GetDocument()->GetTextAutosizer())
     text_autosizer->UpdatePageInfo();
 
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index f3b4db9..2d7b5c6 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1127,6 +1127,10 @@
 
 void HTMLElement::click() {
   DispatchSimulatedClick(nullptr, SimulatedClickCreationScope::kFromScript);
+  if (IsA<HTMLInputElement>(this)) {
+    UseCounter::Count(GetDocument(),
+                      WebFeature::kHTMLInputElementSimulatedClick);
+  }
 }
 
 void HTMLElement::AccessKeyAction(SimulatedClickCreationScope creation_scope) {
diff --git a/third_party/blink/renderer/core/paint/block_painter_test.cc b/third_party/blink/renderer/core/paint/block_painter_test.cc
index 555364337..f7df2f8 100644
--- a/third_party/blink/renderer/core/paint/block_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -277,6 +277,8 @@
     <div id='wheelevent'></div>
   )HTML");
 
+  auto* wheelevent_element = GetElementById("wheelevent");
+  auto* wheelevent = wheelevent_element->GetLayoutObject();
   EXPECT_THAT(ContentDisplayItems(),
               ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM));
 
@@ -288,13 +290,15 @@
   EXPECT_THAT(ContentDisplayItems(),
               ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM));
 
+  PaintChunk::Id hit_test_chunk_id(wheelevent->EnclosingLayer()->Id(),
+                                   kNonScrollingBackgroundChunkType);
   HitTestData hit_test_data;
   hit_test_data.wheel_event_rects = {{gfx::Rect(0, 0, 100, 100)}};
 
   EXPECT_THAT(ContentPaintChunks(),
               ElementsAre(VIEW_SCROLLING_BACKGROUND_CHUNK(1, &hit_test_data)));
 
-  GetElementById("wheelevent")->RemoveAllEventListeners();
+  wheelevent_element->RemoveAllEventListeners();
   UpdateAllLifecyclePhasesForTest();
   EXPECT_THAT(ContentDisplayItems(),
               ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM));
@@ -525,7 +529,7 @@
               ElementsAre(VIEW_SCROLLING_BACKGROUND_DISPLAY_ITEM));
 
   PaintChunk::Id hit_test_chunk_id(touchaction->EnclosingLayer()->Id(),
-                                   kHitTestChunkType);
+                                   kNonScrollingBackgroundChunkType);
   HitTestData hit_test_data;
   hit_test_data.touch_action_rects = {{gfx::Rect(0, 0, 100, 100)}};
 
@@ -666,7 +670,8 @@
       ElementsAre(
           VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
           IsPaintChunk(
-              1, 1, PaintChunk::Id(scroller->Id(), kBackgroundChunkType),
+              1, 1,
+              PaintChunk::Id(scroller->Layer()->Id(), DisplayItem::kLayerChunk),
               scroller->FirstFragment().LocalBorderBoxProperties(),
               &scroller_touch_action_hit_test_data, gfx::Rect(0, 0, 100, 100)),
           IsPaintChunk(
diff --git a/third_party/blink/renderer/core/paint/box_painter_test.cc b/third_party/blink/renderer/core/paint/box_painter_test.cc
index 404fa8b..5cbfe2b 100644
--- a/third_party/blink/renderer/core/paint/box_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_test.cc
@@ -209,9 +209,10 @@
       paint_chunks,
       ElementsAre(
           VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
-          IsPaintChunk(1, 2,
-                       PaintChunk::Id(container.Id(), kBackgroundChunkType),
-                       container.FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(
+              1, 2,
+              PaintChunk::Id(container.Layer()->Id(), DisplayItem::kLayerChunk),
+              container.FirstFragment().LocalBorderBoxProperties()),
           IsPaintChunk(
               2, 2, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest),
               container.FirstFragment().LocalBorderBoxProperties(),
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
index 9206e50..711d533 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
@@ -81,9 +81,10 @@
       ContentPaintChunks(),
       ElementsAre(
           VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
-          IsPaintChunk(1, 1,
-                       PaintChunk::Id(scroller.Id(), kBackgroundChunkType),
-                       scroller.FirstFragment().LocalBorderBoxProperties()),
+          IsPaintChunk(
+              1, 1,
+              PaintChunk::Id(scroller.Layer()->Id(), DisplayItem::kLayerChunk),
+              scroller.FirstFragment().LocalBorderBoxProperties()),
           IsPaintChunk(
               1, 1,
               PaintChunk::Id(root_fragment.Id(), DisplayItem::kScrollHitTest),
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
index 7e71d18..9d9a466 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc
@@ -16,7 +16,6 @@
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 
-using testing::_;
 using testing::ElementsAre;
 
 namespace blink {
@@ -320,10 +319,11 @@
       ContentPaintChunks(),
       ElementsAre(
           VIEW_SCROLLING_BACKGROUND_CHUNK_COMMON,
-          IsPaintChunk(1, 2,
-                       PaintChunk::Id(container.Id(), kBackgroundChunkType),
-                       container.FirstFragment().LocalBorderBoxProperties(),
-                       nullptr, gfx::Rect(0, 0, 200, 200)),
+          IsPaintChunk(
+              1, 2,
+              PaintChunk::Id(container.Layer()->Id(), DisplayItem::kLayerChunk),
+              container.FirstFragment().LocalBorderBoxProperties(), nullptr,
+              gfx::Rect(0, 0, 200, 200)),
           IsPaintChunk(
               2, 2, PaintChunk::Id(container.Id(), DisplayItem::kScrollHitTest),
               container.FirstFragment().LocalBorderBoxProperties(),
@@ -331,9 +331,7 @@
           IsPaintChunk(
               2, 4,
               PaintChunk::Id(container.Id(), kScrollingBackgroundChunkType),
-              container.FirstFragment().ContentsProperties()),
-          // Hit test chunk for forceDocumentScroll.
-          IsPaintChunk(4, 4)));
+              container.FirstFragment().ContentsProperties())));
 }
 
 TEST_P(PaintControllerPaintTest, NonStackingScrollHitTestOrder) {
diff --git a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
index 81e9dec..fbf986d 100644
--- a/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
+++ b/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -124,9 +124,7 @@
 };
 
 // Shorter names for frequently used display item types in core/ tests.
-const DisplayItem::Type kBackgroundChunkType =
-    DisplayItem::PaintPhaseToDrawingType(PaintPhase::kBlockBackground);
-const DisplayItem::Type kHitTestChunkType =
+const DisplayItem::Type kNonScrollingBackgroundChunkType =
     DisplayItem::PaintPhaseToDrawingType(PaintPhase::kSelfBlockBackgroundOnly);
 const DisplayItem::Type kScrollingBackgroundChunkType =
     DisplayItem::PaintPhaseToClipType(PaintPhase::kSelfBlockBackgroundOnly);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 4d44b67..c53fc1b 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -2364,7 +2364,8 @@
 
 bool PaintLayer::ShouldBeSelfPaintingLayer() const {
   return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
-         (scrollable_area_ && scrollable_area_->HasOverlayOverflowControls());
+         (scrollable_area_ && scrollable_area_->HasOverlayOverflowControls()) ||
+         ScrollsOverflow();
 }
 
 void PaintLayer::UpdateSelfPaintingLayer() {
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index e622249..f2740ea 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -393,8 +393,12 @@
     fragment_id = 0;
 
   if (pre_paint_info.is_first_for_node) {
-    if (!allow_update)
+    if (allow_update) {
+      if (fragment_data->FragmentID() < fragment_id)
+        fragment_data->ClearNextFragment();
+    } else {
       DCHECK_EQ(fragment_data->FragmentID(), fragment_id);
+    }
   } else {
     FragmentData* last_fragment = nullptr;
     do {
diff --git a/third_party/blink/renderer/core/probe/async_task_context.h b/third_party/blink/renderer/core/probe/async_task_context.h
index 8a791014..372cd16 100644
--- a/third_party/blink/renderer/core/probe/async_task_context.h
+++ b/third_party/blink/renderer/core/probe/async_task_context.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_ASYNC_TASK_CONTEXT_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_ASYNC_TASK_CONTEXT_H_
 
-#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
 
 namespace v8 {
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
index 05b7bbab..f8fbe5ae 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_advertising_event.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_ADVERTISING_EVENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_ADVERTISING_EVENT_H_
 
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 
diff --git a/third_party/blink/renderer/modules/device_orientation/device_orientation_event.h b/third_party/blink/renderer/modules/device_orientation/device_orientation_event.h
index 54087156..e5c4b435 100644
--- a/third_party/blink/renderer/modules/device_orientation/device_orientation_event.h
+++ b/third_party/blink/renderer/modules/device_orientation/device_orientation_event.h
@@ -26,6 +26,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_H_
 
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/modules/event_modules.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
diff --git a/third_party/blink/renderer/modules/direct_sockets/OWNERS b/third_party/blink/renderer/modules/direct_sockets/OWNERS
index 5a733a4..ef9d017 100644
--- a/third_party/blink/renderer/modules/direct_sockets/OWNERS
+++ b/third_party/blink/renderer/modules/direct_sockets/OWNERS
@@ -1,3 +1,4 @@
+bartfab@chromium.org
 ericwilligers@chromium.org
 glenrob@chromium.org
 mgiuca@chromium.org
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc
index 3d08a8a..420bc60 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.cc
@@ -284,6 +284,11 @@
   return stopped_;
 }
 
+bool FakeRtpTransceiver::stopping() const {
+  NOTIMPLEMENTED();
+  return false;
+}
+
 webrtc::RtpTransceiverDirection FakeRtpTransceiver::direction() const {
   return direction_;
 }
@@ -298,10 +303,6 @@
   return current_direction_;
 }
 
-void FakeRtpTransceiver::Stop() {
-  NOTIMPLEMENTED();
-}
-
 void FakeRtpTransceiver::SetTransport(
     rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport) {
   sender_->SetTransport(transport);
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h
index f78a8fae..0fbb9a3e 100644
--- a/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h
+++ b/third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h
@@ -105,13 +105,32 @@
   rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override;
   rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override;
   bool stopped() const override;
+  bool stopping() const override;
   webrtc::RtpTransceiverDirection direction() const override;
   void SetDirection(webrtc::RtpTransceiverDirection new_direction) override;
   absl::optional<webrtc::RtpTransceiverDirection> current_direction()
       const override;
-  void Stop() override;
   void SetTransport(
       rtc::scoped_refptr<webrtc::DtlsTransportInterface> transport);
+  webrtc::RTCError SetCodecPreferences(
+      rtc::ArrayView<webrtc::RtpCodecCapability>) override {
+    RTC_DCHECK_NOTREACHED() << "Not implemented";
+    return {};
+  }
+  std::vector<webrtc::RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
+      const override {
+    return {};
+  }
+  webrtc::RTCError SetOfferedRtpHeaderExtensions(
+      rtc::ArrayView<const webrtc::RtpHeaderExtensionCapability>
+          header_extensions_to_offer) override {
+    return webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
+  }
+
+  std::vector<webrtc::RtpHeaderExtensionCapability> HeaderExtensionsNegotiated()
+      const override {
+    return {};
+  }
 
  private:
   cricket::MediaType media_type_;
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory_test.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory_test.cc
index 82f3854..f88e60d 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory_test.cc
@@ -61,9 +61,11 @@
             /*force_encoded_video_insertable_streams=*/false);
     MediaConstraints constraints;
     DummyExceptionStateForTesting exception_state;
-    handler->InitializeForTest(
-        webrtc::PeerConnectionInterface::RTCConfiguration(), constraints,
-        /*peer_connection_tracker=*/nullptr, exception_state);
+    webrtc::PeerConnectionInterface::RTCConfiguration config;
+    config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
+    handler->InitializeForTest(config, constraints,
+                               /*peer_connection_tracker=*/nullptr,
+                               exception_state);
     return handler;
   }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
index d520255a..ac78d92c2 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker_test.cc
@@ -148,6 +148,12 @@
   MockRTCPeerConnectionHandlerClient client_;
 };
 
+webrtc::PeerConnectionInterface::RTCConfiguration DefaultConfig() {
+  webrtc::PeerConnectionInterface::RTCConfiguration config;
+  config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
+  return config;
+}
+
 }  // namespace
 
 class PeerConnectionTrackerTest : public ::testing::Test {
@@ -163,10 +169,8 @@
   void CreateAndRegisterPeerConnectionHandler() {
     mock_handler_ = std::make_unique<MockPeerConnectionHandler>();
     EXPECT_CALL(*mock_host_, AddPeerConnection(_));
-    tracker_->RegisterPeerConnection(
-        mock_handler_.get(),
-        webrtc::PeerConnectionInterface::RTCConfiguration(), MediaConstraints(),
-        nullptr);
+    tracker_->RegisterPeerConnection(mock_handler_.get(), DefaultConfig(),
+                                     MediaConstraints(), nullptr);
     base::RunLoop().RunUntilIdle();
   }
 
@@ -249,9 +253,8 @@
   // Nothing is reported by default.
   EXPECT_CALL(handler0, OnThermalStateChange(_)).Times(0);
   EXPECT_CALL(*mock_host_, AddPeerConnection(_)).Times(1);
-  tracker_->RegisterPeerConnection(
-      &handler0, webrtc::PeerConnectionInterface::RTCConfiguration(),
-      MediaConstraints(), nullptr);
+  tracker_->RegisterPeerConnection(&handler0, DefaultConfig(),
+                                   MediaConstraints(), nullptr);
   base::RunLoop().RunUntilIdle();
 
   // Report a known thermal state.
@@ -265,9 +268,8 @@
               OnThermalStateChange(mojom::blink::DeviceThermalState::kNominal))
       .Times(1);
   EXPECT_CALL(*mock_host_, AddPeerConnection(_)).Times(1);
-  tracker_->RegisterPeerConnection(
-      &handler1, webrtc::PeerConnectionInterface::RTCConfiguration(),
-      MediaConstraints(), nullptr);
+  tracker_->RegisterPeerConnection(&handler1, DefaultConfig(),
+                                   MediaConstraints(), nullptr);
   base::RunLoop().RunUntilIdle();
 
   // Report the unknown thermal state.
@@ -282,9 +284,8 @@
   // Handlers registered late get no event.
   EXPECT_CALL(handler2, OnThermalStateChange(_)).Times(0);
   EXPECT_CALL(*mock_host_, AddPeerConnection(_)).Times(1);
-  tracker_->RegisterPeerConnection(
-      &handler2, webrtc::PeerConnectionInterface::RTCConfiguration(),
-      MediaConstraints(), nullptr);
+  tracker_->RegisterPeerConnection(&handler2, DefaultConfig(),
+                                   MediaConstraints(), nullptr);
   base::RunLoop().RunUntilIdle();
 }
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.h
index daa796d..4ad913c 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.h
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_error_event.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_PEER_CONNECTION_ICE_ERROR_EVENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_PEER_CONNECTION_ICE_ERROR_EVENT_H_
 
+#include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/renderer/modules/event_modules.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index d986311c..7c0e2627 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -1570,14 +1570,13 @@
 crbug.com/626703 external/wpt/css/CSS2/borders/border-right-color-applies-to-014.xht [ Failure ]
 crbug.com/626703 external/wpt/css/CSS2/borders/border-right-width-applies-to-014.xht [ Failure ]
 
-# Failures when enabling CompositeAfterPaint
+# Failures when enabling CompositeAfter
 crbug.com/591099 fast/block/float/float-change-composited-scrolling.html [ Failure ]
 crbug.com/591099 svg/dom/viewspec-aspectparams.html [ Failure ]
 crbug.com/591099 svg/dom/viewspec-transformparams.html [ Failure ]
 crbug.com/591099 svg/dom/viewspec-viewboxparams.html [ Failure ]
 crbug.com/591099 svg/dom/viewspec-viewtargetparams.html [ Failure ]
 crbug.com/591099 svg/dom/viewspec-zoomandpanparams.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-multicol/multicol-scroll-content.html [ Failure ]
 
 # Fails with ForceSynchronousHTMLParsing enabled, might be a fluke:
 crbug.com/1254921 svg/as-image/image-respects-deviceScaleFactor.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 91ad573..7b119fd 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4637,7 +4637,6 @@
 crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-000.html [ Failure ]
 crbug.com/990240 external/wpt/css/css-multicol/multicol-breaking-nobackground-001.html [ Failure ]
 crbug.com/481431 external/wpt/css/css-multicol/multicol-breaking-nobackground-004.html [ Failure ]
-crbug.com/829028 external/wpt/css/css-multicol/multicol-fill-balance-017.html [ Failure ]
 crbug.com/829028 [ Mac ] external/wpt/css/css-multicol/multicol-list-item-004.html [ Failure ]
 crbug.com/829028 [ Mac ] external/wpt/css/css-multicol/multicol-list-item-005.html [ Failure ]
 crbug.com/792435 external/wpt/css/css-multicol/multicol-rule-004.xht [ Failure ]
@@ -6522,9 +6521,6 @@
 crbug.com/1157861 http/tests/devtools/extensions/extensions-resources.js [ Failure Pass ]
 crbug.com/1157861 http/tests/devtools/console/paintworklet-console-selector.js [ Failure Pass ]
 
-# Temporarily disabled to land crrev.com/c/3358537
-crbug.com/1282837 http/tests/devtools/console/console-format-style.js [ Skip ]
-
 # Wpt importer Sheriff 2020-12-11
 crbug.com/626703 [ Linux ] wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.html [ Failure Pass ]
 
@@ -7918,7 +7914,6 @@
 # Sheriff 2022-01-07
 crbug.com/1285348 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/hidpi/canvas-transform.https.html [ Failure Pass ]
 crbug.com/1285350 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/parse-input-arguments-011.https.html [ Failure Pass ]
-crbug.com/1285373 [ Linux ] fast/multicol/dynamic/insert-block-before-spanner-before-content.html [ Crash Failure Pass ]
 crbug.com/1285426 [ Mac ] virtual/controls-refresh-hc/fast/forms/color-scheme/week-picker/week-picker-appearance-highlight-es.html [ Crash Pass ]
 crbug.com/1285438 fast/layers/clip-rects-transformed.html [ Failure Pass ]
 crbug.com/1285431 [ Mac ] virtual/backface-visibility-interop/compositing/overflow/transform-should-update-absolute-clip-rects.html [ Crash Failure Pass ]
diff --git a/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow-expected.html b/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow-expected.html
index 208711f..d8391ef 100644
--- a/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow-expected.html
+++ b/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow-expected.html
@@ -7,7 +7,6 @@
   padding: 2px;
   writing-mode: vertical-rl;
   overflow: scroll;
-  position: relative;
 }
 .container .container {
   width: 150px;
diff --git a/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow.html b/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow.html
index 26a2f07d..752e842 100644
--- a/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow.html
+++ b/third_party/blink/web_tests/compositing/overflow/nested-vertical-rl-overflow.html
@@ -7,7 +7,6 @@
   padding: 2px;
   writing-mode: vertical-rl;
   overflow: scroll;
-  position: relative;
 }
 .container .container {
   width: 150px;
diff --git a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index 64a64415..f67e80a 100644
--- a/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -14,13 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [10, 97],
       "bounds": [104, 257],
@@ -33,6 +26,13 @@
       "transform": 1
     },
     {
+      "name": "LayoutNGBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
+      "position": [2, 6],
+      "bounds": [85, 136],
+      "contentsOpaqueForText": true,
+      "transform": 2
+    },
+    {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [35, 10],
       "bounds": [199, 105],
@@ -111,13 +111,6 @@
       "transform": 7
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 8
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [2, 87],
       "bounds": [100, 15],
@@ -131,6 +124,13 @@
       "transform": 7
     },
     {
+      "name": "LayoutNGBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
+      "position": [2, 6],
+      "bounds": [85, 136],
+      "contentsOpaqueForText": true,
+      "transform": 8
+    },
+    {
       "name": "LayoutNGBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [395, 75],
       "bounds": [80, 40],
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 61737ea8..2f3aef32 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
@@ -37371,6 +37371,19 @@
         {}
        ]
       ],
+      "overflow-scroll-float-paint-order.html": [
+       "79ab770eec3bfb864c57c2a05a648114cff8ce45",
+       [
+        null,
+        [
+         [
+          "/css/CSS2/floats/overflow-scroll-float-paint-order-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "overhanging-float-paint-order.html": [
        "6075d0a2c9812e7631bd8235adea7ea7ebbea800",
        [
@@ -51378,6 +51391,19 @@
         {}
        ]
       ],
+      "overflow-scroll-paint-order.html": [
+       "a0813ae4696ca20e204e62ae90bf9d562fa20091",
+       [
+        null,
+        [
+         [
+          "/css/CSS2/normal-flow/overflow-scroll-paint-order-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "replaced-intrinsic-001.xht": [
        "7cbb65bf09022bb3c87b417ae6a93ba3a424b8dc",
        [
@@ -235316,6 +235342,10 @@
        "68139cdbe2d7c998b6d948f5ecca0ed7ce367694",
        []
       ],
+      "overflow-scroll-float-paint-order-ref.html": [
+       "0fb53d4ecd3cd77e6588be0b271a2ee47950bd29",
+       []
+      ],
       "overhanging-float-paint-order-ref.html": [
        "608e009ff5c361192238b455876ef7d4bdd84f7d",
        []
@@ -236802,6 +236832,10 @@
        "e98059a69f63befe25d90eb8fd7f328870633150",
        []
       ],
+      "overflow-scroll-paint-order-ref.html": [
+       "4ea2b5daa64f0d034fb23c28ad02c4a27f8c6be5",
+       []
+      ],
       "replaced-intrinsic-001-ref.xht": [
        "d48d43e00a4c8c03b2ce948e5cadcf8c4119a85d",
        []
@@ -269800,11 +269834,7 @@
        "1e7eed04818a06e4723fb8d1f2df2e258ab5df8b",
        []
       ]
-     },
-     "transition-property-002-expected.txt": [
-      "cdbe8a11e6f3d85f4276ab4840c6c443fbed2be8",
-      []
-     ]
+     }
     },
     "css-typed-om": {
      "CSSMatrixComponent-DOMMatrix-mutable-expected.txt": [
@@ -376841,7 +376871,7 @@
       ]
      ],
      "transition-property-002.html": [
-      "99196b6d1d4ec86be77930d578602110b6a7deb6",
+      "2a46b3e284dc45c0dd06b7b65aa424d2416f8a68",
       [
        null,
        {}
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order-ref.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order-ref.html
deleted file mode 100644
index 0fb53d4e..0000000
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order-ref.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background: green">
-  <div style="width: 50px; height: 50px; background: magenta"></div>
-</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order.html
deleted file mode 100644
index 79ab770..0000000
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/overflow-scroll-float-paint-order.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<title>Overflow:scroll floating paint order</title>
-<link rel="help" href="https://www.w3.org/TR/CSS2/zindex.html">
-<link rel="match" href="overflow-scroll-float-paint-order-ref.html">
-<style>
-  #scroller {
-    float: left;
-    background: red;
-    padding: 20px;
-    box-sizing: border-box;
-    width: 100px;
-    height: 100px;
-    overflow: scroll;
-  }
-  #negative-margin {
-    float: left;
-    width: 100px;
-    height: 100px;
-    background: green;
-    margin-left: -100px;
-  }
-  #foreground1 {
-    display: inline-block;
-    width: 50px;
-    height: 50px;
-    background: blue;
-  }
-  #foreground2 {
-    display: inline-block;
-    width: 50px;
-    height: 50px;
-    background: magenta;
-  }
-</style>
-<!-- The paint order should be:
-  scroller background (invisible)
-  scroller child background (invisible)
-  foreground1 (invisible)
-  negative-margin background (visible)
-  foreground2 (visible)
--->
-<div id="scroller">
-  <div style="height: 200px; background: yellow">
-    <div id="foreground1"></div>
-  </div>
-</div>
-<div id="negative-margin">
-  <div id="foreground2"></div>
-</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order-ref.html b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order-ref.html
deleted file mode 100644
index 4ea2b5da..0000000
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order-ref.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE html>
-<div style="width: 100px; height: 100px; background: green; position: relative">
-  <div style="width: 50px; height: 50px; background: blue; position: absolute; top: 20px; left: 20px"></div>
-  <div style="width: 50px; height: 50px; background: magenta; position: absolute; top: 0; left: 0"></div>
-</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order.html b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order.html
deleted file mode 100644
index a0813ae4..0000000
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/overflow-scroll-paint-order.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<title>Overflow:scroll paint order</title>
-<link rel="help" href="https://www.w3.org/TR/CSS2/zindex.html">
-<link rel="match" href="overflow-scroll-paint-order-ref.html">
-<style>
-  #scroller {
-    background: red;
-    padding: 20px;
-    box-sizing: border-box;
-    width: 100px;
-    height: 100px;
-    overflow: scroll;
-  }
-  #negative-margin {
-    width: 100px;
-    height: 100px;
-    background: green;
-    margin-top: -100px;
-  }
-  #foreground1 {
-    display: inline-block;
-    width: 50px;
-    height: 50px;
-    background: blue;
-  }
-  #foreground2 {
-    display: inline-block;
-    width: 50px;
-    height: 50px;
-    background: magenta;
-  }
-</style>
-<!-- The paint order should be:
-  scroller background (invisible)
-  scroller child background (invisible)
-  negative-margin background (visible)
-  foreground1 (visible)
-  foreground2 (visible)
--->
-<div id="scroller">
-  <div style="height: 200px; background: yellow">
-    <div id="foreground1"></div>
-  </div>
-</div>
-<div id="negative-margin">
-  <div id="foreground2"></div>
-</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-018.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-018.html
new file mode 100644
index 0000000..692071c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-fill-balance-018.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1285795">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div style="columns:4; column-gap:0;">
+    <div id="elm" style="display:none; height:200px; background:green;"></div>
+    <div style="height:200px; background:green;"></div>
+  </div>
+</div>
+<script>
+  requestAnimationFrame(()=> {
+    requestAnimationFrame(()=> {
+      elm.style.display = 'block';
+    });
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002-expected.txt
deleted file mode 100644
index cdbe8a1..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-FAIL parse 'none, all' assert_equals: expected "none, all" but got "all"
-FAIL parse 'all, none' assert_equals: expected "all, none" but got "all"
-PASS parse 'foobar'
-PASS parse 'all, foobar'
-PASS parse 'foobar, all'
-PASS parse 'inherit'
-PASS parse 'initial'
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002.html
index 99196b6..2a46b3e2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-002.html
@@ -27,8 +27,8 @@
 
             // syntax: none | [ all | <IDENT> ] [ ‘,’ [ all | <IDENT> ] ]*
             var values = {
-                'none, all' : 'none, all',
-                'all, none' : 'all, none',
+                'none, all' : 'all',
+                'all, none' : 'all',
                 'foobar' : 'foobar',
                 'all, foobar' : 'all, foobar',
                 'foobar, all' : 'foobar, all',
diff --git a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
index 02a8f64..bf78b95b 100644
--- a/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
+++ b/third_party/blink/web_tests/fast/events/touch/compositor-touch-hit-rects-scroll-expected.txt
@@ -2,23 +2,17 @@
 
 scrollContent: layer(273x75) has hit test rect (0,13 273x12)
 
-scrollContent5: layer(160x10) has hit test rect (0,0 160x10)
 scrollContent5: layer(273x85) has hit test rect (0,13 273x12)
 
 scrollContent6: layer(273x12) has hit test rect (0,0 273x12)
 
-nestedContent: layer(140x10) has hit test rect (0,0 140x10)
 nestedContent: layer(256x72) has hit test rect (0,30 256x12)
 
-overflowwithhandler: layer(250x20) has hit test rect (0,0 250x10)
 overflowwithhandler: layer(256x116) has hit test rect (0,0 256x116)
-overflowwithhandler: layer(250x20) has hit test rect (0,10 70x10)
 overflowwithhandler: layer(273x112) has hit test rect (0,10 273x52)
 
-overflowwithborder: layer(250x20) has hit test rect (0,0 250x10)
 overflowwithborder: layer(255x116) has hit test rect (0,0 255x116)
-overflowwithborder: layer(250x20) has hit test rect (0,10 240x10)
-overflowwithborder: layer(769x881) has hit test rect (5,349 290x70)
+overflowwithborder: layer(769x753) has hit test rect (5,349 290x70)
 
 withTransform: layer(271x12) has hit test rect (0,0 271x12)
 withTransform: layer(273x77) has hit test rect (0,13 273x14)
diff --git a/third_party/blink/web_tests/fast/overflow/overflow-float-stacking.html b/third_party/blink/web_tests/fast/overflow/overflow-float-stacking.html
new file mode 100644
index 0000000..6c6c16e66
--- /dev/null
+++ b/third_party/blink/web_tests/fast/overflow/overflow-float-stacking.html
@@ -0,0 +1,53 @@
+<html>
+<body>
+Make sure that floating overflow:auto/hidden/scroll blocks stack properly with other floats at the same level.
+
+<div style="float:left; overflow:auto; width:300px; height:300px; background-color:lime; ">Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+</div>
+<div style="float:left; background-color:yellow;width:300px;height:300px; font-size:48px; margin-left:-50px">This block should be on top of the overflow block.</div>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/overflow/overflow-stacking.html b/third_party/blink/web_tests/fast/overflow/overflow-stacking.html
new file mode 100644
index 0000000..08004263
--- /dev/null
+++ b/third_party/blink/web_tests/fast/overflow/overflow-stacking.html
@@ -0,0 +1,53 @@
+<html>
+<body style="overflow: hidden;">
+Make sure that overflow:auto/hidden/scroll blocks interleave their background and foreground with other overlapping blocks in the normal flow.
+
+<div style="overflow:auto; width:300px; height:300px; background-color:lime; ">Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+Hello world<br>
+</div>
+<div style="background-color:yellow;width:300px;height:300px; font-size:48px; margin-top:-50px">This text overlaps.</div>
diff --git a/third_party/blink/web_tests/fast/scrolling/hide-scrollbars.html b/third_party/blink/web_tests/fast/scrolling/hide-scrollbars.html
index 066f1e4..9a04b3ea 100644
--- a/third_party/blink/web_tests/fast/scrolling/hide-scrollbars.html
+++ b/third_party/blink/web_tests/fast/scrolling/hide-scrollbars.html
@@ -11,7 +11,6 @@
     height: 100px;
     overflow: auto;
     background-color: lime;
-    position: relative;
 }
 .box {
     width: 500px;
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index 4a41bdc..3b23545 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -16,13 +16,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV class='scrollable bigBox'",
-      "position": [1, 1],
-      "bounds": [285, 800],
-      "contentsOpaque": true,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 286],
       "bounds": [300, 15],
@@ -36,6 +29,13 @@
       "transform": 1
     },
     {
+      "name": "LayoutBlockFlow DIV class='scrollable bigBox'",
+      "position": [1, 1],
+      "bounds": [285, 800],
+      "contentsOpaque": true,
+      "transform": 1
+    },
+    {
       "name": "LayoutBlockFlow (positioned) DIV class='fixed lime box'",
       "position": [10, 100],
       "bounds": [100, 100],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/textarea-scroll-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/textarea-scroll-touch-expected.txt
index d8caa6c..dd4ff7a8 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/textarea-scroll-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/textarea-scroll-touch-expected.txt
@@ -17,7 +17,8 @@
     {
       "name": "Scroll corner of LayoutTextControl TEXTAREA",
       "position": [193, 18],
-      "bounds": [261, 140]
+      "bounds": [261, 126],
+      "contentsOpaqueForText": true
     },
     {
       "name": "LayoutTextControl TEXTAREA",
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
index 1ae47dd..c38183f 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
@@ -14,13 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [10, 97],
       "bounds": [104, 257],
@@ -33,6 +26,13 @@
       "transform": 1
     },
     {
+      "name": "LayoutBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
+      "position": [2, 6],
+      "bounds": [85, 136],
+      "contentsOpaqueForText": true,
+      "transform": 2
+    },
+    {
       "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [35, 10],
       "bounds": [199, 105],
@@ -111,13 +111,6 @@
       "transform": 7
     },
     {
-      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 8
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [2, 87],
       "bounds": [100, 15],
@@ -131,6 +124,13 @@
       "transform": 7
     },
     {
+      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
+      "position": [2, 6],
+      "bounds": [85, 136],
+      "contentsOpaqueForText": true,
+      "transform": 8
+    },
+    {
       "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned'",
       "position": [395, 75],
       "bounds": [80, 40],
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/text/textfield-outline-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/text/textfield-outline-expected.png
new file mode 100644
index 0000000..3839dd0
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/text/textfield-outline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/overflow/overflow-stacking-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/overflow/overflow-stacking-expected.png
new file mode 100644
index 0000000..1b36f6b
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/overflow/overflow-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fragmentation/outline-crossing-columns-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fragmentation/outline-crossing-columns-expected.png
index 51b325f45..b432a376 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fragmentation/outline-crossing-columns-expected.png
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fragmentation/outline-crossing-columns-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/scrolling-without-painting-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/scrolling-without-painting-expected.txt
index 571b2c8..cb8a3ea 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/scrolling-without-painting-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/scrolling-without-painting-expected.txt
@@ -14,14 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "position": [1, 26],
-      "bounds": [185, 1000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [200, 15],
@@ -33,6 +25,14 @@
       "position": [186, 1],
       "bounds": [15, 185],
       "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='scroller'",
+      "position": [1, 26],
+      "bounds": [185, 1000],
+      "contentsOpaqueForText": true,
+      "drawsContent": false,
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
index 37ae674..bb9654f 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -13,16 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV id='container'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "invalidations": [
-        [0, 0, 1000, 1000]
-      ],
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [385, 15],
@@ -40,6 +30,16 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='container'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "invalidations": [
+        [0, 0, 1000, 1000]
+      ],
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/updating-scrolling-content-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/updating-scrolling-content-expected.txt
index ed1e093..9cc5d09 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/updating-scrolling-content-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/compositing/updating-scrolling-content-expected.txt
@@ -13,15 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "bounds": [185, 1200],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 185, 200]
-      ],
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 185],
       "bounds": [200, 15],
@@ -33,6 +24,15 @@
       "position": [185, 0],
       "bounds": [15, 185],
       "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV id='scroller'",
+      "bounds": [185, 1200],
+      "contentsOpaqueForText": true,
+      "invalidations": [
+        [0, 0, 185, 200]
+      ],
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index 0266ebf..6d0ec9ac 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutTextControl INPUT id='target'",
-      "position": [378, 7],
-      "bounds": [30, 24],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
new file mode 100644
index 0000000..6efbcc6
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/compositing/overflow/textarea-scroll-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/compositing/overflow/textarea-scroll-touch-expected.txt
deleted file mode 100644
index d8caa6c..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/compositing/overflow/textarea-scroll-touch-expected.txt
+++ /dev/null
@@ -1,106 +0,0 @@
- 
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutTextControl TEXTAREA",
-      "position": [1, 1],
-      "bounds": [189, 124],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "Scroll corner of LayoutTextControl TEXTAREA",
-      "position": [193, 18],
-      "bounds": [261, 140]
-    },
-    {
-      "name": "LayoutTextControl TEXTAREA",
-      "position": [1, 1],
-      "bounds": [189, 328],
-      "contentsOpaque": true,
-      "backgroundColor": "#CCCCCC",
-      "transform": 2
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [190, 1],
-      "bounds": [15, 109],
-      "transform": 1
-    },
-    {
-      "name": "LayoutTextControl TEXTAREA",
-      "position": [1, 1],
-      "bounds": [189, 124],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "Scroll corner of LayoutTextControl TEXTAREA",
-      "position": [175, 95],
-      "bounds": [30, 30],
-      "contentsOpaqueForText": true,
-      "transform": 3
-    },
-    {
-      "name": "LayoutTextControl TEXTAREA",
-      "position": [1, 1],
-      "bounds": [189, 328],
-      "contentsOpaque": true,
-      "backgroundColor": "#CCCCCC",
-      "transform": 4
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [190, 1],
-      "bounds": [15, 109],
-      "transform": 3
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [18, 18, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -50, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [248, 18, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -50, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/compositing/scrolling-without-painting-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/compositing/scrolling-without-painting-expected.txt
deleted file mode 100644
index 571b2c8..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/compositing/scrolling-without-painting-expected.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "position": [1, 1],
-      "bounds": [185, 185],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='scroller'",
-      "position": [1, 26],
-      "bounds": [185, 1000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [1, 186],
-      "bounds": [200, 15],
-      "contentsOpaqueForText": true,
-      "transform": 1
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [186, 1],
-      "bounds": [15, 185],
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -25, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index 0266ebf..6d0ec9ac 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutTextControl INPUT id='target'",
-      "position": [378, 7],
-      "bounds": [30, 24],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
index 6ad396e..b18aa163 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 6ad396e..b18aa163 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
deleted file mode 100644
index 1ae47dd..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/compositing/overflow/universal-accelerated-overflow-scroll-expected.txt
+++ /dev/null
@@ -1,843 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [785, 2016],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 2
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [10, 97],
-      "bounds": [104, 257],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 1
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-grandchildren-not-contained' class='positionAbsolute positioned'",
-      "position": [35, 10],
-      "bounds": [199, 105],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [85, 15],
-      "transform": 3
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 3
-    },
-    {
-      "name": "Scroll corner of LayoutBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
-      "position": [217, 10],
-      "bounds": [137, 104],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 6],
-      "bounds": [105, 136],
-      "contentsOpaqueForText": true,
-      "transform": 4
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-not-contained' class='overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 5
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 5
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 5
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-not-contained' class='positionAbsolute positioned'",
-      "position": [275, 10],
-      "bounds": [199, 105],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-not-contained' class='scrolled'",
-      "position": [6, 6],
-      "bounds": [75, 136],
-      "contentsOpaqueForText": true,
-      "transform": 6
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 7
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-grandchildren-not-contained' class='overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 8
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 7
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 7
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-grandchildren-not-contained' class='positionAbsolute positioned'",
-      "position": [395, 75],
-      "bounds": [80, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#800080"
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 9
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [85, 15],
-      "transform": 9
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 9
-    },
-    {
-      "name": "Scroll corner of LayoutBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
-      "position": [97, 130],
-      "bounds": [137, 104],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-sibling-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 6],
-      "bounds": [105, 136],
-      "contentsOpaqueForText": true,
-      "transform": 10
-    },
-    {
-      "name": "LayoutBlockFlow DIV id='container-absolute-sibling-not-contained' class='overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 11
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [130, 217],
-      "bounds": [224, 137],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 11
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling-not-contained' class='positionAbsolute positioned'",
-      "position": [155, 130],
-      "bounds": [199, 105],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled'",
-      "position": [6, 6],
-      "bounds": [75, 108],
-      "contentsOpaqueForText": true,
-      "transform": 12
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute-sibling' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 13
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [85, 15],
-      "transform": 13
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 13
-    },
-    {
-      "name": "Scroll corner of LayoutBlockFlow (positioned) DIV id='container-absolute-sibling' class='positionAbsolute overflow'",
-      "position": [337, 130],
-      "bounds": [137, 104],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute-sibling' class='positionAbsolute positioned'",
-      "position": [6, 6],
-      "bounds": [101, 108],
-      "contentsOpaqueForText": true,
-      "transform": 14
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-absolute' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 15
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [85, 15],
-      "transform": 15
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 15
-    },
-    {
-      "name": "Scroll corner of LayoutBlockFlow (positioned) DIV id='container-absolute' class='positionAbsolute overflow'",
-      "position": [370, 217],
-      "bounds": [104, 137],
-      "contentsOpaqueForText": true
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-absolute' class='positionAbsolute positioned'",
-      "position": [6, 6],
-      "bounds": [101, 108],
-      "contentsOpaqueForText": true,
-      "transform": 16
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-sibling-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 17
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 17
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 17
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-sibling-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 18
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-sibling-grandchildren' class='positionFixed positioned'",
-      "bounds": [80, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#800080",
-      "transform": 19
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-sibling' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 20
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 20
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 20
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-sibling' class='positionFixed positioned'",
-      "bounds": [80, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#800080",
-      "transform": 21
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled'",
-      "position": [6, 6],
-      "bounds": [75, 108],
-      "contentsOpaqueForText": true,
-      "transform": 22
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 23
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 23
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 23
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed-grandchildren' class='positionAbsolute overflow'",
-      "position": [2, 6],
-      "bounds": [85, 136],
-      "contentsOpaqueForText": true,
-      "transform": 24
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed-grandchildren' class='positionFixed positioned'",
-      "bounds": [80, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#800080",
-      "transform": 25
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='container-fixed' class='positionAbsolute overflow'",
-      "position": [2, 2],
-      "bounds": [85, 85],
-      "drawsContent": false,
-      "transform": 26
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [2, 87],
-      "bounds": [100, 15],
-      "contentsOpaqueForText": true,
-      "transform": 26
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [87, 2],
-      "bounds": [15, 85],
-      "transform": 26
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='positioned-fixed' class='positionFixed positioned'",
-      "bounds": [80, 40],
-      "contentsOpaque": true,
-      "backgroundColor": "#800080",
-      "transform": 27
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled'",
-      "position": [6, 6],
-      "bounds": [75, 108],
-      "contentsOpaqueForText": true,
-      "transform": 28
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-grandchildren-not-contained' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 29
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-grandchildren' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 30
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling-not-contained' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 31
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-absolute-sibling' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 32
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-fixed-sibling-grandchildren' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 33
-    },
-    {
-      "name": "LayoutBlockFlow (positioned) DIV id='sibling-fixed-sibling' class='positionFixed sibling'",
-      "bounds": [50, 100],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 34
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-grandchildren-not-contained' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 2
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren-not-contained' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 8
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-grandchildren' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 10
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling-not-contained' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 12
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute-sibling' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 14
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-absolute' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 16
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling-grandchildren' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 18
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-sibling' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 22
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed-grandchildren' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 24
-    },
-    {
-      "name": "LayoutBlockFlow (relative positioned) DIV id='scrolled-fixed' class='scrolled onTop'",
-      "position": [6, 62],
-      "bounds": [75, 80],
-      "contentsOpaqueForText": true,
-      "transform": 28
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 600]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [10, 10, 0, 1]
-      ]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [130, 10, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 5,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [250, 10, 0, 1]
-      ]
-    },
-    {
-      "id": 6,
-      "parent": 5,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 7,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [370, 10, 0, 1]
-      ]
-    },
-    {
-      "id": 8,
-      "parent": 7,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 9,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [10, 130, 0, 1]
-      ]
-    },
-    {
-      "id": 10,
-      "parent": 9,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 11,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [130, 130, 0, 1]
-      ]
-    },
-    {
-      "id": 12,
-      "parent": 11,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 13,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [250, 130, 0, 1]
-      ]
-    },
-    {
-      "id": 14,
-      "parent": 13,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 15,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [370, 130, 0, 1]
-      ]
-    },
-    {
-      "id": 16,
-      "parent": 15,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 17,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [10, 250, 0, 1]
-      ]
-    },
-    {
-      "id": 18,
-      "parent": 17,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 19,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [35, 315, 0, 1]
-      ]
-    },
-    {
-      "id": 20,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [130, 250, 0, 1]
-      ]
-    },
-    {
-      "id": 21,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [155, 315, 0, 1]
-      ]
-    },
-    {
-      "id": 22,
-      "parent": 20,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 23,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [250, 250, 0, 1]
-      ]
-    },
-    {
-      "id": 24,
-      "parent": 23,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 25,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [275, 315, 0, 1]
-      ]
-    },
-    {
-      "id": 26,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [370, 250, 0, 1]
-      ]
-    },
-    {
-      "id": 27,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [395, 315, 0, 1]
-      ]
-    },
-    {
-      "id": 28,
-      "parent": 26,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -59, 0, 1]
-      ]
-    },
-    {
-      "id": 29,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [375, 20, 0, 1]
-      ]
-    },
-    {
-      "id": 30,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [15, 140, 0, 1]
-      ]
-    },
-    {
-      "id": 31,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [135, 140, 0, 1]
-      ]
-    },
-    {
-      "id": 32,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [255, 140, 0, 1]
-      ]
-    },
-    {
-      "id": 33,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [15, 260, 0, 1]
-      ]
-    },
-    {
-      "id": 34,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [135, 260, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
new file mode 100644
index 0000000..6efbcc6
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
new file mode 100644
index 0000000..6efbcc6
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
new file mode 100644
index 0000000..6efbcc6
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-float-stacking-expected.png b/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-float-stacking-expected.png
new file mode 100644
index 0000000..a2d7e3e7
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-float-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-stacking-expected.png b/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-stacking-expected.png
new file mode 100644
index 0000000..0cd8d63
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/highdpi/fast/overflow/overflow-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-format-style-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-format-style-expected.txt
index 08eae08..c68ab67 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-format-style-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-format-style-expected.txt
@@ -24,17 +24,21 @@
 Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: blue; background: blue;
 Styled text #1: NO STYLES DEFINED
 console-format-style.js:20 12345678
-Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: black;
-Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: red;
-Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: darkgray;
-Styled text #3: contain: paint; display: inline-block; max-width: 100%; background: black;
-Styled text #4: contain: paint; display: inline-block; max-width: 100%; background: red;
-Styled text #5: contain: paint; display: inline-block; max-width: 100%; background: darkgray;
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-black);
+Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-red);
+Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-darkgray);
+Styled text #3: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred);
+Styled text #4: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-black);
+Styled text #5: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-red);
+Styled text #6: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-darkgray);
+Styled text #7: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-lightred);
 console-format-style.js:21 11.1a22.2b33.3
-Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: black;
-Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: red;
-Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: darkgray;
-Styled text #3: contain: paint; display: inline-block; max-width: 100%; background: black;
-Styled text #4: contain: paint; display: inline-block; max-width: 100%; background: red;
-Styled text #5: contain: paint; display: inline-block; max-width: 100%; background: darkgray;
+Styled text #0: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-black);
+Styled text #1: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-red);
+Styled text #2: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-darkgray);
+Styled text #3: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred);
+Styled text #4: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-black);
+Styled text #5: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-red);
+Styled text #6: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-darkgray);
+Styled text #7: contain: paint; display: inline-block; max-width: 100%; color: var(--console-color-lightred); background-color: var(--console-color-lightred);
 
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt
index 58183fa..4c4e580 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-without-painting-expected.txt
@@ -14,14 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='scroller'",
-      "position": [1, 26],
-      "bounds": [185, 1000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [200, 15],
@@ -33,6 +25,14 @@
       "position": [186, 1],
       "bounds": [15, 185],
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='scroller'",
+      "position": [1, 26],
+      "bounds": [185, 1000],
+      "contentsOpaqueForText": true,
+      "drawsContent": false,
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt
index e548140..b9a9a0e 100644
--- a/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/compositing/updating-scrolling-content-expected.txt
@@ -13,15 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='scroller'",
-      "bounds": [185, 1200],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 185, 200]
-      ],
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 185],
       "bounds": [200, 15],
@@ -33,6 +24,15 @@
       "position": [185, 0],
       "bounds": [15, 185],
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='scroller'",
+      "bounds": [185, 1200],
+      "contentsOpaqueForText": true,
+      "invalidations": [
+        [0, 0, 185, 200]
+      ],
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/text/input-text-scroll-left-on-blur-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/text/input-text-scroll-left-on-blur-expected.png
index acb33e8..9fc0b5b2 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/text/input-text-scroll-left-on-blur-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/text/input-text-scroll-left-on-blur-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/text/textfield-outline-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/text/textfield-outline-expected.png
index 99501d2..3839dd0 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/text/textfield-outline-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/text/textfield-outline-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-float-stacking-expected.png b/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-float-stacking-expected.png
new file mode 100644
index 0000000..af88aba
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-float-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-stacking-expected.png b/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-stacking-expected.png
new file mode 100644
index 0000000..1b36f6b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/overflow/overflow-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index 870f93f..bd3500f8 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='target'",
-      "position": [378, 7],
-      "bounds": [30, 24],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
index ce46d48..8abac62 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [67, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 67, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index ce46d48..8abac62 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [67, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 67, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/platform/linux/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
index d4ce951..6efbcc6 100644
--- a/third_party/blink/web_tests/platform/linux/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
+++ b/third_party/blink/web_tests/platform/linux/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index 870f93f..bd3500f8 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='target'",
-      "position": [378, 7],
-      "bounds": [30, 24],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
index ce46d48..8abac62 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [67, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 67, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index ce46d48..8abac62 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/backface-visibility-interop/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [67, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 67, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
index d4ce951..6efbcc6 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
index d4ce951..6efbcc6 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/scroll-unification-prefer_compositing_to_lcd_text/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
index d4ce951..6efbcc6 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/scroll-unification/scrollbars/custom-scrollbar-with-incomplete-style-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
similarity index 73%
rename from third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
index 6ec9a32..ae1a338 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/storage-access-api/storageAccess.testdriver.sub-expected.txt
@@ -1,8 +1,8 @@
 This is a testharness.js-based test.
 PASS Set up storage access rules
-PASS [third-party-allowed-on-first-party-site] Cookie access is allowed: true
-FAIL [third-party-blocked-all] Cookie access is allowed: false assert_equals: expected "" but got "hello2=world2"
 PASS [same-site] Cookie access is allowed: true
+PASS [third-party-allowed-on-first-party-site] Cookie access is allowed: true
 PASS [third-party-blocked-on-first-party-site] Cookie access is allowed: false
+PASS [third-party-blocked-all] Cookie access is allowed: false
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
deleted file mode 100644
index 9ce3ccab..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.15/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [785, 656],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "bounds": [345, 640],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "position": [0, 18],
-      "bounds": [345, 2000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
-      "bounds": [345, 18],
-      "transform": 4
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 600]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, -0.1],
-        [0, 0, 0, 1]
-      ],
-      "origin": [188, 328]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -35, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 35, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
deleted file mode 100644
index 9ce3ccab..0000000
--- a/third_party/blink/web_tests/platform/mac-mac11-arm64/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [785, 656],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "bounds": [345, 640],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "position": [0, 18],
-      "bounds": [345, 2000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
-      "bounds": [345, 18],
-      "transform": 4
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 600]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, -0.1],
-        [0, 0, 0, 1]
-      ],
-      "origin": [188, 328]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -35, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 35, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index 7307c27..b831b12 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -16,13 +16,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
-      "position": [1, 1],
-      "bounds": [285, 800],
-      "contentsOpaque": true,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 286],
       "bounds": [300, 15],
@@ -36,6 +29,13 @@
       "transform": 1
     },
     {
+      "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
+      "position": [1, 1],
+      "bounds": [285, 800],
+      "contentsOpaque": true,
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow (positioned) DIV class='fixed lime box'",
       "position": [10, 100],
       "bounds": [100, 100],
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
index 4146b889..74a5897 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index 4146b889..74a5897 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/textarea-scroll-touch-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/overflow/textarea-scroll-touch-expected.txt
index 3f77449..f839ce61 100644
--- a/third_party/blink/web_tests/platform/mac/compositing/overflow/textarea-scroll-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/textarea-scroll-touch-expected.txt
@@ -17,7 +17,8 @@
     {
       "name": "Scroll corner of LayoutNGTextControlMultiLine TEXTAREA",
       "position": [193, 18],
-      "bounds": [261, 140]
+      "bounds": [261, 126],
+      "contentsOpaqueForText": true
     },
     {
       "name": "LayoutNGTextControlMultiLine TEXTAREA",
diff --git a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-float-stacking-expected.png b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-float-stacking-expected.png
new file mode 100644
index 0000000..fbb1db9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-float-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-stacking-expected.png b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-stacking-expected.png
new file mode 100644
index 0000000..bdcdd63
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/overflow/overflow-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
index 6ee1cf68..f973ad9 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -13,16 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "invalidations": [
-        [0, 0, 1000, 1000]
-      ],
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [385, 15],
@@ -40,6 +30,16 @@
       "bounds": [15, 15],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "invalidations": [
+        [0, 0, 1000, 1000]
+      ],
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt
index f9c16c56..1647f6f 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/text-match-highlight-expected.txt
@@ -16,6 +16,19 @@
       "transform": 1
     },
     {
+      "name": "HorizontalScrollbar",
+      "position": [0, 485],
+      "bounds": [800, 15],
+      "contentsOpaqueForText": true,
+      "transform": 1
+    },
+    {
+      "name": "VerticalScrollbar",
+      "position": [785, 0],
+      "bounds": [15, 485],
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow DIV",
       "bounds": [785, 1340],
       "invalidations": [
@@ -28,19 +41,6 @@
         [52, 18, 45, 18]
       ],
       "transform": 1
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [0, 485],
-      "bounds": [800, 15],
-      "contentsOpaqueForText": true,
-      "transform": 1
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 485],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt
index 4fd0bd7d..3921eaa 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/compositing/updating-scrolling-container-expected.txt
@@ -17,12 +17,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container'",
-      "position": [5, 5],
-      "bounds": [400, 400],
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [5, 190],
       "bounds": [185, 15],
@@ -40,6 +34,12 @@
       "bounds": [15, 15],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "position": [5, 5],
+      "bounds": [400, 400],
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt
index becf587..e1b39c1 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-child-expected.txt
@@ -14,16 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='container'",
-      "position": [1, 1],
-      "bounds": [2100, 100],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [2000, 0, 100, 100]
-      ],
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [285, 15],
@@ -35,6 +25,16 @@
       "bounds": [15, 200],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='container'",
+      "position": [1, 1],
+      "bounds": [2100, 100],
+      "contentsOpaqueForText": true,
+      "invalidations": [
+        [2000, 0, 100, 100]
+      ],
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt
index 8ed52f00..73ff67c 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-parent-expected.txt
@@ -14,16 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='container'",
-      "position": [1, 1],
-      "bounds": [2100, 100],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 100, 100]
-      ],
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [285, 15],
@@ -35,6 +25,16 @@
       "bounds": [15, 200],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='container'",
+      "position": [1, 1],
+      "bounds": [2100, 100],
+      "contentsOpaqueForText": true,
+      "invalidations": [
+        [0, 0, 100, 100]
+      ],
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt
index 2e4fc76..9eac869 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/vertical-overflow-same-expected.txt
@@ -14,16 +14,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='vertical-rl container'",
-      "position": [1, 1],
-      "bounds": [2100, 100],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 100, 100]
-      ],
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [285, 15],
@@ -35,6 +25,16 @@
       "bounds": [15, 200],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='vertical-rl container'",
+      "position": [1, 1],
+      "bounds": [2100, 100],
+      "contentsOpaqueForText": true,
+      "invalidations": [
+        [0, 0, 100, 100]
+      ],
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index 35bdb3c..6da51e38 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 15]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='target'",
-      "position": [386, 7],
-      "bounds": [30, 23],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
index bb1c587..b3d0a23 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 15]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [50, 23],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 50, 23]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index bb1c587..b3d0a23 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 15]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [50, 23],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 50, 23]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
index e49a1b1..d1be11a0 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -13,6 +13,12 @@
       "transform": 1
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [769, 0],
+      "bounds": [15, 300],
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow DIV id='outerDiv'",
       "bounds": [769, 700],
       "contentsOpaqueForText": true,
@@ -25,23 +31,17 @@
       "transform": 3
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
-      "bounds": [300, 800],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 4
-    },
-    {
       "name": "VerticalScrollbar",
       "position": [754, 0],
       "bounds": [15, 400],
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [769, 0],
-      "bounds": [15, 300],
-      "transform": 1
+      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
+      "bounds": [300, 800],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 4
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index e49a1b1..d1be11a0 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -13,6 +13,12 @@
       "transform": 1
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [769, 0],
+      "bounds": [15, 300],
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow DIV id='outerDiv'",
       "bounds": [769, 700],
       "contentsOpaqueForText": true,
@@ -25,23 +31,17 @@
       "transform": 3
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
-      "bounds": [300, 800],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "transform": 4
-    },
-    {
       "name": "VerticalScrollbar",
       "position": [754, 0],
       "bounds": [15, 400],
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [769, 0],
-      "bounds": [15, 300],
-      "transform": 1
+      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
+      "bounds": [300, 800],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "transform": 4
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
index e51fc7b..768e500 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-ancestor-clip-change-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='target'",
-      "bounds": [400, 400],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 185],
       "bounds": [85, 15],
@@ -40,6 +33,13 @@
         [0, 0, 15, 15]
       ],
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='target'",
+      "bounds": [400, 400],
+      "contentsOpaqueForText": true,
+      "drawsContent": false,
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt
index 5c01d1ad..cf98a16 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-damage-and-full-viewport-repaint-expected.txt
@@ -18,14 +18,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container'",
-      "position": [1, 1],
-      "bounds": [2000, 2000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 186],
       "bounds": [185, 15],
@@ -46,6 +38,14 @@
         [0, 0, 15, 15]
       ],
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "position": [1, 1],
+      "bounds": [2000, 2000],
+      "contentsOpaqueForText": true,
+      "drawsContent": false,
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt
index 5c4cbcd..367fb46 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/scrollbar-parts-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV",
-      "bounds": [150, 300],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 85],
       "bounds": [85, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaqueForText": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV",
+      "bounds": [150, 300],
+      "contentsOpaqueForText": true,
+      "drawsContent": false,
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
index 78b2dd46..9ce3ccab 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
@@ -13,6 +13,12 @@
       "transform": 2
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [345, 0],
+      "bounds": [15, 640],
+      "transform": 2
+    },
+    {
       "name": "LayoutNGBlockFlow MAT id='scroller'",
       "position": [0, 18],
       "bounds": [345, 2000],
@@ -21,12 +27,6 @@
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
       "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
       "bounds": [345, 18],
       "transform": 4
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
index cf52cf893..8d07762 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-auto-in-overflow-auto-scrolled-expected.txt
@@ -13,6 +13,12 @@
       "transform": 1
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [769, 0],
+      "bounds": [15, 300],
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow DIV id='outerDiv'",
       "bounds": [769, 700],
       "contentsOpaqueForText": true,
@@ -25,22 +31,16 @@
       "transform": 3
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
-      "bounds": [306, 810],
-      "contentsOpaqueForText": true,
-      "transform": 4
-    },
-    {
       "name": "VerticalScrollbar",
       "position": [754, 0],
       "bounds": [15, 400],
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [769, 0],
-      "bounds": [15, 300],
-      "transform": 1
+      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
+      "bounds": [306, 810],
+      "contentsOpaqueForText": true,
+      "transform": 4
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
index cf52cf893..8d07762 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/table/table-overflow-scroll-in-overflow-scroll-scrolled-expected.txt
@@ -13,6 +13,12 @@
       "transform": 1
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [769, 0],
+      "bounds": [15, 300],
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow DIV id='outerDiv'",
       "bounds": [769, 700],
       "contentsOpaqueForText": true,
@@ -25,22 +31,16 @@
       "transform": 3
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
-      "bounds": [306, 810],
-      "contentsOpaqueForText": true,
-      "transform": 4
-    },
-    {
       "name": "VerticalScrollbar",
       "position": [754, 0],
       "bounds": [15, 400],
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [769, 0],
-      "bounds": [15, 300],
-      "transform": 1
+      "name": "LayoutNGBlockFlow DIV id='innerDiv'",
+      "bounds": [306, 810],
+      "contentsOpaqueForText": true,
+      "transform": 4
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/mac/virtual/backface-visibility-interop/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/backface-visibility-interop/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
deleted file mode 100644
index 78b2dd46..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/backface-visibility-interop/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [785, 656],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "bounds": [345, 640],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "position": [0, 18],
-      "bounds": [345, 2000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
-      "bounds": [345, 18],
-      "transform": 4
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 600]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, -0.1],
-        [0, 0, 0, 1]
-      ],
-      "origin": [188, 328]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -35, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 35, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
index a194211d..44e76574 100644
--- a/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers-expected.txt
@@ -16,13 +16,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
-      "position": [1, 1],
-      "bounds": [285, 800],
-      "contentsOpaque": true,
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [1, 286],
       "bounds": [300, 15],
@@ -36,6 +29,13 @@
       "transform": 1
     },
     {
+      "name": "LayoutNGBlockFlow DIV class='scrollable bigBox'",
+      "position": [1, 1],
+      "bounds": [285, 800],
+      "contentsOpaque": true,
+      "transform": 1
+    },
+    {
       "name": "LayoutNGBlockFlow (positioned) DIV class='fixed lime box'",
       "position": [10, 100],
       "bounds": [100, 100],
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/textarea-scroll-touch-expected.txt b/third_party/blink/web_tests/platform/win/compositing/overflow/textarea-scroll-touch-expected.txt
index 9c61a61..2c45613a 100644
--- a/third_party/blink/web_tests/platform/win/compositing/overflow/textarea-scroll-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/win/compositing/overflow/textarea-scroll-touch-expected.txt
@@ -17,7 +17,8 @@
     {
       "name": "Scroll corner of LayoutNGTextControlMultiLine TEXTAREA",
       "position": [193, 18],
-      "bounds": [261, 140]
+      "bounds": [261, 126],
+      "contentsOpaqueForText": true
     },
     {
       "name": "LayoutNGTextControlMultiLine TEXTAREA",
diff --git a/third_party/blink/web_tests/platform/win/fast/overflow/overflow-float-stacking-expected.png b/third_party/blink/web_tests/platform/win/fast/overflow/overflow-float-stacking-expected.png
new file mode 100644
index 0000000..31ac325
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/overflow/overflow-float-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/overflow/overflow-stacking-expected.png b/third_party/blink/web_tests/platform/win/fast/overflow/overflow-stacking-expected.png
new file mode 100644
index 0000000..afc1cad6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/overflow/overflow-stacking-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
index 1c2de1e..ab73de1 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer-expected.txt
@@ -13,16 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV id='container'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#008000",
-      "invalidations": [
-        [0, 0, 1000, 1000]
-      ],
-      "transform": 2
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [385, 15],
@@ -40,6 +30,16 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV id='container'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#008000",
+      "invalidations": [
+        [0, 0, 1000, 1000]
+      ],
+      "transform": 2
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
index ddce7c6..afb14ab 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/caret-invalidation-in-overflow-scroll-expected.txt
@@ -15,12 +15,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 1
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='target'",
-      "position": [360, 7],
-      "bounds": [30, 24],
-      "contentsOpaqueForText": true
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
index c374580..584bf20 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [74, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 74, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
index c374580..584bf20 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container-expected.txt
@@ -26,16 +26,6 @@
         [0, 0, 1, 16]
       ],
       "transform": 2
-    },
-    {
-      "name": "LayoutNGTextControlSingleLine INPUT id='root'",
-      "position": [-1, -1],
-      "bounds": [74, 24],
-      "contentsOpaqueForText": true,
-      "invalidations": [
-        [0, 0, 74, 24]
-      ],
-      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/platform/win/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
index 2a75512..27f8829 100644
--- a/third_party/blink/web_tests/platform/win/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ b/third_party/blink/web_tests/platform/win/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
@@ -13,6 +13,12 @@
       "transform": 2
     },
     {
+      "name": "VerticalScrollbar",
+      "position": [345, 0],
+      "bounds": [15, 640],
+      "transform": 2
+    },
+    {
       "name": "LayoutNGBlockFlow MAT id='scroller'",
       "position": [0, 20],
       "bounds": [345, 2000],
@@ -21,12 +27,6 @@
       "transform": 3
     },
     {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
       "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
       "bounds": [345, 20],
       "transform": 4
diff --git a/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
index a9d5c31..66e361c 100644
--- a/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ b/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
index a9d5c31..66e361c 100644
--- a/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ b/third_party/blink/web_tests/platform/win/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
@@ -13,13 +13,6 @@
       "transform": 1
     },
     {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
       "name": "HorizontalScrollbar",
       "position": [0, 285],
       "bounds": [285, 15],
@@ -37,6 +30,13 @@
       "bounds": [15, 15],
       "contentsOpaque": true,
       "transform": 1
+    },
+    {
+      "name": "LayoutNGBlockFlow DIV class='scroller'",
+      "bounds": [1000, 1000],
+      "contentsOpaque": true,
+      "backgroundColor": "#C0C0C0",
+      "transform": 1
     }
   ],
   "transforms": [
diff --git a/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt b/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
deleted file mode 100644
index 78b2dd46..0000000
--- a/third_party/blink/web_tests/virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky-expected.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [785, 656],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "bounds": [345, 640],
-      "drawsContent": false,
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow MAT id='scroller'",
-      "position": [0, 18],
-      "bounds": [345, 2000],
-      "contentsOpaqueForText": true,
-      "drawsContent": false,
-      "transform": 3
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [345, 0],
-      "bounds": [15, 640],
-      "transform": 2
-    },
-    {
-      "name": "LayoutNGBlockFlow (sticky positioned) DIV id='sticky'",
-      "bounds": [345, 18],
-      "transform": 4
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [785, 0],
-      "bounds": [15, 600]
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, -0.1],
-        [0, 0, 0, 1]
-      ],
-      "origin": [188, 328]
-    },
-    {
-      "id": 2,
-      "parent": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ],
-      "flattenInheritedTransform": false
-    },
-    {
-      "id": 3,
-      "parent": 2,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, -35, 0, 1]
-      ]
-    },
-    {
-      "id": 4,
-      "parent": 3,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [0, 35, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
deleted file mode 100644
index 4146b889..0000000
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [285, 285],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [0, 285],
-      "bounds": [285, 15],
-      "transform": 1
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [285, 0],
-      "bounds": [15, 285],
-      "transform": 1
-    },
-    {
-      "name": "Scroll corner of LayoutNGBlockFlow DIV class='scroller'",
-      "position": [285, 285],
-      "bounds": [15, 15],
-      "contentsOpaqueForText": true,
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
deleted file mode 100644
index 4146b889..0000000
--- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/overflow-auto-with-touch-toggle-expected.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling background of LayoutView #document",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF"
-    },
-    {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [285, 285],
-      "drawsContent": false,
-      "transform": 1
-    },
-    {
-      "name": "LayoutNGBlockFlow DIV class='scroller'",
-      "bounds": [1000, 1000],
-      "contentsOpaque": true,
-      "backgroundColor": "#C0C0C0",
-      "transform": 1
-    },
-    {
-      "name": "HorizontalScrollbar",
-      "position": [0, 285],
-      "bounds": [285, 15],
-      "transform": 1
-    },
-    {
-      "name": "VerticalScrollbar",
-      "position": [285, 0],
-      "bounds": [15, 285],
-      "transform": 1
-    },
-    {
-      "name": "Scroll corner of LayoutNGBlockFlow DIV class='scroller'",
-      "position": [285, 285],
-      "bounds": [15, 15],
-      "contentsOpaqueForText": true,
-      "transform": 1
-    }
-  ],
-  "transforms": [
-    {
-      "id": 1,
-      "transform": [
-        [1, 0, 0, 0],
-        [0, 1, 0, 0],
-        [0, 0, 1, 0],
-        [8, 8, 0, 1]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index e2b78de..f464eb1 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-11-1-21-gbf9b1ef90
-Revision: bf9b1ef90564987856a42461147435f143e9e7cd
+Version: VER-2-11-1-26-ga25e85ed9
+Revision: a25e85ed95dc855e42e6bb55138e27d362c5ea1e
 CPEPrefix: cpe:/a:freetype:freetype:2.11.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/node/README.chromium b/third_party/node/README.chromium
index e1f415b..617815c 100644
--- a/third_party/node/README.chromium
+++ b/third_party/node/README.chromium
@@ -125,3 +125,17 @@
 
 Local Modifications:
 (none)
+
+
+Name: ESLint JSDoc Plugin
+Short Name: eslint-plugin-jsdoc
+URL: https://www.npmjs.com/package/eslint-plugin-jsdoc
+Version: 37.5.1
+License: BSD-3-Clause
+Security Critical: No. The ESLint checks are not shipped with Chrome and code are only linted with it.
+
+Description:
+JSDoc linting rules for ESLint.
+
+Local Modifications:
+(none)
diff --git a/third_party/node/node_modules.tar.gz.sha1 b/third_party/node/node_modules.tar.gz.sha1
index db12726..4b3a85d 100644
--- a/third_party/node/node_modules.tar.gz.sha1
+++ b/third_party/node/node_modules.tar.gz.sha1
@@ -1 +1 @@
-31d731fb82ea62a6dae24d2bdfe6f0aa6164b949
+1291471c9ef3dd6fca73dda7b5d0eea1026da863
diff --git a/third_party/node/package-lock.json b/third_party/node/package-lock.json
index 55a2f3c..812b07a 100644
--- a/third_party/node/package-lock.json
+++ b/third_party/node/package-lock.json
@@ -20,6 +20,7 @@
         "babel-eslint": "10.0.2",
         "crisper": "2.1.1",
         "eslint": "7.11.0",
+        "eslint-plugin-jsdoc": "37.5.1",
         "polymer-bundler": "4.0.10",
         "polymer-css-build": "0.7.0",
         "rollup": "2.58.0",
@@ -174,6 +175,19 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/@es-joy/jsdoccomment": {
+      "version": "0.14.2",
+      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.14.2.tgz",
+      "integrity": "sha512-812igKXDcLEdkwUbJvnhzMy88dBBiDeaf3mMF1jnQwclIObu5UQB8ow1KAvDRN1FQqpB+IsZnpmRA0jZ6KGt3g==",
+      "dependencies": {
+        "comment-parser": "1.3.0",
+        "esquery": "^1.4.0",
+        "jsdoc-type-pratt-parser": "2.0.2"
+      },
+      "engines": {
+        "node": "^12 || ^14 || ^16 || ^17"
+      }
+    },
     "node_modules/@eslint/eslintrc": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@@ -1054,6 +1068,14 @@
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
     },
+    "node_modules/comment-parser": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
+      "integrity": "sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==",
+      "engines": {
+        "node": ">= 12.0.0"
+      }
+    },
     "node_modules/concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1171,9 +1193,9 @@
       }
     },
     "node_modules/debug": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-      "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "version": "4.3.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
       "dependencies": {
         "ms": "2.1.2"
       },
@@ -1424,6 +1446,39 @@
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/eslint-plugin-jsdoc": {
+      "version": "37.5.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.5.1.tgz",
+      "integrity": "sha512-WMv/Na5QdpMQao1MR3SgYpGFi2PSrhh/JljlErQru9ZYXf1j9oQVIVCELQV7jcyqKQ/svPqCyU8eMhet9dzP+w==",
+      "dependencies": {
+        "@es-joy/jsdoccomment": "0.14.2",
+        "comment-parser": "1.3.0",
+        "debug": "^4.3.3",
+        "escape-string-regexp": "^4.0.0",
+        "esquery": "^1.4.0",
+        "jsdoc-type-pratt-parser": "^2.0.2",
+        "regextras": "^0.8.0",
+        "semver": "^7.3.5",
+        "spdx-expression-parse": "^3.0.1"
+      },
+      "engines": {
+        "node": "^12 || ^14 || ^16 || ^17"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/eslint-scope": {
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
@@ -2232,6 +2287,14 @@
         "js-yaml": "bin/js-yaml.js"
       }
     },
+    "node_modules/jsdoc-type-pratt-parser": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.0.2.tgz",
+      "integrity": "sha512-gXN5CxeaI9WtYQYzpOO/CtTRfZppQlKxXRTIm73JuAX6kOGTQ7iZ0e+YB+b2m7Fk+gTYYxRtE1nqje7H6dqv8w==",
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
     "node_modules/jsesc": {
       "version": "2.5.2",
       "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -3156,6 +3219,14 @@
         "url": "https://github.com/sponsors/mysticatea"
       }
     },
+    "node_modules/regextras": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.8.0.tgz",
+      "integrity": "sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==",
+      "engines": {
+        "node": ">=0.1.14"
+      }
+    },
     "node_modules/repeating": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
@@ -3345,6 +3416,25 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/spdx-exceptions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
+    },
+    "node_modules/spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dependencies": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "node_modules/spdx-license-ids": {
+      "version": "3.0.11",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+      "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g=="
+    },
     "node_modules/sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -3878,6 +3968,16 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@es-joy/jsdoccomment": {
+      "version": "0.14.2",
+      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.14.2.tgz",
+      "integrity": "sha512-812igKXDcLEdkwUbJvnhzMy88dBBiDeaf3mMF1jnQwclIObu5UQB8ow1KAvDRN1FQqpB+IsZnpmRA0jZ6KGt3g==",
+      "requires": {
+        "comment-parser": "1.3.0",
+        "esquery": "^1.4.0",
+        "jsdoc-type-pratt-parser": "2.0.2"
+      }
+    },
     "@eslint/eslintrc": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
@@ -4568,6 +4668,11 @@
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
       "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
     },
+    "comment-parser": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
+      "integrity": "sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA=="
+    },
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -4658,9 +4763,9 @@
       }
     },
     "debug": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-      "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+      "version": "4.3.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+      "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
       "requires": {
         "ms": "2.1.2"
       }
@@ -4915,6 +5020,29 @@
         }
       }
     },
+    "eslint-plugin-jsdoc": {
+      "version": "37.5.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.5.1.tgz",
+      "integrity": "sha512-WMv/Na5QdpMQao1MR3SgYpGFi2PSrhh/JljlErQru9ZYXf1j9oQVIVCELQV7jcyqKQ/svPqCyU8eMhet9dzP+w==",
+      "requires": {
+        "@es-joy/jsdoccomment": "0.14.2",
+        "comment-parser": "1.3.0",
+        "debug": "^4.3.3",
+        "escape-string-regexp": "^4.0.0",
+        "esquery": "^1.4.0",
+        "jsdoc-type-pratt-parser": "^2.0.2",
+        "regextras": "^0.8.0",
+        "semver": "^7.3.5",
+        "spdx-expression-parse": "^3.0.1"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+        }
+      }
+    },
     "eslint-scope": {
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
@@ -5418,6 +5546,11 @@
         "esprima": "^4.0.0"
       }
     },
+    "jsdoc-type-pratt-parser": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.0.2.tgz",
+      "integrity": "sha512-gXN5CxeaI9WtYQYzpOO/CtTRfZppQlKxXRTIm73JuAX6kOGTQ7iZ0e+YB+b2m7Fk+gTYYxRtE1nqje7H6dqv8w=="
+    },
     "jsesc": {
       "version": "2.5.2",
       "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@@ -6133,6 +6266,11 @@
       "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
       "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg=="
     },
+    "regextras": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.8.0.tgz",
+      "integrity": "sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ=="
+    },
     "repeating": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
@@ -6261,6 +6399,25 @@
         }
       }
     },
+    "spdx-exceptions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A=="
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.11",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+      "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g=="
+    },
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
diff --git a/third_party/node/package.json b/third_party/node/package.json
index 1d7f088..f8ac24cc 100644
--- a/third_party/node/package.json
+++ b/third_party/node/package.json
@@ -15,6 +15,7 @@
     "babel-eslint": "10.0.2",
     "crisper": "2.1.1",
     "eslint": "7.11.0",
+    "eslint-plugin-jsdoc": "37.5.1",
     "polymer-bundler": "4.0.10",
     "polymer-css-build": "0.7.0",
     "rollup": "2.58.0",
diff --git a/tools/binary_size/libsupersize/describe.py b/tools/binary_size/libsupersize/describe.py
index de87d68..44ba312 100644
--- a/tools/binary_size/libsupersize/describe.py
+++ b/tools/binary_size/libsupersize/describe.py
@@ -535,9 +535,8 @@
           self._DescribeDeltaDict('Build config', diff.before.build_config,
                                   diff.after.build_config))
       for c in diff.containers:
-        name = c.name
         desc_list.append(('', ))
-        desc_list.append(('Container: <%s>' % name, ))
+        desc_list.append(('Container<%s>: %s' % (c.short_name, c.name), ))
         desc_list.append(
             self._DescribeDeltaDict('Metadata',
                                     c.before.metadata,
@@ -581,7 +580,7 @@
     for c in containers:
       if c.name:
         desc_list.append(('', ))
-        desc_list.append(('Container <%s>' % c.name, ))
+        desc_list.append(('Container<%s>: %s' % (c.short_name, c.name), ))
       desc_list.append(('Metadata:', ))
       desc_list.append('    %s' % line for line in DescribeDict(c.metadata))
       unsummed_sections, summed_sections = c.ClassifySections()
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py
index f44bcb0e..9d64158 100644
--- a/tools/binary_size/libsupersize/models.py
+++ b/tools/binary_size/libsupersize/models.py
@@ -1082,6 +1082,7 @@
 
   def WhereInContainer(self, container):
     """|container| can be name, short_name, or container instance."""
+    container = str(container)  # Allow int to be used for short names.
     if isinstance(container, str):
       if container.isdigit():
         return self.Filter(lambda s: s.container_short_name == container)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index cb690d9..539e1844 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -8368,6 +8368,7 @@
   <int value="259" label="PMM_SUBSCRIBE_INVALID_ORIGIN"/>
   <int value="260" label="PMM_UNSUBSCRIBE_INVALID_ORIGIN"/>
   <int value="261" label="PMM_GET_SUBSCRIPTION_INVALID_ORIGIN"/>
+  <int value="262" label="RFH_INACTIVE_CHECK_FROM_PENDING_COMMIT_RFH"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions">
@@ -36658,6 +36659,7 @@
   <int value="4102" label="HTMLObjectElementFallback"/>
   <int value="4103" label="SecureContextIncorrectForWorker"/>
   <int value="4104" label="V8UDPSocket_Close_Method"/>
+  <int value="4105" label="HTMLInputElementSimulatedClick"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index bff2166..73e46334 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -711,7 +711,7 @@
 </histogram>
 
 <histogram name="Permissions.Prompt.{PermissionType}.{Disposition}.Action"
-    enum="PermissionAction" expires_after="M100">
+    enum="PermissionAction" expires_after="M110">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -741,7 +741,7 @@
 
 <histogram
     name="Permissions.Prompt.{PermissionType}.{Disposition}.Ignored.DidShowBubble"
-    enum="Boolean" expires_after="M100">
+    enum="Boolean" expires_after="M110">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -772,7 +772,7 @@
 
 <histogram
     name="Permissions.Prompt.{PermissionType}.{Disposition}.{Action}.TimeToAction"
-    units="ms" expires_after="M100">
+    units="ms" expires_after="M110">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -810,7 +810,7 @@
 
 <histogram
     name="Permissions.Prompt.{PermissionType}.{Disposition}.{Action}.{ButtonClick}"
-    enum="Boolean" expires_after="M100">
+    enum="Boolean" expires_after="M110">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 465b9dc..08fd8dbc 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -176,6 +176,9 @@
 
 <histogram name="Settings.PinnedTabEngineTypes" enum="OmniboxSearchEngineType"
     expires_after="2022-01-02">
+  <obsolete>
+    Removed January 2022.
+  </obsolete>
   <owner>mpearson@chromium.org</owner>
   <owner>csharp@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index 7d765bd..e1584e8 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -1847,7 +1847,7 @@
 </histogram>
 
 <histogram name="V8.WasmModuleCodeSizePercentFreed" units="%"
-    expires_after="2022-02-15">
+    expires_after="2023-01-31">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
@@ -1884,7 +1884,7 @@
 </histogram>
 
 <histogram name="V8.WasmModuleNumberOfCodeSpaces" units="spaces"
-    expires_after="2022-02-15">
+    expires_after="2023-01-31">
   <owner>ecmziegler@chromium.org</owner>
   <owner>adamk@chromium.org</owner>
   <owner>clemensb@chromium.org</owner>
diff --git a/tools/traffic_annotation/scripts/auditor/auditor.py b/tools/traffic_annotation/scripts/auditor/auditor.py
index de11a6d..ba067fb 100755
--- a/tools/traffic_annotation/scripts/auditor/auditor.py
+++ b/tools/traffic_annotation/scripts/auditor/auditor.py
@@ -2015,7 +2015,11 @@
 
   try:
     sys.exit(auditor_ui.main())
-  except Exception as e:
+  except extractor.SourceCodeParsingError:
+    # Even with --error-resilient, CQ should turn red if C++/Java code doesn't
+    # parse.
+    raise
+  except Exception:
     if args.error_resilient:
       traceback.print_exc()
       sys.exit(0)
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
index b94fff1..e959b1b 100644
--- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -457,9 +457,17 @@
 // about to finish.
 void WaylandWindowDragController::HandleDropAndResetState() {
   DCHECK_EQ(state_, State::kDropped);
-  DCHECK(drag_source_);
   DVLOG(1) << "Notifying drop. window=" << pointer_grab_owner_;
 
+  // StopDragging() may get called in response to bogus input events, eg:
+  // wl_pointer.button release, which would imply in multiple calls to this
+  // function for a single drop event. That results in ILL_ILLOPN crashes in
+  // below code, because |drag_source_| is null after the first call to this
+  // function. So, early out here in that case.
+  // TODO(crbug.com/1280981): Revert this once Exo-side issue gets solved.
+  if (!drag_source_.has_value())
+    return;
+
   if (*drag_source_ == DragSource::kMouse) {
     if (pointer_grab_owner_) {
       pointer_delegate_->OnPointerButtonEvent(
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index c92ce0c..946426c3 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -609,6 +609,8 @@
       "accessibility/ax_virtual_view_mac.mm",
       "cocoa/drag_drop_client_mac.h",
       "cocoa/drag_drop_client_mac.mm",
+      "cocoa/native_widget_mac_event_monitor.h",
+      "cocoa/native_widget_mac_event_monitor.mm",
       "cocoa/native_widget_mac_ns_window_host.mm",
       "cocoa/text_input_host.h",
       "cocoa/text_input_host.mm",
diff --git a/ui/views/cocoa/native_widget_mac_event_monitor.h b/ui/views/cocoa/native_widget_mac_event_monitor.h
new file mode 100644
index 0000000..1b31a8b
--- /dev/null
+++ b/ui/views/cocoa/native_widget_mac_event_monitor.h
@@ -0,0 +1,48 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_EVENT_MONITOR_H_
+#define UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_EVENT_MONITOR_H_
+
+#include "base/callback_helpers.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class Event;
+}  // namespace ui
+
+namespace views {
+
+class NativeWidgetMacNSWindowHost;
+
+// A class for event monitoring. This will create a NSEvent local monitor in
+// for this widget (in this process or in a remote process). The monitor will
+// call back through the Client interface.
+class VIEWS_EXPORT NativeWidgetMacEventMonitor {
+ public:
+  class Client {
+   public:
+    // Called for every observed NSEvent. If this client handles the event,
+    // it should set `event_handled` to true. The initial value of
+    // `event_handled` will be true if another client handled this event.
+    virtual void NativeWidgetMacEventMonitorOnEvent(ui::Event* event,
+                                                    bool* event_handled) = 0;
+  };
+  ~NativeWidgetMacEventMonitor();
+
+ private:
+  friend class NativeWidgetMacNSWindowHost;
+  explicit NativeWidgetMacEventMonitor(Client* client);
+
+  Client* const client_;
+
+  // Scoped closure runner that will unregister `this` from its
+  // NativeWidgetMacNSWindowHost when `this` is destroyed.
+  base::ScopedClosureRunner remove_closure_runner_;
+};
+
+}  // namespace views
+
+#endif  // UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_EVENT_MONITOR_H_
diff --git a/ui/views/cocoa/native_widget_mac_event_monitor.mm b/ui/views/cocoa/native_widget_mac_event_monitor.mm
new file mode 100644
index 0000000..cf86ec8c
--- /dev/null
+++ b/ui/views/cocoa/native_widget_mac_event_monitor.mm
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/cocoa/native_widget_mac_event_monitor.h"
+
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
+
+namespace views {
+
+NativeWidgetMacEventMonitor::NativeWidgetMacEventMonitor(Client* client)
+    : client_(client) {}
+
+NativeWidgetMacEventMonitor::~NativeWidgetMacEventMonitor() = default;
+
+}  // namespace views
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.h b/ui/views/cocoa/native_widget_mac_ns_window_host.h
index 0dfd2de..03c2f1a9 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.h
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.h
@@ -5,6 +5,7 @@
 #ifndef UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_
 #define UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_
 
+#include <list>
 #include <map>
 #include <memory>
 #include <string>
@@ -24,6 +25,7 @@
 #include "ui/compositor/layer_owner.h"
 #include "ui/display/mac/display_link_mac.h"
 #include "ui/views/cocoa/drag_drop_client_mac.h"
+#include "ui/views/cocoa/native_widget_mac_event_monitor.h"
 #include "ui/views/views_export.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_observer.h"
@@ -44,6 +46,7 @@
 namespace views {
 
 class NativeWidgetMac;
+class NativeWidgetMacEventMonitor;
 class TextInputHost;
 
 // The portion of NativeWidgetMac that lives in the browser process. This
@@ -221,6 +224,15 @@
   bool IsWindowKey() const { return is_window_key_; }
   bool IsMouseCaptureActive() const { return is_mouse_capture_active_; }
 
+  // Add a NSEvent local event monitor, which will send events to `client`
+  // before they are dispatched to their ordinary target. Clients may specify
+  // that they have handled an event, which will prevent further dispatch. All
+  // clients will receive all events, in the order that the clients were added,
+  // regardless of whether or not a previous client handled the event.
+  std::unique_ptr<NativeWidgetMacEventMonitor> AddEventMonitor(
+      NativeWidgetMacEventMonitor::Client* client);
+  void RemoveEventMonitor(NativeWidgetMacEventMonitor*);
+
   // Used by NativeWidgetPrivate::GetGlobalCapture.
   static NSView* GetGlobalCaptureView();
 
@@ -288,6 +300,8 @@
   bool DispatchKeyEventToMenuControllerRemote(std::unique_ptr<ui::Event> event,
                                               bool* event_swallowed,
                                               bool* event_handled) override;
+  bool DispatchMonitorEvent(std::unique_ptr<ui::Event> event,
+                            bool* event_handled) override;
   bool GetHasMenuController(bool* has_menu_controller) override;
   bool GetIsDraggableBackgroundAt(const gfx::Point& location_in_content,
                                   bool* is_draggable_background) override;
@@ -348,6 +362,8 @@
   void DispatchKeyEventToMenuControllerRemote(
       std::unique_ptr<ui::Event> event,
       DispatchKeyEventToMenuControllerRemoteCallback callback) override;
+  void DispatchMonitorEvent(std::unique_ptr<ui::Event> event,
+                            DispatchMonitorEventCallback callback) override;
   void GetHasMenuController(GetHasMenuControllerCallback callback) override;
   void GetIsDraggableBackgroundAt(
       const gfx::Point& location_in_content,
@@ -476,6 +492,10 @@
   bool is_mouse_capture_active_ = false;
   gfx::Rect window_bounds_before_fullscreen_;
 
+  // Weak pointers to event monitors for this widget. The event monitors
+  // themselves will remove themselves from this list.
+  std::list<NativeWidgetMacEventMonitor*> event_monitors_;
+
   std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
   std::unique_ptr<remote_cocoa::ScopedCGWindowID> scoped_cg_window_id_;
 
@@ -488,6 +508,8 @@
 
   mojo::AssociatedReceiver<remote_cocoa::mojom::NativeWidgetNSWindowHost>
       remote_ns_window_host_receiver_{this};
+
+  base::WeakPtrFactory<NativeWidgetMacNSWindowHost> weak_factory_;
 };
 
 }  // namespace views
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index e190295..946de81 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/base64.h"
+#include "base/containers/contains.h"
 #include "base/mac/foundation_util.h"
 #include "base/no_destructor.h"
 #include "base/strings/sys_string_conversions.h"
@@ -108,6 +109,11 @@
     bool event_swallowed = false;
     std::move(callback).Run(event_swallowed, key_event->handled());
   }
+  void DispatchMonitorEvent(std::unique_ptr<ui::Event> event,
+                            DispatchMonitorEventCallback callback) override {
+    bool event_handled = false;
+    std::move(callback).Run(event_handled);
+  }
   void GetHasMenuController(GetHasMenuControllerCallback callback) override {
     bool has_menu_controller = false;
     std::move(callback).Run(has_menu_controller);
@@ -238,7 +244,8 @@
       native_widget_mac_(owner),
       root_view_id_(remote_cocoa::GetNewNSViewId()),
       accessibility_focus_overrider_(this),
-      text_input_host_(new TextInputHost(this)) {
+      text_input_host_(new TextInputHost(this)),
+      weak_factory_(this) {
   DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
          GetIdToWidgetHostImplMap().end());
   GetIdToWidgetHostImplMap().emplace(widget_id_, this);
@@ -741,6 +748,38 @@
                           animate:NO];
 }
 
+std::unique_ptr<NativeWidgetMacEventMonitor>
+NativeWidgetMacNSWindowHost::AddEventMonitor(
+    NativeWidgetMacEventMonitor::Client* client) {
+  // Enable the local event monitor if this is the first registered monitor.
+  if (event_monitors_.empty())
+    GetNSWindowMojo()->SetLocalEventMonitorEnabled(true);
+
+  // Add the new monitor to `event_monitors_`.
+  auto* monitor = new NativeWidgetMacEventMonitor(client);
+  event_monitors_.push_back(monitor);
+
+  // Set up `monitor`'s remove closure to remove it from `event_monitors_`.
+  auto remove_lambda = [](base::WeakPtr<NativeWidgetMacNSWindowHost> weak_this,
+                          NativeWidgetMacEventMonitor* monitor) {
+    if (!weak_this)
+      return;
+    auto found = std::find(weak_this->event_monitors_.begin(),
+                           weak_this->event_monitors_.end(), monitor);
+    CHECK(found != weak_this->event_monitors_.end());
+    weak_this->event_monitors_.erase(found);
+
+    // If this was the last monitor to be removed, disable the local
+    // event monitor.
+    if (weak_this->event_monitors_.empty())
+      weak_this->GetNSWindowMojo()->SetLocalEventMonitorEnabled(false);
+  };
+  monitor->remove_closure_runner_.ReplaceClosure(
+      base::BindOnce(remove_lambda, weak_factory_.GetWeakPtr(), monitor));
+
+  return base::WrapUnique<NativeWidgetMacEventMonitor>(monitor);
+}
+
 // static
 NSView* NativeWidgetMacNSWindowHost::GetGlobalCaptureView() {
   // TODO(ccameron): This will not work across process boundaries.
@@ -880,6 +919,31 @@
   return true;
 }
 
+bool NativeWidgetMacNSWindowHost::DispatchMonitorEvent(
+    std::unique_ptr<ui::Event> event,
+    bool* event_handled) {
+  // The calls to NativeWidgetMacEventMonitorOnEvent can add or remove monitors,
+  // so take a snapshot of `event_monitors_` before making any calls.
+  auto event_monitors_snapshot = event_monitors_;
+
+  // The calls to NativeWidgetMacEventMonitorOnEvent can delete `this`. Use
+  // `weak_this` to detect that.
+  auto weak_this = weak_factory_.GetWeakPtr();
+
+  *event_handled = false;
+  for (auto* event_monitor : event_monitors_snapshot) {
+    // Ensure `event_monitor` was not removed from `event_monitors_` by a
+    // previous call to NativeWidgetMacEventMonitorOnEvent.
+    if (!base::Contains(event_monitors_, event_monitor))
+      continue;
+    event_monitor->client_->NativeWidgetMacEventMonitorOnEvent(event.get(),
+                                                               event_handled);
+    if (!weak_this)
+      return true;
+  }
+  return true;
+}
+
 bool NativeWidgetMacNSWindowHost::GetHasMenuController(
     bool* has_menu_controller) {
   MenuController* menu_controller = MenuController::GetActiveInstance();
@@ -1285,6 +1349,14 @@
   std::move(callback).Run(event_swallowed, key_event->handled());
 }
 
+void NativeWidgetMacNSWindowHost::DispatchMonitorEvent(
+    std::unique_ptr<ui::Event> event,
+    DispatchMonitorEventCallback callback) {
+  bool event_handled = false;
+  DispatchMonitorEvent(std::move(event), &event_handled);
+  std::move(callback).Run(event_handled);
+}
+
 void NativeWidgetMacNSWindowHost::GetHasMenuController(
     GetHasMenuControllerCallback callback) {
   bool has_menu_controller = false;
diff --git a/ui/views/controls/menu/menu_pre_target_handler_mac.h b/ui/views/controls/menu/menu_pre_target_handler_mac.h
index 659163b..a4eedef 100644
--- a/ui/views/controls/menu/menu_pre_target_handler_mac.h
+++ b/ui/views/controls/menu/menu_pre_target_handler_mac.h
@@ -5,15 +5,21 @@
 #ifndef UI_VIEWS_CONTROLS_MENU_MENU_PRE_TARGET_HANDLER_MAC_H_
 #define UI_VIEWS_CONTROLS_MENU_MENU_PRE_TARGET_HANDLER_MAC_H_
 
+#include <memory>
+
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
 #include "ui/views/controls/menu/menu_pre_target_handler.h"
 
-#include "ui/base/cocoa/weak_ptr_nsobject.h"
+namespace ui {
+class Event;
+}  // namespace ui
 
 namespace views {
 
 // Stops dispatch of key events when they are handled by MenuController.
 // While similar to EventMonitorMac, that class does not allow dispatch changes.
-class MenuPreTargetHandlerMac : public MenuPreTargetHandler {
+class MenuPreTargetHandlerMac : public MenuPreTargetHandler,
+                                public NativeWidgetMacEventMonitor::Client {
  public:
   MenuPreTargetHandlerMac(MenuController* controller, Widget* widget);
 
@@ -23,9 +29,12 @@
   ~MenuPreTargetHandlerMac() override;
 
  private:
-  MenuController* controller_;  // Weak. Owns |this|.
-  id monitor_;
-  ui::WeakPtrNSObjectFactory<MenuPreTargetHandlerMac> factory_;
+  // public:
+  void NativeWidgetMacEventMonitorOnEvent(ui::Event* event,
+                                          bool* was_handled) final;
+
+  std::unique_ptr<NativeWidgetMacEventMonitor> monitor_;
+  MenuController* const controller_;  // Weak. Owns |this|.
 };
 
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_pre_target_handler_mac.mm b/ui/views/controls/menu/menu_pre_target_handler_mac.mm
index 4308b8cd..650c9d56 100644
--- a/ui/views/controls/menu/menu_pre_target_handler_mac.mm
+++ b/ui/views/controls/menu/menu_pre_target_handler_mac.mm
@@ -8,6 +8,7 @@
 
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
 #include "ui/views/controls/menu/menu_controller.h"
 #include "ui/views/widget/widget.h"
 
@@ -15,35 +16,25 @@
 
 MenuPreTargetHandlerMac::MenuPreTargetHandlerMac(MenuController* controller,
                                                  Widget* widget)
-    : controller_(controller), factory_(this) {
+    : controller_(controller) {
   gfx::NativeWindow target_window = widget->GetNativeWindow();
-
-  // Capture a WeakPtr via NSObject. This allows the block to detect another
-  // event monitor for the same event deleting |this|.
-  WeakPtrNSObject* handle = factory_.handle();
-
-  auto block = ^NSEvent*(NSEvent* event) {
-    if (!ui::WeakPtrNSObjectFactory<MenuPreTargetHandlerMac>::Get(handle))
-      return event;
-
-    if (!target_window || [event window] == target_window.GetNativeNSWindow()) {
-      std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event);
-      if (ui_event && ui_event->IsKeyEvent() &&
-          controller_->OnWillDispatchKeyEvent(ui_event->AsKeyEvent()) !=
-              ui::POST_DISPATCH_PERFORM_DEFAULT) {
-        // Return nil so the event will not proceed through normal dispatch.
-        return nil;
-      }
-    }
-    return event;
-  };
-
-  monitor_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
-                                                   handler:block];
+  auto* host =
+      views::NativeWidgetMacNSWindowHost::GetFromNativeWindow(target_window);
+  CHECK(host);
+  monitor_ = host->AddEventMonitor(this);
 }
 
-MenuPreTargetHandlerMac::~MenuPreTargetHandlerMac() {
-  [NSEvent removeMonitor:monitor_];
+MenuPreTargetHandlerMac::~MenuPreTargetHandlerMac() = default;
+
+void MenuPreTargetHandlerMac::NativeWidgetMacEventMonitorOnEvent(
+    ui::Event* ui_event,
+    bool* was_handled) {
+  if (*was_handled)
+    return;
+  if (!ui_event->IsKeyEvent())
+    return;
+  *was_handled = controller_->OnWillDispatchKeyEvent(ui_event->AsKeyEvent()) !=
+                 ui::POST_DISPATCH_PERFORM_DEFAULT;
 }
 
 // static
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts b/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts
index 73c12f6..2480e9d2 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.m.d.ts
@@ -20,8 +20,8 @@
   inputmode: string|null|undefined;
   label: string|null|undefined;
   placeholder: string|null;
-  readonly: boolean|null|undefined;
-  required: boolean|null|undefined;
+  readonly: boolean|undefined;
+  required: boolean|undefined;
   tabindex: number|null;
   type: string|null|undefined;
   value: string;