diff --git a/BUILD.gn b/BUILD.gn
index 7169f53..8f14d13 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -197,7 +197,6 @@
       "//gpu:gpu_unittests",
       "//ipc:ipc_tests",
       "//media:media_unittests",
-      "//media/blink:media_blink_unittests",
       "//media/midi:midi_unittests",
       "//media/mojo:media_mojo_unittests",
       "//mojo",
diff --git a/DEPS b/DEPS
index df17d94..277fdf2 100644
--- a/DEPS
+++ b/DEPS
@@ -217,11 +217,11 @@
   # 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': '8f9f763ec510c3c510b1de8b63cf89089953c5e7',
+  'skia_revision': 'be03ef156568dc0b6e6c00d5c53a42f7d6a637cf',
   # 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': '676b039f932a490af484d2dfb018c460e4c4fde8',
+  'v8_revision': 'ecaad7f89fd5f1cc2b4a55adaee0831fed330eb6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -229,7 +229,7 @@
   # 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': '9c5009519cbd61ebca30912818e3a13769fb6274',
+  'angle_revision': '33b5ff4c4a1998b6af7f03b7a7937f8ebbb3cccf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -288,7 +288,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '70bf08ecdba10a3d8578c62a81044b3f70d6afe4',
+  'catapult_revision': '96bc38d7d5073ed80b2cb41325d07da67051f776',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -336,7 +336,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': 'ff7eb1641e92a39357e2895361d18e73d011de24',
+  'dawn_revision': 'cd417bc9a1fb555b6b89e370ad685b15fc77098d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -969,7 +969,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '592d5ec077c9cbd999bc80de08eaab67489064b0',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '74ef838a40d8fecac485416f1a1fb07f9aeb6fd1',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1444,7 +1444,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'D99f9rA6SsUg1U4VGdh-MSQQX94eeW2Mi8I_xw6-ccwC'
+              'version': 'xHK1AABg-PLOiW8AceE-Bl6-257z_-pCNPjMgEQM5owC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1648,7 +1648,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@12043255d16ef30071b793bc2c6cfeae8fd08056',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0d2d1fe16b11bb3a79341acf06ea69b1dcf043f3',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index da10b00..810c317 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1271,7 +1271,6 @@
     },
     'media_remoting': {
       'filepath': 'chrome/browser/media/cast_remoting'\
-                  '|media/blink/webmediaplayer_'\
                   '|media/mojo/mojom/remoting.mojom'\
                   '|media/remoting/'\
                   '|third_party/blink/public/platform/media/web_media_player_'\
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index ff05f65..e3d841b 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -37,7 +37,8 @@
     # TODO: move the following to source. Do NOT add new files here.
     "accessibility/accessibility_controller_impl.h",
     "accessibility/accessibility_delegate.h",
-    "accessibility/magnifier/full_screen_magnifier_controller.h",
+    "accessibility/magnifier/docked_magnifier_controller.h",
+    "accessibility/magnifier/fullscreen_magnifier_controller.h",
     "accessibility/sticky_keys/sticky_keys_controller.h",
     "accessibility/ui/focus_ring_controller.h",
     "clipboard/clipboard_history_controller_impl.h",
@@ -58,7 +59,6 @@
     "public/cpp/capture_mode_delegate.h",
     "public/cpp/capture_mode_test_api.h",
     "public/cpp/debug_utils.h",
-    "public/cpp/docked_magnifier_controller.h",
     "public/cpp/event_rewriter_controller.h",
     "public/cpp/multi_user_window_manager.h",
     "public/cpp/multi_user_window_manager_delegate.h",
@@ -164,10 +164,10 @@
     "accessibility/chromevox/touch_exploration_manager.h",
     "accessibility/default_accessibility_delegate.cc",
     "accessibility/default_accessibility_delegate.h",
-    "accessibility/magnifier/docked_magnifier_controller_impl.cc",
-    "accessibility/magnifier/docked_magnifier_controller_impl.h",
-    "accessibility/magnifier/full_screen_magnifier_controller.cc",
-    "accessibility/magnifier/full_screen_magnifier_controller.h",
+    "accessibility/magnifier/docked_magnifier_controller.cc",
+    "accessibility/magnifier/docked_magnifier_controller.h",
+    "accessibility/magnifier/fullscreen_magnifier_controller.cc",
+    "accessibility/magnifier/fullscreen_magnifier_controller.h",
     "accessibility/magnifier/magnifier_glass.cc",
     "accessibility/magnifier/magnifier_glass.h",
     "accessibility/magnifier/magnifier_utils.cc",
@@ -1589,6 +1589,8 @@
     "wm/event_client_impl.h",
     "wm/full_restore/full_restore_controller.cc",
     "wm/full_restore/full_restore_controller.h",
+    "wm/full_restore/full_restore_util.cc",
+    "wm/full_restore/full_restore_util.h",
     "wm/fullscreen_window_finder.cc",
     "wm/fullscreen_window_finder.h",
     "wm/gestures/back_gesture/back_gesture_affordance.cc",
@@ -2052,8 +2054,8 @@
     "accessibility/chromevox/touch_accessibility_enabler_unittest.cc",
     "accessibility/chromevox/touch_exploration_controller_unittest.cc",
     "accessibility/chromevox/touch_exploration_manager_unittest.cc",
-    "accessibility/magnifier/docked_magnifier_controller_impl_unittest.cc",
-    "accessibility/magnifier/full_screen_magnifier_controller_unittest.cc",
+    "accessibility/magnifier/docked_magnifier_controller_unittest.cc",
+    "accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc",
     "accessibility/magnifier/magnifier_test_utils.cc",
     "accessibility/magnifier/magnifier_test_utils.h",
     "accessibility/magnifier/magnifier_utils_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index 0f03081c3..542b229 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -12,8 +12,8 @@
 #include "ash/accelerators/accelerator_commands.h"
 #include "ash/accelerators/debug_commands.h"
 #include "ash/accessibility/accessibility_controller_impl.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/ui/accessibility_confirmation_dialog.h"
 #include "ash/ambient/ambient_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
@@ -1436,7 +1436,7 @@
     return;
   }
 
-  DockedMagnifierControllerImpl* docked_magnifier_controller =
+  DockedMagnifierController* docked_magnifier_controller =
       shell->docked_magnifier_controller();
   AccessibilityControllerImpl* accessibility_controller =
       shell->accessibility_controller();
@@ -1475,7 +1475,7 @@
   shell->accessibility_controller()->fullscreen_magnifier().SetEnabled(enabled);
 
   RemoveStickyNotitification(kFullscreenMagnifierToggleAccelNotificationId);
-  if (shell->full_screen_magnifier_controller()->IsEnabled()) {
+  if (shell->fullscreen_magnifier_controller()->IsEnabled()) {
     CreateAndShowStickyNotification(
         IDS_FULLSCREEN_MAGNIFIER_ACCEL_TITLE,
         IDS_FULLSCREEN_MAGNIFIER_ACCEL_MSG,
@@ -1557,13 +1557,13 @@
   if (!is_shortcut_enabled) {
     NotifyAccessibilityFeatureDisabledByAdmin(
         IDS_ASH_FULLSCREEN_MAGNIFIER_SHORTCUT_DISABLED,
-        shell->full_screen_magnifier_controller()->IsEnabled(),
+        shell->fullscreen_magnifier_controller()->IsEnabled(),
         kFullscreenMagnifierToggleAccelNotificationId);
     return;
   }
 
-  FullScreenMagnifierController* magnification_controller =
-      shell->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnification_controller =
+      shell->fullscreen_magnifier_controller();
   AccessibilityControllerImpl* accessibility_controller =
       shell->accessibility_controller();
 
@@ -1670,14 +1670,14 @@
 }
 
 bool CanHandleActiveMagnifierZoom() {
-  return Shell::Get()->full_screen_magnifier_controller()->IsEnabled() ||
+  return Shell::Get()->fullscreen_magnifier_controller()->IsEnabled() ||
          Shell::Get()->docked_magnifier_controller()->GetEnabled();
 }
 
 // Change the scale of the active magnifier.
 void HandleActiveMagnifierZoom(int delta_index) {
-  if (Shell::Get()->full_screen_magnifier_controller()->IsEnabled()) {
-    Shell::Get()->full_screen_magnifier_controller()->StepToNextScaleValue(
+  if (Shell::Get()->fullscreen_magnifier_controller()->IsEnabled()) {
+    Shell::Get()->fullscreen_magnifier_controller()->StepToNextScaleValue(
         delta_index);
     return;
   }
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index be2abd2..367e666 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -10,8 +10,8 @@
 #include "ash/accelerators/accelerator_table.h"
 #include "ash/accelerators/pre_target_accelerator_handler.h"
 #include "ash/accessibility/accessibility_controller_impl.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/accessibility/ui/accessibility_confirmation_dialog.h"
 #include "ash/app_list/app_list_metrics.h"
@@ -2594,12 +2594,12 @@
   MagnifiersAcceleratorsTester() = default;
   ~MagnifiersAcceleratorsTester() override = default;
 
-  DockedMagnifierControllerImpl* docked_magnifier_controller() const {
+  DockedMagnifierController* docked_magnifier_controller() const {
     return Shell::Get()->docked_magnifier_controller();
   }
 
-  FullScreenMagnifierController* fullscreen_magnifier_controller() const {
-    return Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* fullscreen_magnifier_controller() const {
+    return Shell::Get()->fullscreen_magnifier_controller();
   }
 
   PrefService* user_pref_service() {
@@ -2635,7 +2635,7 @@
   }
 
   void UpdateMagnifierFromPrefs() {
-    Shell::Get()->full_screen_magnifier_controller()->SetEnabled(
+    Shell::Get()->fullscreen_magnifier_controller()->SetEnabled(
         prefs_->GetBoolean(prefs::kAccessibilityScreenMagnifierEnabled));
   }
 
diff --git a/ash/accelerators/ash_focus_manager_factory.cc b/ash/accelerators/ash_focus_manager_factory.cc
index 0b2fd45..199ab7be 100644
--- a/ash/accelerators/ash_focus_manager_factory.cc
+++ b/ash/accelerators/ash_focus_manager_factory.cc
@@ -7,8 +7,8 @@
 #include <memory>
 
 #include "ash/accelerators/accelerator_controller_impl.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/shell.h"
 #include "ui/base/ime/text_input_client.h"
 #include "ui/views/focus/focus_manager.h"
@@ -52,10 +52,10 @@
     return;
 
   // Note that both magnifiers are mutually exclusive.
-  DockedMagnifierControllerImpl* docked_magnifier =
+  DockedMagnifierController* docked_magnifier =
       Shell::Get()->docked_magnifier_controller();
-  FullScreenMagnifierController* fullscreen_magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* fullscreen_magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   gfx::Point point_of_interest = bounds_in_screen.CenterPoint();
   const ui::InputMethod* input_method = focused_now->GetInputMethod();
diff --git a/ash/accelerators/magnifier_key_scroller.cc b/ash/accelerators/magnifier_key_scroller.cc
index afb7278..2de05963 100644
--- a/ash/accelerators/magnifier_key_scroller.cc
+++ b/ash/accelerators/magnifier_key_scroller.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "ash/accelerators/key_hold_detector.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/keyboard/keyboard_util.h"
 #include "ash/shell.h"
@@ -25,7 +25,7 @@
       switches::kAshEnableMagnifierKeyScroller);
 
   return (magnifier_key_scroller_enabled || has_switch) &&
-         Shell::Get()->full_screen_magnifier_controller()->IsEnabled();
+         Shell::Get()->fullscreen_magnifier_controller()->IsEnabled();
 }
 
 // static
@@ -55,23 +55,23 @@
 }
 
 void MagnifierKeyScroller::OnKeyHold(const ui::KeyEvent* event) {
-  FullScreenMagnifierController* controller =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* controller =
+      Shell::Get()->fullscreen_magnifier_controller();
   switch (event->key_code()) {
     case ui::VKEY_UP:
-      controller->SetScrollDirection(FullScreenMagnifierController::SCROLL_UP);
+      controller->SetScrollDirection(FullscreenMagnifierController::SCROLL_UP);
       break;
     case ui::VKEY_DOWN:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_DOWN);
+          FullscreenMagnifierController::SCROLL_DOWN);
       break;
     case ui::VKEY_LEFT:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_LEFT);
+          FullscreenMagnifierController::SCROLL_LEFT);
       break;
     case ui::VKEY_RIGHT:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_RIGHT);
+          FullscreenMagnifierController::SCROLL_RIGHT);
       break;
     default:
       NOTREACHED() << "Unknown keyboard_code:" << event->key_code();
@@ -79,9 +79,9 @@
 }
 
 void MagnifierKeyScroller::OnKeyUnhold(const ui::KeyEvent* event) {
-  FullScreenMagnifierController* controller =
-      Shell::Get()->full_screen_magnifier_controller();
-  controller->SetScrollDirection(FullScreenMagnifierController::SCROLL_NONE);
+  FullscreenMagnifierController* controller =
+      Shell::Get()->fullscreen_magnifier_controller();
+  controller->SetScrollDirection(FullscreenMagnifierController::SCROLL_NONE);
 }
 
 MagnifierKeyScroller::MagnifierKeyScroller() = default;
diff --git a/ash/accelerators/magnifier_key_scroller_unittest.cc b/ash/accelerators/magnifier_key_scroller_unittest.cc
index c35d96a0..f06acce9 100644
--- a/ash/accelerators/magnifier_key_scroller_unittest.cc
+++ b/ash/accelerators/magnifier_key_scroller_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_util.h"
@@ -49,8 +49,8 @@
   wm::ActivateWindow(window.get());
 
   MagnifierKeyScroller::ScopedEnablerForTest scoped;
-  FullScreenMagnifierController* controller =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* controller =
+      Shell::Get()->fullscreen_magnifier_controller();
   controller->SetEnabled(true);
 
   EXPECT_EQ("200,150", controller->GetWindowPosition().ToString());
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc
index 941687d4..baf017d9 100644
--- a/ash/accessibility/accessibility_controller_unittest.cc
+++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -8,7 +8,7 @@
 #include <utility>
 
 #include "ash/accessibility/accessibility_observer.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/accessibility/sticky_keys/sticky_keys_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/constants/ash_constants.h"
@@ -1054,7 +1054,7 @@
 
   AccessibilityControllerImpl* accessibility =
       Shell::Get()->accessibility_controller();
-  DockedMagnifierControllerImpl* docked_magnifier =
+  DockedMagnifierController* docked_magnifier =
       Shell::Get()->docked_magnifier_controller();
 
   SessionControllerImpl* session = Shell::Get()->session_controller();
diff --git a/ash/accessibility/magnifier/DEPS b/ash/accessibility/magnifier/DEPS
index a4d7111..1f3a5f8 100644
--- a/ash/accessibility/magnifier/DEPS
+++ b/ash/accessibility/magnifier/DEPS
@@ -1,8 +1,8 @@
 specific_include_rules = {
-  "full_screen_magnifier_controller\.cc": [
+  "fullscreen_magnifier_controller\.cc": [
     "+ash/host"
   ],
-  "docked_magnifier_controller_impl.*\.cc": [
+  "docked_magnifier_controller.*\.cc": [
     "+ash/host"
   ],
 }
diff --git a/ash/accessibility/magnifier/docked_magnifier_controller_impl.cc b/ash/accessibility/magnifier/docked_magnifier_controller.cc
similarity index 89%
rename from ash/accessibility/magnifier/docked_magnifier_controller_impl.cc
rename to ash/accessibility/magnifier/docked_magnifier_controller.cc
index 95bd19e9..2216d45f 100644
--- a/ash/accessibility/magnifier/docked_magnifier_controller_impl.cc
+++ b/ash/accessibility/magnifier/docked_magnifier_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 
 #include <algorithm>
 #include <utility>
@@ -77,7 +77,7 @@
 
   auto root_bounds = root->GetBoundsInRootWindow();
   root_bounds.set_height(root_bounds.height() /
-                         DockedMagnifierControllerImpl::kScreenHeightDivisor);
+                         DockedMagnifierController::kScreenHeightDivisor);
   return root_bounds;
 }
 
@@ -87,7 +87,7 @@
     const gfx::Rect& viewport_bounds) {
   return gfx::Rect(viewport_bounds.x(), viewport_bounds.bottom(),
                    viewport_bounds.width(),
-                   DockedMagnifierControllerImpl::kSeparatorHeight);
+                   DockedMagnifierController::kSeparatorHeight);
 }
 
 // Returns the child container in |root| that should be used as the parent of
@@ -99,17 +99,13 @@
 }  // namespace
 
 // static
-DockedMagnifierController* DockedMagnifierController::Get() {
-  return Shell::Get()->docked_magnifier_controller();
-}
-
-DockedMagnifierControllerImpl::DockedMagnifierControllerImpl() {
+DockedMagnifierController::DockedMagnifierController() {
   Shell::Get()->session_controller()->AddObserver(this);
   if (ui::IMEBridge::Get())
     ui::IMEBridge::Get()->AddObserver(this);
 }
 
-DockedMagnifierControllerImpl::~DockedMagnifierControllerImpl() {
+DockedMagnifierController::~DockedMagnifierController() {
   if (input_method_)
     input_method_->RemoveObserver(this);
   input_method_ = nullptr;
@@ -127,33 +123,33 @@
 }
 
 // static
-void DockedMagnifierControllerImpl::RegisterProfilePrefs(
+void DockedMagnifierController::RegisterProfilePrefs(
     PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kDockedMagnifierEnabled, false);
   registry->RegisterDoublePref(prefs::kDockedMagnifierScale,
                                kDefaultMagnifierScale);
 }
 
-bool DockedMagnifierControllerImpl::GetEnabled() const {
+bool DockedMagnifierController::GetEnabled() const {
   return active_user_pref_service_ &&
          active_user_pref_service_->GetBoolean(prefs::kDockedMagnifierEnabled);
 }
 
-float DockedMagnifierControllerImpl::GetScale() const {
+float DockedMagnifierController::GetScale() const {
   if (active_user_pref_service_)
     return active_user_pref_service_->GetDouble(prefs::kDockedMagnifierScale);
 
   return kDefaultMagnifierScale;
 }
 
-void DockedMagnifierControllerImpl::SetEnabled(bool enabled) {
+void DockedMagnifierController::SetEnabled(bool enabled) {
   if (active_user_pref_service_) {
     active_user_pref_service_->SetBoolean(prefs::kDockedMagnifierEnabled,
                                           enabled);
   }
 }
 
-void DockedMagnifierControllerImpl::SetScale(float scale) {
+void DockedMagnifierController::SetScale(float scale) {
   if (active_user_pref_service_) {
     active_user_pref_service_->SetDouble(
         prefs::kDockedMagnifierScale,
@@ -161,12 +157,12 @@
   }
 }
 
-void DockedMagnifierControllerImpl::StepToNextScaleValue(int delta_index) {
+void DockedMagnifierController::StepToNextScaleValue(int delta_index) {
   SetScale(magnifier_utils::GetNextMagnifierScaleValue(
       delta_index, GetScale(), kMinMagnifierScale, kMaxMagnifierScale));
 }
 
-void DockedMagnifierControllerImpl::MoveMagnifierToRect(
+void DockedMagnifierController::MoveMagnifierToRect(
     const gfx::Rect& rect_in_screen) {
   DCHECK(GetEnabled());
   last_move_magnifier_to_rect_ = base::TimeTicks::Now();
@@ -187,7 +183,7 @@
   CenterOnPoint(point_in_screen);
 }
 
-void DockedMagnifierControllerImpl::CenterOnPoint(
+void DockedMagnifierController::CenterOnPoint(
     const gfx::Point& point_in_screen) {
   if (!GetEnabled())
     return;
@@ -254,27 +250,27 @@
   viewport_magnifier_layer_->SetTransform(transform);
 }
 
-int DockedMagnifierControllerImpl::GetMagnifierHeightForTesting() const {
+int DockedMagnifierController::GetMagnifierHeightForTesting() const {
   return GetTotalMagnifierHeight();
 }
 
-void DockedMagnifierControllerImpl::OnActiveUserPrefServiceChanged(
+void DockedMagnifierController::OnActiveUserPrefServiceChanged(
     PrefService* pref_service) {
   active_user_pref_service_ = pref_service;
   InitFromUserPrefs();
 }
 
-void DockedMagnifierControllerImpl::OnSigninScreenPrefServiceInitialized(
+void DockedMagnifierController::OnSigninScreenPrefServiceInitialized(
     PrefService* prefs) {
   OnActiveUserPrefServiceChanged(prefs);
 }
 
-void DockedMagnifierControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
+void DockedMagnifierController::OnMouseEvent(ui::MouseEvent* event) {
   DCHECK(GetEnabled());
   CenterOnPoint(GetCursorScreenPoint());
 }
 
-void DockedMagnifierControllerImpl::OnScrollEvent(ui::ScrollEvent* event) {
+void DockedMagnifierController::OnScrollEvent(ui::ScrollEvent* event) {
   DCHECK(GetEnabled());
   if (!event->IsAltDown() || !event->IsControlDown())
     return;
@@ -296,7 +292,7 @@
   }
 }
 
-void DockedMagnifierControllerImpl::OnTouchEvent(ui::TouchEvent* event) {
+void DockedMagnifierController::OnTouchEvent(ui::TouchEvent* event) {
   DCHECK(GetEnabled());
 
   aura::Window* target = static_cast<aura::Window*>(event->target());
@@ -306,7 +302,7 @@
   CenterOnPoint(event_screen_point);
 }
 
-void DockedMagnifierControllerImpl::OnInputContextHandlerChanged() {
+void DockedMagnifierController::OnInputContextHandlerChanged() {
   if (!GetEnabled())
     return;
 
@@ -322,14 +318,14 @@
     input_method_->AddObserver(this);
 }
 
-void DockedMagnifierControllerImpl::OnInputMethodDestroyed(
+void DockedMagnifierController::OnInputMethodDestroyed(
     const ui::InputMethod* input_method) {
   DCHECK_EQ(input_method, input_method_);
   input_method_->RemoveObserver(this);
   input_method_ = nullptr;
 }
 
-void DockedMagnifierControllerImpl::OnCaretBoundsChanged(
+void DockedMagnifierController::OnCaretBoundsChanged(
     const ui::TextInputClient* client) {
   if (!GetEnabled()) {
     // There is a small window between the time the "enabled" pref is updated to
@@ -362,17 +358,17 @@
   last_caret_screen_point_ = caret_screen_bounds.CenterPoint();
   move_magnifier_timer_.Start(
       FROM_HERE, kMoveMagnifierCaretDelay, this,
-      &DockedMagnifierControllerImpl::OnMoveMagnifierTimer);
+      &DockedMagnifierController::OnMoveMagnifierTimer);
 }
 
-void DockedMagnifierControllerImpl::OnWidgetDestroying(views::Widget* widget) {
+void DockedMagnifierController::OnWidgetDestroying(views::Widget* widget) {
   DCHECK_EQ(widget, viewport_widget_);
 
   SwitchCurrentSourceRootWindowIfNeeded(nullptr,
                                         false /* update_old_root_workarea */);
 }
 
-void DockedMagnifierControllerImpl::OnDisplayConfigurationChanged() {
+void DockedMagnifierController::OnDisplayConfigurationChanged() {
   DCHECK(GetEnabled());
 
   // The viewport might have been on a display that just got removed, and hence
@@ -403,13 +399,13 @@
   CenterOnPoint(GetCursorScreenPoint());
 }
 
-bool DockedMagnifierControllerImpl::GetFullscreenMagnifierEnabled() const {
+bool DockedMagnifierController::GetFullscreenMagnifierEnabled() const {
   return active_user_pref_service_ &&
          active_user_pref_service_->GetBoolean(
              prefs::kAccessibilityScreenMagnifierEnabled);
 }
 
-void DockedMagnifierControllerImpl::SetFullscreenMagnifierEnabled(
+void DockedMagnifierController::SetFullscreenMagnifierEnabled(
     bool enabled) {
   if (active_user_pref_service_) {
     active_user_pref_service_->SetBoolean(
@@ -417,7 +413,7 @@
   }
 }
 
-int DockedMagnifierControllerImpl::GetTotalMagnifierHeight() const {
+int DockedMagnifierController::GetTotalMagnifierHeight() const {
   if (separator_layer_)
     return separator_layer_->bounds().bottom();
 
@@ -425,26 +421,26 @@
 }
 
 const views::Widget*
-DockedMagnifierControllerImpl::GetViewportWidgetForTesting() const {
+DockedMagnifierController::GetViewportWidgetForTesting() const {
   return viewport_widget_;
 }
 
 const ui::Layer*
-DockedMagnifierControllerImpl::GetViewportMagnifierLayerForTesting() const {
+DockedMagnifierController::GetViewportMagnifierLayerForTesting() const {
   return viewport_magnifier_layer_.get();
 }
 
-float DockedMagnifierControllerImpl::GetMinimumPointOfInterestHeightForTesting()
+float DockedMagnifierController::GetMinimumPointOfInterestHeightForTesting()
     const {
   return minimum_point_of_interest_height_;
 }
 
-gfx::Point DockedMagnifierControllerImpl::GetLastCaretScreenPointForTesting()
+gfx::Point DockedMagnifierController::GetLastCaretScreenPointForTesting()
     const {
   return last_caret_screen_point_;
 }
 
-void DockedMagnifierControllerImpl::SwitchCurrentSourceRootWindowIfNeeded(
+void DockedMagnifierController::SwitchCurrentSourceRootWindowIfNeeded(
     aura::Window* new_root_window,
     bool update_old_root_workarea) {
   if (current_source_root_window_ == new_root_window)
@@ -503,29 +499,29 @@
       magnified_container->layer());
 }
 
-void DockedMagnifierControllerImpl::InitFromUserPrefs() {
+void DockedMagnifierController::InitFromUserPrefs() {
   DCHECK(active_user_pref_service_);
 
   pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
   pref_change_registrar_->Init(active_user_pref_service_);
   pref_change_registrar_->Add(
       prefs::kDockedMagnifierEnabled,
-      base::BindRepeating(&DockedMagnifierControllerImpl::OnEnabledPrefChanged,
+      base::BindRepeating(&DockedMagnifierController::OnEnabledPrefChanged,
                           base::Unretained(this)));
   pref_change_registrar_->Add(
       prefs::kDockedMagnifierScale,
-      base::BindRepeating(&DockedMagnifierControllerImpl::OnScalePrefChanged,
+      base::BindRepeating(&DockedMagnifierController::OnScalePrefChanged,
                           base::Unretained(this)));
   pref_change_registrar_->Add(
       prefs::kAccessibilityScreenMagnifierEnabled,
-      base::BindRepeating(&DockedMagnifierControllerImpl::
+      base::BindRepeating(&DockedMagnifierController::
                               OnFullscreenMagnifierEnabledPrefChanged,
                           base::Unretained(this)));
 
   OnEnabledPrefChanged();
 }
 
-void DockedMagnifierControllerImpl::OnEnabledPrefChanged() {
+void DockedMagnifierController::OnEnabledPrefChanged() {
   // When switching from the signin screen to a newly created profile while the
   // Docked Magnifier is enabled, the prefs will be copied from the signin
   // profile to the user profile, and the Docked Magnifier will remain enabled.
@@ -586,7 +582,7 @@
   shell->UpdateCursorCompositingEnabled();
 }
 
-void DockedMagnifierControllerImpl::OnScalePrefChanged() {
+void DockedMagnifierController::OnScalePrefChanged() {
   if (GetEnabled()) {
     // Invalidate the cached minimum height of the point of interest since the
     // change in scale changes that height.
@@ -595,18 +591,18 @@
   }
 }
 
-void DockedMagnifierControllerImpl::OnFullscreenMagnifierEnabledPrefChanged() {
+void DockedMagnifierController::OnFullscreenMagnifierEnabledPrefChanged() {
   // Enabling the Fullscreen Magnifier disables the Docked Magnifier.
   if (GetFullscreenMagnifierEnabled())
     SetEnabled(false);
 }
 
-void DockedMagnifierControllerImpl::Refresh() {
+void DockedMagnifierController::Refresh() {
   DCHECK(GetEnabled());
   CenterOnPoint(GetCursorScreenPoint());
 }
 
-void DockedMagnifierControllerImpl::CreateMagnifierViewport() {
+void DockedMagnifierController::CreateMagnifierViewport() {
   DCHECK(GetEnabled());
   DCHECK(current_source_root_window_);
 
@@ -674,7 +670,7 @@
   viewport_widget_->Show();
 }
 
-void DockedMagnifierControllerImpl::MaybeCachePointOfInterestMinimumHeight(
+void DockedMagnifierController::MaybeCachePointOfInterestMinimumHeight(
     aura::WindowTreeHost* host) {
   DCHECK(GetEnabled());
   DCHECK(current_source_root_window_);
@@ -759,7 +755,7 @@
   is_minimum_point_of_interest_height_valid_ = true;
 }
 
-void DockedMagnifierControllerImpl::ConfineMouseCursorOutsideViewport() {
+void DockedMagnifierController::ConfineMouseCursorOutsideViewport() {
   DCHECK(current_source_root_window_);
 
   gfx::Rect confine_bounds =
@@ -772,7 +768,7 @@
       ->ConfineCursorToBoundsInRoot(confine_bounds);
 }
 
-void DockedMagnifierControllerImpl::OnMoveMagnifierTimer() {
+void DockedMagnifierController::OnMoveMagnifierTimer() {
   // Ignore caret changes while move magnifier to rect activity is occurring.
   if (base::TimeTicks::Now() - last_move_magnifier_to_rect_ <
       magnifier_utils::kPauseCaretUpdateDuration) {
diff --git a/ash/accessibility/magnifier/docked_magnifier_controller_impl.h b/ash/accessibility/magnifier/docked_magnifier_controller.h
similarity index 92%
rename from ash/accessibility/magnifier/docked_magnifier_controller_impl.h
rename to ash/accessibility/magnifier/docked_magnifier_controller.h
index 3ccbba1..9346c55 100644
--- a/ash/accessibility/magnifier/docked_magnifier_controller_impl.h
+++ b/ash/accessibility/magnifier/docked_magnifier_controller.h
@@ -2,14 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_ACCESSIBILITY_MAGNIFIER_DOCKED_MAGNIFIER_CONTROLLER_IMPL_H_
-#define ASH_ACCESSIBILITY_MAGNIFIER_DOCKED_MAGNIFIER_CONTROLLER_IMPL_H_
+#ifndef ASH_ACCESSIBILITY_MAGNIFIER_DOCKED_MAGNIFIER_CONTROLLER_H_
+#define ASH_ACCESSIBILITY_MAGNIFIER_DOCKED_MAGNIFIER_CONTROLLER_H_
 
 #include <memory>
 
 #include "ash/ash_export.h"
 #include "ash/display/window_tree_host_manager.h"
-#include "ash/public/cpp/docked_magnifier_controller.h"
 #include "ash/public/cpp/session/session_observer.h"
 #include "ui/base/ime/chromeos/ime_bridge_observer.h"
 #include "ui/base/ime/input_method_observer.h"
@@ -41,17 +40,16 @@
 // (which follows the cursor location, text input caret location, or focus
 // changes). In a multiple display scenario, the magnifier viewport is located
 // on the same display as that of the point of interest.
-class ASH_EXPORT DockedMagnifierControllerImpl
-    : public DockedMagnifierController,
-      public SessionObserver,
+class ASH_EXPORT DockedMagnifierController
+    : public SessionObserver,
       public ui::EventHandler,
       public ui::IMEBridgeObserver,
       public ui::InputMethodObserver,
       public views::WidgetObserver,
       public WindowTreeHostManager::Observer {
  public:
-  DockedMagnifierControllerImpl();
-  ~DockedMagnifierControllerImpl() override;
+  DockedMagnifierController();
+  ~DockedMagnifierController() override;
 
   // The height of the black separator layer between the magnifier viewport and
   // the rest of the screen.
@@ -76,10 +74,9 @@
   // value of |delta_index|.
   void StepToNextScaleValue(int delta_index);
 
-  // DockedMagnifierController:
-  void CenterOnPoint(const gfx::Point& point_in_screen) override;
-  void MoveMagnifierToRect(const gfx::Rect& rect_in_screen) override;
-  int GetMagnifierHeightForTesting() const override;
+  void CenterOnPoint(const gfx::Point& point_in_screen);
+  void MoveMagnifierToRect(const gfx::Rect& rect_in_screen);
+  int GetMagnifierHeightForTesting() const;
 
   // ash::SessionObserver:
   void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
@@ -221,9 +218,9 @@
   // few milliseconds after the last move magnifier to rect call.
   base::TimeTicks last_move_magnifier_to_rect_;
 
-  DISALLOW_COPY_AND_ASSIGN(DockedMagnifierControllerImpl);
+  DISALLOW_COPY_AND_ASSIGN(DockedMagnifierController);
 };
 
 }  // namespace ash
 
-#endif  // ASH_ACCESSIBILITY_MAGNIFIER_DOCKED_MAGNIFIER_CONTROLLER_IMPL_H_
+#endif  // ASH_ACCESSIBILITY_MAGNIFIER_docked_magnifier_controller_H_
diff --git a/ash/accessibility/magnifier/docked_magnifier_controller_impl_unittest.cc b/ash/accessibility/magnifier/docked_magnifier_controller_unittest.cc
similarity index 97%
rename from ash/accessibility/magnifier/docked_magnifier_controller_impl_unittest.cc
rename to ash/accessibility/magnifier/docked_magnifier_controller_unittest.cc
index d3da89a..45f6f25 100644
--- a/ash/accessibility/magnifier/docked_magnifier_controller_impl_unittest.cc
+++ b/ash/accessibility/magnifier/docked_magnifier_controller_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 
 #include <memory>
 #include <vector>
@@ -53,8 +53,8 @@
 // Returns the magnifier area height given the display height.
 int GetMagnifierHeight(int display_height) {
   return (display_height /
-          DockedMagnifierControllerImpl::kScreenHeightDivisor) +
-         DockedMagnifierControllerImpl::kSeparatorHeight;
+          DockedMagnifierController::kScreenHeightDivisor) +
+         DockedMagnifierController::kSeparatorHeight;
 }
 
 class DockedMagnifierTest : public NoSessionAshTestBase {
@@ -62,7 +62,7 @@
   DockedMagnifierTest() = default;
   ~DockedMagnifierTest() override = default;
 
-  DockedMagnifierControllerImpl* controller() const {
+  DockedMagnifierController* controller() const {
     return Shell::Get()->docked_magnifier_controller();
   }
 
@@ -345,7 +345,7 @@
 }
 
 // Tests that updates of the Docked Magnifier user prefs from outside the
-// DockedMagnifierControllerImpl (such as Settings UI) are observed and applied.
+// DockedMagnifierController (such as Settings UI) are observed and applied.
 TEST_F(DockedMagnifierTest, TestOutsidePrefsUpdates) {
   EXPECT_FALSE(controller()->GetEnabled());
   user1_pref_service()->SetBoolean(prefs::kDockedMagnifierEnabled, true);
@@ -684,7 +684,7 @@
   ASSERT_NE(nullptr, viewport_widget);
   EXPECT_EQ(root_windows[0], viewport_widget->GetNativeView()->GetRootWindow());
   const int viewport_1_height =
-      800 / DockedMagnifierControllerImpl::kScreenHeightDivisor;
+      800 / DockedMagnifierController::kScreenHeightDivisor;
   EXPECT_EQ(gfx::Rect(0, 0, 600, viewport_1_height),
             viewport_widget->GetWindowBoundsInScreen());
 
@@ -709,7 +709,7 @@
   viewport_widget = controller()->GetViewportWidgetForTesting();
   EXPECT_EQ(root_windows[1], viewport_widget->GetNativeView()->GetRootWindow());
   const int viewport_2_height =
-      600 / DockedMagnifierControllerImpl::kScreenHeightDivisor;
+      600 / DockedMagnifierController::kScreenHeightDivisor;
   EXPECT_EQ(gfx::Rect(600, 0, 400, viewport_2_height),
             viewport_widget->GetWindowBoundsInScreen());
 
@@ -748,7 +748,7 @@
   ASSERT_NE(nullptr, viewport_widget);
   EXPECT_EQ(root_windows[0], viewport_widget->GetNativeView()->GetRootWindow());
   const int viewport_height =
-      800 / DockedMagnifierControllerImpl::kScreenHeightDivisor;
+      800 / DockedMagnifierController::kScreenHeightDivisor;
   EXPECT_EQ(gfx::Rect(0, 0, 800, viewport_height),
             viewport_widget->GetWindowBoundsInScreen());
 
@@ -772,7 +772,7 @@
   // separator, and it should go to the center of the top *edge* of the viewport
   // widget.
   point_of_interest.set_y(viewport_height +
-                          DockedMagnifierControllerImpl::kSeparatorHeight);
+                          DockedMagnifierController::kSeparatorHeight);
   const gfx::Point viewport_center =
       viewport_widget->GetNativeWindow()->GetBoundsInRootWindow().CenterPoint();
   gfx::Point viewport_top_edge_center = viewport_center;
@@ -785,7 +785,7 @@
   // + the height of the separator + half the height of the viewport when scaled
   // back to the non-magnified space.
   EXPECT_FLOAT_EQ(viewport_height +
-                      DockedMagnifierControllerImpl::kSeparatorHeight +
+                      DockedMagnifierController::kSeparatorHeight +
                       (viewport_center.y() / scale1),
                   controller()->GetMinimumPointOfInterestHeightForTesting());
 
@@ -797,12 +797,12 @@
   point_of_interest = gfx::Point(799, 0);
   TestMagnifierLayerTransform(point_of_interest, root_windows[0]);
   point_of_interest.set_y(viewport_height +
-                          DockedMagnifierControllerImpl::kSeparatorHeight);
+                          DockedMagnifierController::kSeparatorHeight);
   magnifier_layer->transform().TransformPoint(&point_of_interest);
   EXPECT_EQ(viewport_top_edge_center, point_of_interest);
 
   EXPECT_FLOAT_EQ(viewport_height +
-                      DockedMagnifierControllerImpl::kSeparatorHeight +
+                      DockedMagnifierController::kSeparatorHeight +
                       (viewport_center.y() / scale2),
                   controller()->GetMinimumPointOfInterestHeightForTesting());
 }
diff --git a/ash/accessibility/magnifier/full_screen_magnifier_controller.cc b/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc
similarity index 91%
rename from ash/accessibility/magnifier/full_screen_magnifier_controller.cc
rename to ash/accessibility/magnifier/fullscreen_magnifier_controller.cc
index 21df8b4..42c4773 100644
--- a/ash/accessibility/magnifier/full_screen_magnifier_controller.cc
+++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 
 #include <algorithm>
 #include <memory>
@@ -89,7 +89,7 @@
 
 }  // namespace
 
-class FullScreenMagnifierController::GestureProviderClient
+class FullscreenMagnifierController::GestureProviderClient
     : public ui::GestureProviderAuraClient {
  public:
   GestureProviderClient() = default;
@@ -99,7 +99,7 @@
   void OnGestureEvent(GestureConsumer* consumer,
                       ui::GestureEvent* event) override {
     // Do nothing. OnGestureEvent is for timer based gesture events, e.g. tap.
-    // FullScreenMagnifierController is interested only in pinch and scroll
+    // FullscreenMagnifierController is interested only in pinch and scroll
     // gestures.
     DCHECK_NE(ui::ET_GESTURE_SCROLL_BEGIN, event->type());
     DCHECK_NE(ui::ET_GESTURE_SCROLL_END, event->type());
@@ -113,7 +113,7 @@
   DISALLOW_COPY_AND_ASSIGN(GestureProviderClient);
 };
 
-FullScreenMagnifierController::FullScreenMagnifierController()
+FullscreenMagnifierController::FullscreenMagnifierController()
     : root_window_(Shell::GetPrimaryRootWindow()),
       scale_(kNonMagnifiedScale),
       original_scale_(kNonMagnifiedScale) {
@@ -132,7 +132,7 @@
   magnifier_debug_draw_rect_ = ::switches::IsMagnifierDebugDrawRectEnabled();
 }
 
-FullScreenMagnifierController::~FullScreenMagnifierController() {
+FullscreenMagnifierController::~FullscreenMagnifierController() {
   if (input_method_)
     input_method_->RemoveObserver(this);
   input_method_ = nullptr;
@@ -145,7 +145,7 @@
   Shell::Get()->RemovePreTargetHandler(this);
 }
 
-void FullScreenMagnifierController::SetEnabled(bool enabled) {
+void FullscreenMagnifierController::SetEnabled(bool enabled) {
   if (enabled) {
     if (!is_enabled_) {
       input_method_ = magnifier_utils::GetInputMethod(root_window_);
@@ -189,20 +189,20 @@
   keyboard::KeyboardUIController::Get()->UpdateKeyboardConfig(config);
 }
 
-bool FullScreenMagnifierController::IsEnabled() const {
+bool FullscreenMagnifierController::IsEnabled() const {
   return is_enabled_;
 }
 
-void FullScreenMagnifierController::SetKeepFocusCentered(
+void FullscreenMagnifierController::SetKeepFocusCentered(
     bool keep_focus_centered) {
   keep_focus_centered_ = keep_focus_centered;
 }
 
-bool FullScreenMagnifierController::KeepFocusCentered() const {
+bool FullscreenMagnifierController::KeepFocusCentered() const {
   return keep_focus_centered_;
 }
 
-void FullScreenMagnifierController::SetScale(float scale, bool animate) {
+void FullscreenMagnifierController::SetScale(float scale, bool animate) {
   if (!is_enabled_)
     return;
 
@@ -211,20 +211,20 @@
   RedrawKeepingMousePosition(scale, animate, false);
 }
 
-void FullScreenMagnifierController::StepToNextScaleValue(int delta_index) {
+void FullscreenMagnifierController::StepToNextScaleValue(int delta_index) {
   SetScale(magnifier_utils::GetNextMagnifierScaleValue(
                delta_index, GetScale(), kNonMagnifiedScale, kMaxMagnifiedScale),
            true /* animate */);
 }
 
-void FullScreenMagnifierController::MoveWindow(int x, int y, bool animate) {
+void FullscreenMagnifierController::MoveWindow(int x, int y, bool animate) {
   if (!is_enabled_)
     return;
 
   Redraw(gfx::PointF(x, y), scale_, animate);
 }
 
-void FullScreenMagnifierController::MoveWindow(const gfx::Point& point,
+void FullscreenMagnifierController::MoveWindow(const gfx::Point& point,
                                                bool animate) {
   if (!is_enabled_)
     return;
@@ -232,21 +232,21 @@
   Redraw(gfx::PointF(point), scale_, animate);
 }
 
-gfx::Point FullScreenMagnifierController::GetWindowPosition() const {
+gfx::Point FullscreenMagnifierController::GetWindowPosition() const {
   return gfx::ToFlooredPoint(origin_);
 }
 
-void FullScreenMagnifierController::SetScrollDirection(
+void FullscreenMagnifierController::SetScrollDirection(
     ScrollDirection direction) {
   scroll_direction_ = direction;
   StartOrStopScrollIfNecessary();
 }
 
-gfx::Rect FullScreenMagnifierController::GetViewportRect() const {
+gfx::Rect FullscreenMagnifierController::GetViewportRect() const {
   return gfx::ToEnclosingRect(GetWindowRectDIP(scale_));
 }
 
-void FullScreenMagnifierController::CenterOnPoint(
+void FullscreenMagnifierController::CenterOnPoint(
     const gfx::Point& point_in_screen) {
   gfx::Point point_in_root = point_in_screen;
   ::wm::ConvertPointFromScreen(root_window_, &point_in_root);
@@ -254,7 +254,7 @@
   MoveMagnifierWindowCenterPoint(point_in_root);
 }
 
-void FullScreenMagnifierController::HandleFocusedNodeChanged(
+void FullscreenMagnifierController::HandleFocusedNodeChanged(
     bool is_editable_node,
     const gfx::Rect& node_bounds_in_screen) {
   // The editable node is handled by OnCaretBoundsChanged.
@@ -273,7 +273,7 @@
   MoveMagnifierWindowFollowRect(node_bounds_in_root);
 }
 
-void FullScreenMagnifierController::HandleMoveMagnifierToRect(
+void FullscreenMagnifierController::HandleMoveMagnifierToRect(
     const gfx::Rect& rect_in_screen) {
   gfx::Rect node_bounds_in_root = rect_in_screen;
   ::wm::ConvertRectFromScreen(root_window_, &node_bounds_in_root);
@@ -283,7 +283,7 @@
   MoveMagnifierWindowFollowRect(node_bounds_in_root);
 }
 
-void FullScreenMagnifierController::SwitchTargetRootWindow(
+void FullscreenMagnifierController::SwitchTargetRootWindow(
     aura::Window* new_root_window,
     bool redraw_original_root_window) {
   DCHECK(new_root_window);
@@ -310,7 +310,7 @@
   root_window_->AddObserver(this);
 }
 
-gfx::Transform FullScreenMagnifierController::GetMagnifierTransform() const {
+gfx::Transform FullscreenMagnifierController::GetMagnifierTransform() const {
   gfx::Transform transform;
   if (IsEnabled()) {
     transform.Scale(scale_, scale_);
@@ -321,7 +321,7 @@
   return transform;
 }
 
-void FullScreenMagnifierController::OnInputContextHandlerChanged() {
+void FullscreenMagnifierController::OnInputContextHandlerChanged() {
   if (!is_enabled_)
     return;
 
@@ -336,7 +336,7 @@
     input_method_->AddObserver(this);
 }
 
-void FullScreenMagnifierController::OnCaretBoundsChanged(
+void FullscreenMagnifierController::OnCaretBoundsChanged(
     const ui::TextInputClient* client) {
   // caret bounds in screen coordinates.
   const gfx::Rect caret_bounds = client->GetCaretBounds();
@@ -388,17 +388,17 @@
       FROM_HERE,
       base::TimeDelta::FromMilliseconds(
           disable_move_magnifier_delay_ ? 0 : kMoveMagnifierDelayInMs),
-      this, &FullScreenMagnifierController::OnMoveMagnifierTimer);
+      this, &FullscreenMagnifierController::OnMoveMagnifierTimer);
 }
 
-void FullScreenMagnifierController::OnInputMethodDestroyed(
+void FullscreenMagnifierController::OnInputMethodDestroyed(
     const ui::InputMethod* input_method) {
   DCHECK_EQ(input_method, input_method_);
   input_method_->RemoveObserver(this);
   input_method_ = nullptr;
 }
 
-void FullScreenMagnifierController::OnImplicitAnimationsCompleted() {
+void FullscreenMagnifierController::OnImplicitAnimationsCompleted() {
   if (!is_on_animation_)
     return;
 
@@ -417,7 +417,7 @@
   StartOrStopScrollIfNecessary();
 }
 
-void FullScreenMagnifierController::OnWindowDestroying(
+void FullscreenMagnifierController::OnWindowDestroying(
     aura::Window* root_window) {
   if (root_window == root_window_) {
     // There must be at least one root window because this controller is
@@ -435,7 +435,7 @@
   }
 }
 
-void FullScreenMagnifierController::OnWindowBoundsChanged(
+void FullscreenMagnifierController::OnWindowBoundsChanged(
     aura::Window* window,
     const gfx::Rect& old_bounds,
     const gfx::Rect& new_bounds,
@@ -443,7 +443,7 @@
   // TODO(yoshiki): implement here. crbug.com/230979
 }
 
-void FullScreenMagnifierController::OnMouseEvent(ui::MouseEvent* event) {
+void FullscreenMagnifierController::OnMouseEvent(ui::MouseEvent* event) {
   aura::Window* target = static_cast<aura::Window*>(event->target());
   aura::Window* current_root = target->GetRootWindow();
   gfx::Point root_location = event->root_location();
@@ -481,7 +481,7 @@
   }
 }
 
-void FullScreenMagnifierController::OnScrollEvent(ui::ScrollEvent* event) {
+void FullscreenMagnifierController::OnScrollEvent(ui::ScrollEvent* event) {
   if (event->IsAltDown() && event->IsControlDown()) {
     if (event->type() == ui::ET_SCROLL_FLING_START) {
       event->StopPropagation();
@@ -510,7 +510,7 @@
   }
 }
 
-void FullScreenMagnifierController::OnTouchEvent(ui::TouchEvent* event) {
+void FullscreenMagnifierController::OnTouchEvent(ui::TouchEvent* event) {
   aura::Window* target = static_cast<aura::Window*>(event->target());
   aura::Window* current_root = target->GetRootWindow();
 
@@ -524,7 +524,7 @@
     SwitchTargetRootWindow(current_root, true);
 }
 
-ui::EventDispatchDetails FullScreenMagnifierController::RewriteEvent(
+ui::EventDispatchDetails FullscreenMagnifierController::RewriteEvent(
     const ui::Event& event,
     const Continuation continuation) {
   if (!IsEnabled())
@@ -554,7 +554,7 @@
   }
 
   // User can change zoom level with two fingers pinch and pan around with two
-  // fingers scroll. Once FullScreenMagnifierController detects one of those two
+  // fingers scroll. Once FullscreenMagnifierController detects one of those two
   // gestures, it starts consuming all touch events with cancelling existing
   // touches. If cancel_pressed_touches is set to true, ET_TOUCH_CANCELLED
   // events are dispatched for existing touches after the next for-loop.
@@ -563,7 +563,7 @@
   if (cancel_pressed_touches) {
     DCHECK_EQ(2u, press_event_map_.size());
 
-    // FullScreenMagnifierController starts consuming all touch events after it
+    // FullscreenMagnifierController starts consuming all touch events after it
     // cancells existing touches.
     consume_touch_event_ = true;
 
@@ -576,7 +576,7 @@
       touch_cancel_event.set_flags(it.second->flags());
 
       // TouchExplorationController is watching event stream and managing its
-      // internal state. If an event rewriter (FullScreenMagnifierController)
+      // internal state. If an event rewriter (FullscreenMagnifierController)
       // rewrites event stream, the next event rewriter won't get the event,
       // which makes TouchExplorationController confused. Send cancelled event
       // for recorded touch events to the next event rewriter here instead of
@@ -610,7 +610,7 @@
   return SendEvent(continuation, &event);
 }
 
-bool FullScreenMagnifierController::Redraw(
+bool FullscreenMagnifierController::Redraw(
     const gfx::PointF& position_in_physical_pixels,
     float scale,
     bool animate) {
@@ -621,7 +621,7 @@
                    kDefaultAnimationTweenType);
 }
 
-bool FullScreenMagnifierController::RedrawDIP(
+bool FullscreenMagnifierController::RedrawDIP(
     const gfx::PointF& position_in_dip,
     float scale,
     int duration_in_ms,
@@ -717,7 +717,7 @@
   return true;
 }
 
-void FullScreenMagnifierController::StartOrStopScrollIfNecessary() {
+void FullscreenMagnifierController::StartOrStopScrollIfNecessary() {
   // This value controls the scrolling speed.
   const int kMoveOffset = 40;
   if (is_on_animation_) {
@@ -748,7 +748,7 @@
             kDefaultAnimationTweenType);
 }
 
-void FullScreenMagnifierController::RedrawKeepingMousePosition(
+void FullscreenMagnifierController::RedrawKeepingMousePosition(
     float scale,
     bool animate,
     bool ignore_mouse_change) {
@@ -767,7 +767,7 @@
     AfterAnimationMoveCursorTo(mouse_in_root);
 }
 
-void FullScreenMagnifierController::OnMouseMove(const gfx::Point& location) {
+void FullscreenMagnifierController::OnMouseMove(const gfx::Point& location) {
   DCHECK(root_window_);
 
   gfx::Point mouse(location);
@@ -792,7 +792,7 @@
                                  reduce_bottom_margin);
 }
 
-void FullScreenMagnifierController::AfterAnimationMoveCursorTo(
+void FullscreenMagnifierController::AfterAnimationMoveCursorTo(
     const gfx::Point& location) {
   DCHECK(root_window_);
 
@@ -809,11 +809,11 @@
   position_after_animation_ = location;
 }
 
-bool FullScreenMagnifierController::IsMagnified() const {
+bool FullscreenMagnifierController::IsMagnified() const {
   return scale_ >= kMinMagnifiedScaleThreshold;
 }
 
-gfx::RectF FullScreenMagnifierController::GetWindowRectDIP(float scale) const {
+gfx::RectF FullscreenMagnifierController::GetWindowRectDIP(float scale) const {
   const gfx::Size size_in_dip = root_window_->bounds().size();
   const float width = size_in_dip.width() / scale;
   const float height = size_in_dip.height() / scale;
@@ -821,16 +821,16 @@
   return gfx::RectF(origin_.x(), origin_.y(), width, height);
 }
 
-gfx::Size FullScreenMagnifierController::GetHostSizeDIP() const {
+gfx::Size FullscreenMagnifierController::GetHostSizeDIP() const {
   return root_window_->bounds().size();
 }
 
-void FullScreenMagnifierController::ValidateScale(float* scale) {
+void FullscreenMagnifierController::ValidateScale(float* scale) {
   *scale = base::ClampToRange(*scale, kNonMagnifiedScale, kMaxMagnifiedScale);
   DCHECK(kNonMagnifiedScale <= *scale && *scale <= kMaxMagnifiedScale);
 }
 
-bool FullScreenMagnifierController::ProcessGestures() {
+bool FullscreenMagnifierController::ProcessGestures() {
   bool cancel_pressed_touches = false;
 
   std::vector<std::unique_ptr<ui::GestureEvent>> gestures =
@@ -910,7 +910,7 @@
   return cancel_pressed_touches;
 }
 
-void FullScreenMagnifierController::MoveMagnifierWindowFollowPoint(
+void FullscreenMagnifierController::MoveMagnifierWindowFollowPoint(
     const gfx::Point& point,
     int x_panning_margin,
     int y_panning_margin,
@@ -973,7 +973,7 @@
   }
 }
 
-void FullScreenMagnifierController::MoveMagnifierWindowCenterPoint(
+void FullscreenMagnifierController::MoveMagnifierWindowCenterPoint(
     const gfx::Point& point) {
   DCHECK(root_window_);
 
@@ -999,7 +999,7 @@
   }
 }
 
-void FullScreenMagnifierController::MoveMagnifierWindowFollowRect(
+void FullscreenMagnifierController::MoveMagnifierWindowFollowRect(
     const gfx::Rect& rect) {
   DCHECK(root_window_);
   last_move_magnifier_to_rect_ = base::TimeTicks::Now();
@@ -1043,7 +1043,7 @@
   }
 }
 
-void FullScreenMagnifierController::OnMoveMagnifierTimer() {
+void FullscreenMagnifierController::OnMoveMagnifierTimer() {
   // Ignore caret changes while move magnifier to rect activity is occurring.
   if (base::TimeTicks::Now() - last_move_magnifier_to_rect_ <
       magnifier_utils::kPauseCaretUpdateDuration) {
diff --git a/ash/accessibility/magnifier/full_screen_magnifier_controller.h b/ash/accessibility/magnifier/fullscreen_magnifier_controller.h
similarity index 95%
rename from ash/accessibility/magnifier/full_screen_magnifier_controller.h
rename to ash/accessibility/magnifier/fullscreen_magnifier_controller.h
index 41c8797..1051961 100644
--- a/ash/accessibility/magnifier/full_screen_magnifier_controller.h
+++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_ACCESSIBILITY_MAGNIFIER_FULL_SCREEN_MAGNIFIER_CONTROLLER_H_
-#define ASH_ACCESSIBILITY_MAGNIFIER_FULL_SCREEN_MAGNIFIER_CONTROLLER_H_
+#ifndef ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
+#define ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
 
 #include <map>
 #include <memory>
@@ -37,15 +37,15 @@
 
 namespace ash {
 
-// FullScreenMagnifierController implements GestureConsumer as it has its own
+// FullscreenMagnifierController implements GestureConsumer as it has its own
 // GestureProvider to recognize gestures with screen coordinates of touches.
 // Logical coordinates of touches cannot be used as they are changed with
 // viewport change: scroll, zoom.
-// FullScreenMagnifierController implements EventRewriter to see and rewrite
+// FullscreenMagnifierController implements EventRewriter to see and rewrite
 // touch events. Once the controller detects two fingers pinch or scroll, it
 // starts consuming all touch events not to confuse an app or a browser on the
 // screen. It needs to rewrite events to dispatch touch cancel events.
-class ASH_EXPORT FullScreenMagnifierController
+class ASH_EXPORT FullscreenMagnifierController
     : public ui::EventHandler,
       public ui::ImplicitAnimationObserver,
       public aura::WindowObserver,
@@ -62,8 +62,8 @@
     SCROLL_DOWN
   };
 
-  FullScreenMagnifierController();
-  ~FullScreenMagnifierController() override;
+  FullscreenMagnifierController();
+  ~FullscreenMagnifierController() override;
 
   void set_mouse_following_mode(
       MagnifierMouseFollowingMode mouse_following_mode) {
@@ -306,7 +306,7 @@
 
   ScrollDirection scroll_direction_ = SCROLL_NONE;
 
-  // If true, FullScreenMagnifierController consumes all touch events.
+  // If true, FullscreenMagnifierController consumes all touch events.
   bool consume_touch_event_ = false;
 
   // Number of touch points on the screen.
@@ -321,7 +321,7 @@
   std::unique_ptr<GestureProviderClient> gesture_provider_client_;
 
   // MagnificationCotroller owns its GestureProvider to detect gestures with
-  // screen coordinates of touch events. As FullScreenMagnifierController
+  // screen coordinates of touch events. As FullscreenMagnifierController
   // changes zoom level and moves viewport, logical coordinates of touches
   // cannot be used for gesture detection as they are changed if the controller
   // reacts to gestures.
@@ -345,9 +345,9 @@
   // few milliseconds after the last move magnifier to rect call.
   base::TimeTicks last_move_magnifier_to_rect_;
 
-  DISALLOW_COPY_AND_ASSIGN(FullScreenMagnifierController);
+  DISALLOW_COPY_AND_ASSIGN(FullscreenMagnifierController);
 };
 
 }  // namespace ash
 
-#endif  // ASH_ACCESSIBILITY_MAGNIFIER_FULL_SCREEN_MAGNIFIER_CONTROLLER_H_
+#endif  // ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
diff --git a/ash/accessibility/magnifier/full_screen_magnifier_controller_unittest.cc b/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc
similarity index 79%
rename from ash/accessibility/magnifier/full_screen_magnifier_controller_unittest.cc
rename to ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc
index 17500e5..e12f6665 100644
--- a/ash/accessibility/magnifier/full_screen_magnifier_controller_unittest.cc
+++ b/ash/accessibility/magnifier/fullscreen_magnifier_controller_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 
 #include "ash/accessibility/magnifier/magnifier_test_utils.h"
 #include "ash/accessibility/magnifier/magnifier_utils.h"
@@ -51,16 +51,16 @@
 
 }  // namespace
 
-class FullScreenMagnifierControllerTest : public AshTestBase {
+class FullscreenMagnifierControllerTest : public AshTestBase {
  public:
-  FullScreenMagnifierControllerTest() {}
-  ~FullScreenMagnifierControllerTest() override = default;
+  FullscreenMagnifierControllerTest() {}
+  ~FullscreenMagnifierControllerTest() override = default;
 
   void SetUp() override {
     AshTestBase::SetUp();
     UpdateDisplay(base::StringPrintf("%dx%d", kRootWidth, kRootHeight));
 
-    GetFullScreenMagnifierController()->DisableMoveMagnifierDelayForTesting();
+    GetFullscreenMagnifierController()->DisableMoveMagnifierDelayForTesting();
 
     touch_event_watcher_ = std::make_unique<TouchEventWatcher>();
     GetRootWindow()->AddPreTargetHandler(touch_event_watcher_.get(),
@@ -91,8 +91,8 @@
     return location.ToString();
   }
 
-  FullScreenMagnifierController* GetFullScreenMagnifierController() const {
-    return Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* GetFullscreenMagnifierController() const {
+    return Shell::Get()->fullscreen_magnifier_controller();
   }
 
   gfx::Rect GetViewport() const {
@@ -102,7 +102,7 @@
   }
 
   std::string CurrentPointOfInterest() const {
-    return GetFullScreenMagnifierController()
+    return GetFullscreenMagnifierController()
         ->GetPointOfInterestForTesting()
         .ToString();
   }
@@ -172,100 +172,100 @@
   MagnifierTextInputTestHelper text_input_helper_;
 };
 
-TEST_F(FullScreenMagnifierControllerTest, EnableAndDisable) {
+TEST_F(FullscreenMagnifierControllerTest, EnableAndDisable) {
   // Confirms the magnifier is disabled.
   EXPECT_TRUE(GetRootWindow()->layer()->transform().IsIdentity());
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
 
   // Enables magnifier.
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_FALSE(GetRootWindow()->layer()->transform().IsIdentity());
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
 
   // Disables magnifier.
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
   EXPECT_TRUE(GetRootWindow()->layer()->transform().IsIdentity());
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
 
   // Confirms the the scale can't be changed.
-  GetFullScreenMagnifierController()->SetScale(4.0f, false);
+  GetFullscreenMagnifierController()->SetScale(4.0f, false);
   EXPECT_TRUE(GetRootWindow()->layer()->transform().IsIdentity());
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, MagnifyAndUnmagnify) {
+TEST_F(FullscreenMagnifierControllerTest, MagnifyAndUnmagnify) {
   // Enables magnifier and confirms the default scale is 2.0x.
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_FALSE(GetRootWindow()->layer()->transform().IsIdentity());
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 
   // Changes the scale.
-  GetFullScreenMagnifierController()->SetScale(4.0f, false);
-  EXPECT_EQ(4.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(4.0f, false);
+  EXPECT_EQ(4.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("300,225 200x150", GetViewport().ToString());
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 
-  GetFullScreenMagnifierController()->SetScale(1.0f, false);
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(1.0f, false);
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 
-  GetFullScreenMagnifierController()->SetScale(3.0f, false);
-  EXPECT_EQ(3.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(3.0f, false);
+  EXPECT_EQ(3.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("266,200 267x200", GetViewport().ToString());
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, MoveWindow) {
+TEST_F(FullscreenMagnifierControllerTest, MoveWindow) {
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
 
   // Move the viewport.
-  GetFullScreenMagnifierController()->MoveWindow(0, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 0, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(200, 300, false);
+  GetFullscreenMagnifierController()->MoveWindow(200, 300, false);
   EXPECT_EQ("200,300 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(400, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(400, 0, false);
   EXPECT_EQ("400,0 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(400, 300, false);
+  GetFullscreenMagnifierController()->MoveWindow(400, 300, false);
   EXPECT_EQ("400,300 400x300", GetViewport().ToString());
 
   // Confirms that the viewport can't across the top-left border.
-  GetFullScreenMagnifierController()->MoveWindow(-100, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(-100, 0, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(0, -100, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, -100, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(-100, -100, false);
+  GetFullscreenMagnifierController()->MoveWindow(-100, -100, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
 
   // Confirms that the viewport can't across the bittom-right border.
-  GetFullScreenMagnifierController()->MoveWindow(800, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(800, 0, false);
   EXPECT_EQ("400,0 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(0, 400, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 400, false);
   EXPECT_EQ("0,300 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(200, 400, false);
+  GetFullscreenMagnifierController()->MoveWindow(200, 400, false);
   EXPECT_EQ("200,300 400x300", GetViewport().ToString());
 
-  GetFullScreenMagnifierController()->MoveWindow(1000, 1000, false);
+  GetFullscreenMagnifierController()->MoveWindow(1000, 1000, false);
   EXPECT_EQ("400,300 400x300", GetViewport().ToString());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, PointOfInterest) {
+TEST_F(FullscreenMagnifierControllerTest, PointOfInterest) {
   ui::test::EventGenerator* event_generator = GetEventGenerator();
 
   event_generator->MoveMouseToInHost(gfx::Point(0, 0));
@@ -277,7 +277,7 @@
   event_generator->MoveMouseToInHost(gfx::Point(400, 300));
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_EQ("400,300", CurrentPointOfInterest());
 
   event_generator->MoveMouseToInHost(gfx::Point(500, 400));
@@ -285,47 +285,47 @@
 }
 
 // TODO(warx): move this test to unit_tests.
-TEST_F(FullScreenMagnifierControllerTest, FollowFocusChanged) {
+TEST_F(FullscreenMagnifierControllerTest, FollowFocusChanged) {
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
 
   // Don't move viewport when focusing edit box.
-  GetFullScreenMagnifierController()->HandleFocusedNodeChanged(
+  GetFullscreenMagnifierController()->HandleFocusedNodeChanged(
       true, gfx::Rect(0, 0, 10, 10));
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
 
   // Move viewport to element in upper left.
-  GetFullScreenMagnifierController()->HandleFocusedNodeChanged(
+  GetFullscreenMagnifierController()->HandleFocusedNodeChanged(
       false, gfx::Rect(0, 0, 10, 10));
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
 
   // Move viewport to element in lower right.
-  GetFullScreenMagnifierController()->HandleFocusedNodeChanged(
+  GetFullscreenMagnifierController()->HandleFocusedNodeChanged(
       false, gfx::Rect(790, 590, 10, 10));
   EXPECT_EQ("400,300 400x300", GetViewport().ToString());
 
   // Don't follow focus onto empty rectangle.
-  GetFullScreenMagnifierController()->HandleFocusedNodeChanged(
+  GetFullscreenMagnifierController()->HandleFocusedNodeChanged(
       false, gfx::Rect(0, 0, 0, 0));
   EXPECT_EQ("400,300 400x300", GetViewport().ToString());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, PanWindow2xLeftToRight) {
+TEST_F(FullscreenMagnifierControllerTest, PanWindow2xLeftToRight) {
   const aura::Env* env = aura::Env::GetInstance();
 
   ui::test::EventGenerator* event_generator = GetEventGenerator();
   event_generator->MoveMouseToInHost(gfx::Point(0, 0));
-  EXPECT_EQ(1.f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
   EXPECT_EQ("0,0", env->last_mouse_location().ToString());
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->MoveWindow(0, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 0, false);
   event_generator->MoveMouseToInHost(gfx::Point(0, 0));
   EXPECT_EQ("0,0", env->last_mouse_location().ToString());
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
@@ -416,17 +416,17 @@
   EXPECT_EQ("400,0 400x300", GetViewport().ToString());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, PanWindow2xRightToLeft) {
+TEST_F(FullscreenMagnifierControllerTest, PanWindow2xRightToLeft) {
   const aura::Env* env = aura::Env::GetInstance();
 
   ui::test::EventGenerator* event_generator = GetEventGenerator();
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
-  EXPECT_EQ(1.f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
   EXPECT_EQ("799,300", env->last_mouse_location().ToString());
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
 
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
   EXPECT_EQ("798,300", env->last_mouse_location().ToString());
@@ -469,24 +469,24 @@
   EXPECT_EQ("0,150 400x300", GetViewport().ToString());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, PanWindowToRight) {
+TEST_F(FullscreenMagnifierControllerTest, PanWindowToRight) {
   const aura::Env* env = aura::Env::GetInstance();
 
   ui::test::EventGenerator* event_generator = GetEventGenerator();
   event_generator->MoveMouseToInHost(gfx::Point(400, 300));
-  EXPECT_EQ(1.f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
   EXPECT_EQ("400,300", env->last_mouse_location().ToString());
 
   float scale = 2.f;
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_FLOAT_EQ(2.f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_FLOAT_EQ(2.f, GetFullscreenMagnifierController()->GetScale());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(2.3784142, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(2.3784142, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(400, 300));
   EXPECT_EQ("400,300", env->last_mouse_location().ToString());
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
@@ -494,45 +494,45 @@
   EXPECT_EQ("705,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(2.8284268, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(2.8284268, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
   EXPECT_EQ("599,299", env->last_mouse_location().ToString());
   EXPECT_EQ("702,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(3.3635852, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(3.3635852, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
   EXPECT_EQ("627,298", env->last_mouse_location().ToString());
   EXPECT_EQ("707,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(4.f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(4.f, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(799, 300));
   EXPECT_EQ("649,298", env->last_mouse_location().ToString());
   EXPECT_EQ("704,300", GetHostMouseLocation());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, PanWindowToLeft) {
+TEST_F(FullscreenMagnifierControllerTest, PanWindowToLeft) {
   const aura::Env* env = aura::Env::GetInstance();
 
   ui::test::EventGenerator* event_generator = GetEventGenerator();
   event_generator->MoveMouseToInHost(gfx::Point(400, 300));
-  EXPECT_EQ(1.f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("0,0 800x600", GetViewport().ToString());
   EXPECT_EQ("400,300", env->last_mouse_location().ToString());
 
   float scale = 2.f;
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_FLOAT_EQ(2.f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_FLOAT_EQ(2.f, GetFullscreenMagnifierController()->GetScale());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(2.3784142, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(2.3784142, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(400, 300));
   EXPECT_EQ("400,300", env->last_mouse_location().ToString());
   event_generator->MoveMouseToInHost(gfx::Point(0, 300));
@@ -540,36 +540,36 @@
   EXPECT_EQ("100,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(2.8284268, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(2.8284268, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(0, 300));
   EXPECT_EQ("194,299", env->last_mouse_location().ToString());
   EXPECT_EQ("99,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(3.3635852, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(3.3635852, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(0, 300));
   EXPECT_EQ("164,298", env->last_mouse_location().ToString());
   EXPECT_EQ("98,300", GetHostMouseLocation());
 
   scale *= magnifier_utils::kMagnificationScaleFactor;
-  GetFullScreenMagnifierController()->SetScale(scale, false);
-  EXPECT_FLOAT_EQ(4.f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetScale(scale, false);
+  EXPECT_FLOAT_EQ(4.f, GetFullscreenMagnifierController()->GetScale());
   event_generator->MoveMouseToInHost(gfx::Point(0, 300));
   EXPECT_EQ("139,298", env->last_mouse_location().ToString());
   EXPECT_EQ("100,300", GetHostMouseLocation());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, FocusChangeEvents) {
+TEST_F(FullscreenMagnifierControllerTest, FocusChangeEvents) {
   MagnifierFocusTestHelper focus_test_helper;
   focus_test_helper.CreateAndShowFocusTestView(gfx::Point(100, 200));
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_FALSE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_FALSE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
   // Focus on the first button and expect the magnifier to be centered around
   // its center.
@@ -585,19 +585,19 @@
   EXPECT_EQ(button_2_center, GetViewport().CenterPoint());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, FollowTextInputFieldFocus) {
+TEST_F(FullscreenMagnifierControllerTest, FollowTextInputFieldFocus) {
   text_input_helper_.CreateAndShowTextInputView(gfx::Rect(500, 300, 80, 80));
   gfx::Rect text_input_bounds = text_input_helper_.GetTextInputViewBounds();
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_FALSE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_FALSE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
   // Move the viewport to (0, 0), so that text input field will be out of
   // the viewport region.
-  GetFullScreenMagnifierController()->MoveWindow(0, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 0, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
   EXPECT_FALSE(GetViewport().Intersects(text_input_bounds));
 
@@ -618,7 +618,7 @@
 // caret panning margin, so that when it gets focus, the view port won't move.
 // Then when user types a character, the caret moves beyond the right panning
 // edge, the view port will be moved to center the caret horizontally.
-TEST_F(FullScreenMagnifierControllerTest, FollowTextInputFieldKeyPress) {
+TEST_F(FullscreenMagnifierControllerTest, FollowTextInputFieldKeyPress) {
   const int kCaretPanningMargin = 50;
   const int kScale = 2.0f;
   const int kViewportWidth = 400;
@@ -629,14 +629,14 @@
   gfx::Rect text_input_bounds = text_input_helper_.GetTextInputViewBounds();
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_FALSE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_FALSE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
   // Move the viewport to (0, 0), so that text input field intersects the
   // view port at the right edge.
-  GetFullScreenMagnifierController()->MoveWindow(0, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 0, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
   EXPECT_TRUE(GetViewport().Intersects(text_input_bounds));
 
@@ -665,20 +665,20 @@
   EXPECT_EQ(caret_bounds.CenterPoint().x(), new_view_port.CenterPoint().x());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, CenterTextCaretNotInsideViewport) {
+TEST_F(FullscreenMagnifierControllerTest, CenterTextCaretNotInsideViewport) {
   text_input_helper_.CreateAndShowTextInputView(gfx::Rect(500, 300, 50, 30));
   gfx::Rect text_input_bounds = text_input_helper_.GetTextInputViewBounds();
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetKeepFocusCentered(true);
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetKeepFocusCentered(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_TRUE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_TRUE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
   // Move the viewport to (0, 0), so that text input field will be out of
   // the viewport region.
-  GetFullScreenMagnifierController()->MoveWindow(0, 0, false);
+  GetFullscreenMagnifierController()->MoveWindow(0, 0, false);
   EXPECT_EQ("0,0 400x300", GetViewport().ToString());
   EXPECT_FALSE(GetViewport().Contains(text_input_bounds));
 
@@ -707,16 +707,16 @@
   EXPECT_EQ(new_caret_bounds.CenterPoint(), new_view_port.CenterPoint());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, CenterTextCaretInViewport) {
+TEST_F(FullscreenMagnifierControllerTest, CenterTextCaretInViewport) {
   text_input_helper_.CreateAndShowTextInputView(gfx::Rect(250, 200, 50, 30));
   gfx::Rect text_input_bounds = text_input_helper_.GetTextInputViewBounds();
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetKeepFocusCentered(true);
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetKeepFocusCentered(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_TRUE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_TRUE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
   // Verify the text input field is inside the view port.
   gfx::Rect view_port = GetViewport();
@@ -736,37 +736,37 @@
 }
 
 // Make sure that unified desktop can enter magnified mode.
-TEST_F(FullScreenMagnifierControllerTest, EnableMagnifierInUnifiedDesktop) {
+TEST_F(FullscreenMagnifierControllerTest, EnableMagnifierInUnifiedDesktop) {
   Shell::Get()->display_manager()->SetUnifiedDesktopEnabled(true);
 
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
 
   display::Screen* screen = display::Screen::GetScreen();
 
   UpdateDisplay("500x500, 500x500");
   EXPECT_EQ("0,0 1000x500", screen->GetPrimaryDisplay().bounds().ToString());
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
 
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   UpdateDisplay("500x500");
   EXPECT_EQ("0,0 500x500", screen->GetPrimaryDisplay().bounds().ToString());
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
   EXPECT_EQ("0,0 500x500", screen->GetPrimaryDisplay().bounds().ToString());
-  EXPECT_EQ(1.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(1.0f, GetFullscreenMagnifierController()->GetScale());
 }
 
 // Make sure that mouse can move across display in magnified mode.
-TEST_F(FullScreenMagnifierControllerTest, MoveMouseToSecondDisplay) {
+TEST_F(FullscreenMagnifierControllerTest, MoveMouseToSecondDisplay) {
   UpdateDisplay("0+0-500x500, 500+0-500x500");
   EXPECT_EQ(2ul, display::Screen::GetScreen()->GetAllDisplays().size());
 
@@ -777,7 +777,7 @@
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_FALSE(root_windows[0]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
 
@@ -785,12 +785,12 @@
   EXPECT_FALSE(root_windows[1]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
 
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
 }
 
-TEST_F(FullScreenMagnifierControllerTest, MoveToSecondDisplayWithTouch) {
+TEST_F(FullscreenMagnifierControllerTest, MoveToSecondDisplayWithTouch) {
   UpdateDisplay("0+0-500x500, 500+0-500x500");
   EXPECT_EQ(2ul, display::Screen::GetScreen()->GetAllDisplays().size());
 
@@ -800,7 +800,7 @@
   ASSERT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
   ASSERT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_FALSE(root_windows[0]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
 
@@ -808,18 +808,18 @@
   EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
   EXPECT_FALSE(root_windows[1]->layer()->transform().IsIdentity());
 
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
   EXPECT_TRUE(root_windows[0]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
 }
 
 // Performs pinch zoom and confirm that zoom level is changed. This test case
 // also tests touch event handling.
-TEST_F(FullScreenMagnifierControllerTest, PinchZoom) {
+TEST_F(FullscreenMagnifierControllerTest, PinchZoom) {
   ASSERT_EQ(0u, touch_event_watcher_->touch_events.size());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  ASSERT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  ASSERT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   base::TimeTicks time = base::TimeTicks::Now();
   ui::PointerDetails pointer_details1(ui::EventPointerType::kTouch, 0);
@@ -862,12 +862,12 @@
   // All events are consumed by the controller after it detects gesture.
   EXPECT_EQ(4u, touch_event_watcher_->touch_events.size());
 
-  EXPECT_LT(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_LT(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-  float ratio = GetFullScreenMagnifierController()->GetScale() / 2.0f;
+  float ratio = GetFullscreenMagnifierController()->GetScale() / 2.0f;
 
   // Peform pinch gesture again with 4.0x.
-  GetFullScreenMagnifierController()->SetScale(4.0f, false /* animate */);
+  GetFullscreenMagnifierController()->SetScale(4.0f, false /* animate */);
 
   DispatchTouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(900, 10), time,
                      pointer_details1);
@@ -884,42 +884,42 @@
   DispatchTouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(1200, 10), time,
                      pointer_details2);
 
-  float ratio_zoomed = GetFullScreenMagnifierController()->GetScale() / 4.0f;
+  float ratio_zoomed = GetFullscreenMagnifierController()->GetScale() / 4.0f;
 
   // Ratio of zoom level change should be the same regardless of current zoom
   // level.
   EXPECT_GT(0.01f, std::abs(ratio - ratio_zoomed));
 }
 
-TEST_F(FullScreenMagnifierControllerTest, TwoFingersScroll) {
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  ASSERT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+TEST_F(FullscreenMagnifierControllerTest, TwoFingersScroll) {
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  ASSERT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   const gfx::Point initial_position =
-      GetFullScreenMagnifierController()->GetWindowPosition();
+      GetFullscreenMagnifierController()->GetWindowPosition();
   PerformTwoFingersScrollGesture(ScrollDirection::kPositiveX);
   const gfx::Point moved_position =
-      GetFullScreenMagnifierController()->GetWindowPosition();
+      GetFullscreenMagnifierController()->GetWindowPosition();
 
   // Confirm that two fingers scroll gesture moves viewport.
   EXPECT_GT(initial_position.x(), moved_position.x());
   EXPECT_EQ(initial_position.y(), moved_position.y());
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   int32_t delta = initial_position.x() - moved_position.x();
 
   // Perform the same gesture with 4.0x.
-  GetFullScreenMagnifierController()->SetScale(4.0f, false /* animate */);
+  GetFullscreenMagnifierController()->SetScale(4.0f, false /* animate */);
 
   const gfx::Point initial_position_zoomed =
-      GetFullScreenMagnifierController()->GetWindowPosition();
+      GetFullscreenMagnifierController()->GetWindowPosition();
   PerformTwoFingersScrollGesture(ScrollDirection::kPositiveX);
   const gfx::Point moved_position_zoomed =
-      GetFullScreenMagnifierController()->GetWindowPosition();
+      GetFullscreenMagnifierController()->GetWindowPosition();
 
   EXPECT_GT(initial_position_zoomed.x(), moved_position_zoomed.x());
   EXPECT_EQ(initial_position_zoomed.y(), moved_position_zoomed.y());
-  EXPECT_EQ(4.0f, GetFullScreenMagnifierController()->GetScale());
+  EXPECT_EQ(4.0f, GetFullscreenMagnifierController()->GetScale());
 
   int32_t delta_zoomed =
       initial_position_zoomed.x() - moved_position_zoomed.x();
@@ -928,13 +928,13 @@
   EXPECT_EQ(delta, delta_zoomed * 2);
 }
 
-TEST_F(FullScreenMagnifierControllerTest, TwoFingersScrollRotation) {
+TEST_F(FullscreenMagnifierControllerTest, TwoFingersScrollRotation) {
   const int64_t internal_display_id =
       display::test::DisplayManagerTestApi(display_manager())
           .SetFirstDisplayAsInternalDisplay();
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  ASSERT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  ASSERT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   // Test two-finger scroll gestures in all rotations in all directions.
   for (const auto& rotation :
@@ -953,10 +953,10 @@
       SCOPED_TRACE(::testing::Message()
                    << "Scroll direction: " << (int)scroll_direction);
       const gfx::Point initial_position =
-          GetFullScreenMagnifierController()->GetWindowPosition();
+          GetFullscreenMagnifierController()->GetWindowPosition();
       PerformTwoFingersScrollGesture(scroll_direction);
       const gfx::Point moved_position =
-          GetFullScreenMagnifierController()->GetWindowPosition();
+          GetFullscreenMagnifierController()->GetWindowPosition();
 
       // Confirm that two fingers scroll gesture moves viewport in the right
       // direction.
@@ -989,16 +989,16 @@
   }
 }
 
-TEST_F(FullScreenMagnifierControllerTest, ZoomsIntoCenter) {
+TEST_F(FullscreenMagnifierControllerTest, ZoomsIntoCenter) {
   UpdateDisplay("0+0-500x500");
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  ASSERT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  ASSERT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-  GetFullScreenMagnifierController()->CenterOnPoint(gfx::Point(250, 250));
+  GetFullscreenMagnifierController()->CenterOnPoint(gfx::Point(250, 250));
   ASSERT_EQ(
       gfx::Point(250, 250),
-      GetFullScreenMagnifierController()->GetViewportRect().CenterPoint());
+      GetFullscreenMagnifierController()->GetViewportRect().CenterPoint());
 
   base::TimeTicks time = base::TimeTicks::Now();
   ui::PointerDetails pointer_details1(ui::EventPointerType::kTouch, 0);
@@ -1023,7 +1023,7 @@
                      pointer_details2);
 
   // Confirms that scale has increased with the gesture.
-  ASSERT_LT(2.0f, GetFullScreenMagnifierController()->GetScale());
+  ASSERT_LT(2.0f, GetFullscreenMagnifierController()->GetScale());
 
   // Confirms that center is kept at center of pinch gesture. In ideal
   // situation, center of viewport should be kept at (250, 250). But as noted
@@ -1031,45 +1031,45 @@
   // moves the viewport a little. We accept 5 pixels viewport move for the
   // scroll gesture.
   EXPECT_TRUE(gfx::Rect(245, 245, 10, 10)
-                  .Contains(GetFullScreenMagnifierController()
+                  .Contains(GetFullscreenMagnifierController()
                                 ->GetViewportRect()
                                 .CenterPoint()));
 }
 
 // Tests to see if keyboard overscroll is disabled when fullscreen magnification
 // is enabled.
-TEST_F(FullScreenMagnifierControllerTest, KeyboardOverscrollDisabled) {
-  GetFullScreenMagnifierController()->SetEnabled(false);
+TEST_F(FullscreenMagnifierControllerTest, KeyboardOverscrollDisabled) {
+  GetFullscreenMagnifierController()->SetEnabled(false);
 
   auto* keyboard_controller = keyboard::KeyboardUIController::Get();
   bool old_keyboard_overscroll_value =
       keyboard_controller->IsKeyboardOverscrollEnabled();
 
   // Enable magnification. Keyboard overscroll should be disabled.
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   EXPECT_FALSE(keyboard_controller->IsKeyboardOverscrollEnabled());
 
   // Disable magnification. Keyboard overscroll should be back to the way it was
   // before magnification was enabled.
-  GetFullScreenMagnifierController()->SetEnabled(false);
+  GetFullscreenMagnifierController()->SetEnabled(false);
   EXPECT_EQ(keyboard_controller->IsKeyboardOverscrollEnabled(),
             old_keyboard_overscroll_value);
 }
 
 // Disabled due to https://crbug.com/917113.
-TEST_F(FullScreenMagnifierControllerTest,
+TEST_F(FullscreenMagnifierControllerTest,
        DISABLED_TextfieldFocusedWithKeyboard) {
   // Set up text input view.
   text_input_helper_.CreateAndShowTextInputView(gfx::Rect(500, 200, 80, 80));
   gfx::Rect text_input_bounds = text_input_helper_.GetTextInputViewBounds();
 
   // Enables magnifier and confirm the viewport is at center.
-  GetFullScreenMagnifierController()->SetEnabled(true);
-  EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+  GetFullscreenMagnifierController()->SetEnabled(true);
+  EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
   EXPECT_EQ("200,150 400x300", GetViewport().ToString());
-  EXPECT_FALSE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_FALSE(GetFullscreenMagnifierController()->KeepFocusCentered());
 
-  GetFullScreenMagnifierController()->SetKeepFocusCentered(true);
+  GetFullscreenMagnifierController()->SetKeepFocusCentered(true);
 
   // Set up and show the keyboard.
   keyboard::SetAccessibilityKeyboardEnabled(true);
@@ -1085,11 +1085,11 @@
   viewport_outside_keyboard_bounds.set_height(
       viewport_outside_keyboard_bounds.height() -
       keyboard_controller->GetVisualBoundsInScreen().height() /
-          GetFullScreenMagnifierController()->GetScale());
+          GetFullscreenMagnifierController()->GetScale());
 
   gfx::Rect caret_bounds = text_input_helper_.GetCaretBounds();
 
-  EXPECT_TRUE(GetFullScreenMagnifierController()->KeepFocusCentered());
+  EXPECT_TRUE(GetFullscreenMagnifierController()->KeepFocusCentered());
   EXPECT_TRUE(viewport_outside_keyboard_bounds.Contains(text_input_bounds));
   EXPECT_TRUE(text_input_bounds.Contains(caret_bounds.CenterPoint()));
   EXPECT_EQ(caret_bounds.CenterPoint(),
@@ -1097,7 +1097,7 @@
 }
 
 // Tests that the magnifier gets updated when dragging a window.
-TEST_F(FullScreenMagnifierControllerTest, DragWindow) {
+TEST_F(FullscreenMagnifierControllerTest, DragWindow) {
   UpdateDisplay("800x800");
 
   // Create a window and start dragging by grabbing its caption.
@@ -1108,7 +1108,7 @@
   event_generator->PressLeftButton();
   ASSERT_TRUE(WindowState::Get(window.get())->is_dragged());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   const gfx::Rect initial_viewport_bounds(GetViewport());
 
   // Move the mouse around a bit. The viewport should change, and the window
@@ -1123,7 +1123,7 @@
 }
 
 // Tests that the magnifier gets updated while drag a window across displays.
-TEST_F(FullScreenMagnifierControllerTest, DragWindowAcrossDisplays) {
+TEST_F(FullscreenMagnifierControllerTest, DragWindowAcrossDisplays) {
   UpdateDisplay("0+0-500x500, 500+0-500x500");
   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
 
@@ -1135,7 +1135,7 @@
   event_generator->PressLeftButton();
   ASSERT_TRUE(WindowState::Get(window.get())->is_dragged());
 
-  GetFullScreenMagnifierController()->SetEnabled(true);
+  GetFullscreenMagnifierController()->SetEnabled(true);
   event_generator->MoveMouseToInHost(gfx::Point(250, 250));
   EXPECT_FALSE(root_windows[0]->layer()->transform().IsIdentity());
   EXPECT_TRUE(root_windows[1]->layer()->transform().IsIdentity());
diff --git a/ash/accessibility/magnifier/partial_magnifier_controller_unittest.cc b/ash/accessibility/magnifier/partial_magnifier_controller_unittest.cc
index 8d06063..9e74910 100644
--- a/ash/accessibility/magnifier/partial_magnifier_controller_unittest.cc
+++ b/ash/accessibility/magnifier/partial_magnifier_controller_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "ash/accessibility/magnifier/partial_magnifier_controller.h"
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/magnifier/magnifier_glass.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
diff --git a/ash/app_list/views/ghost_image_view.cc b/ash/app_list/views/ghost_image_view.cc
index d300978..b8a0fcc 100644
--- a/ash/app_list/views/ghost_image_view.cc
+++ b/ash/app_list/views/ghost_image_view.cc
@@ -11,13 +11,11 @@
 #include "ash/app_list/model/app_list_item_list.h"
 #include "ash/app_list/views/app_list_item_view.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
-#include "third_party/skia/include/core/SkPaint.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/animation/tween.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
-#include "ui/gfx/image/image_skia_operations.h"
 
 namespace ash {
 
@@ -30,16 +28,6 @@
 constexpr base::TimeDelta kGhostFadeInOutLength =
     base::TimeDelta::FromMilliseconds(180);
 constexpr gfx::Tween::Type kGhostTween = gfx::Tween::FAST_OUT_SLOW_IN;
-constexpr int kAlphaGradient = 2;
-constexpr int kAlphaChannelFilter = 180;
-
-// These values determine the thickness and appearance of the icon outlines.
-constexpr float kBlurSizeOutline = 2.5;
-constexpr float kBlurSizeThinOutline = 1;
-
-// Amount of padding added on each side of the icon to avoid clipping when the
-// ghost outline is generated.
-constexpr int kGhostImagePadding = 5;
 
 }  // namespace
 
@@ -62,6 +50,10 @@
   icon_bounds_ = drag_view->GetIconBounds();
 
   if (is_folder_) {
+    inner_icon_radius_ =
+        drag_view->GetAppListConfig().item_icon_in_folder_icon_size().width() /
+        2;
+
     AppListFolderItem* folder_item =
         static_cast<AppListFolderItem*>(drag_view->item());
     num_items_ = std::min(FolderImage::kNumFolderTopItems,
@@ -70,23 +62,10 @@
     std::vector<gfx::Rect> top_icon_bounds = FolderImage::GetTopIconsBounds(
         drag_view->GetAppListConfig(), icon_bounds_, num_items_.value());
 
-    // Create an outline, and calculate position for each item within the folder
-    // icon.
+    // Push back the position for each app to be shown within the folder icon.
     for (size_t i = 0; i < num_items_.value(); i++) {
-      gfx::ImageSkia inner_icon_outline =
-          gfx::ImageSkiaOperations::CreateResizedImage(
-              folder_item->item_list()->item_at(i)->GetIcon(
-                  drag_view->GetAppListConfig().type()),
-              skia::ImageOperations::RESIZE_BEST,
-              drag_view->GetAppListConfig().item_icon_in_folder_icon_size());
-      inner_folder_icon_outlines_.push_back(GetIconOutline(inner_icon_outline));
-      inner_folder_icon_origins_.push_back(
-          gfx::Point(top_icon_bounds[i].x() - kGhostImagePadding,
-                     top_icon_bounds[i].y() - kGhostImagePadding));
+      inner_folder_icon_origins_.push_back(top_icon_bounds[i].CenterPoint());
     }
-  } else {
-    // Create outline of app icon and set |outline_| to it.
-    outline_ = GetIconOutline(drag_view->GetIconImage());
   }
 }
 
@@ -137,12 +116,12 @@
   circle_flags.setStyle(cc::PaintFlags::kStroke_Style);
   circle_flags.setStrokeWidth(kGhostCircleStrokeWidth);
 
+  const float ghost_radius = icon_bounds_.width() / 2;
+
+  // Draw a circle to represent an app or folder outline.
+  canvas->DrawCircle(circle_center, ghost_radius, circle_flags);
+
   if (is_folder_) {
-    const float ghost_radius = icon_bounds_.width() / 2;
-
-    // Draw circle to represent outline of folder.
-    canvas->DrawCircle(circle_center, ghost_radius, circle_flags);
-
     // Draw a mask so inner folder icons do not overlap the outer circle.
     SkPath outer_circle_mask;
     outer_circle_mask.addCircle(circle_center.x(), circle_center.y(),
@@ -151,13 +130,9 @@
 
     // Draw ghost items within the ghost folder circle.
     for (size_t i = 0; i < num_items_.value(); i++) {
-      canvas->DrawImageInt(inner_folder_icon_outlines_[i],
-                           inner_folder_icon_origins_[i].x(),
-                           inner_folder_icon_origins_[i].y());
+      canvas->DrawCircle(inner_folder_icon_origins_[i], inner_icon_radius_,
+                         circle_flags);
     }
-  } else {
-    canvas->DrawImageInt(outline_, icon_bounds_.x() - kGhostImagePadding,
-                         icon_bounds_.y() - kGhostImagePadding);
   }
   ImageView::OnPaint(canvas);
 }
@@ -167,152 +142,4 @@
   delete this;
 }
 
-// The implementation for GetIconOutline is copied and adapted from the Android
-// Launcher. See com.android.launcher3.graphics.DragPreviewProvider.java in the
-// Android source.
-
-gfx::ImageSkia GhostImageView::GetIconOutline(
-    const gfx::ImageSkia& original_icon) {
-  gfx::ImageSkia icon_outline;
-
-  original_icon.EnsureRepsForSupportedScales();
-  for (gfx::ImageSkiaRep rep : original_icon.image_reps()) {
-    // Only generate the outline for the ImageSkiaRep with the highest supported
-    // scale.
-    if (rep.scale() != original_icon.GetMaxSupportedScale())
-      continue;
-
-    SkBitmap bitmap(rep.GetBitmap());
-
-    // Add padding to each side of the bitmap so the outline does not get cut
-    // off by the edges from the original bitmap.
-    gfx::Canvas padded_canvas(
-        gfx::Size(bitmap.pixmap().width() + kGhostImagePadding * 2,
-                  bitmap.pixmap().height() + kGhostImagePadding * 2),
-        rep.scale(), false /* is_opaque */);
-    padded_canvas.DrawImageInt(
-        gfx::ImageSkia::CreateFromBitmap(bitmap, rep.scale()),
-        kGhostImagePadding, kGhostImagePadding);
-    bitmap = padded_canvas.GetBitmap();
-
-    const SkPixmap pixmap = bitmap.pixmap();
-    const int width = pixmap.width();
-    const int height = pixmap.height();
-
-    SkBitmap preview;
-    preview.allocN32Pixels(width, height);
-    preview.eraseColor(SK_ColorTRANSPARENT);
-
-    SkBitmap thick_outer_blur;
-    SkBitmap bright_outline;
-    SkBitmap thick_inner_blur;
-
-    preview.setAlphaType(SkAlphaType::kUnpremul_SkAlphaType);
-    thick_outer_blur.setAlphaType(SkAlphaType::kUnpremul_SkAlphaType);
-    bright_outline.setAlphaType(SkAlphaType::kUnpremul_SkAlphaType);
-    thick_inner_blur.setAlphaType(SkAlphaType::kUnpremul_SkAlphaType);
-
-    // Remove most of the alpha channel so as to ignore shadows and other types
-    // of partial transparency when defining the shape of the object.
-    for (int x = 1; x < width; x++) {
-      for (int y = 1; y < height; y++) {
-        const SkColor* src_color =
-            reinterpret_cast<SkColor*>(bitmap.getAddr32(0, y));
-        SkColor* preview_color =
-            reinterpret_cast<SkColor*>(preview.getAddr32(0, y));
-
-        if (SkColorGetA(src_color[x]) < kAlphaChannelFilter) {
-          preview_color[x] = SK_ColorTRANSPARENT;
-        } else {
-          preview_color[x] = SK_ColorWHITE;
-        }
-      }
-    }
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-
-    // Calculate the outer blur first.
-    paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kOuter_SkBlurStyle,
-                                               kBlurSizeOutline));
-    SkIPoint outer_blur_offset;
-    preview.extractAlpha(&thick_outer_blur, &paint, &outer_blur_offset);
-    paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kOuter_SkBlurStyle,
-                                               kBlurSizeThinOutline));
-    SkIPoint bright_outline_offset;
-    preview.extractAlpha(&bright_outline, &paint, &bright_outline_offset);
-
-    // Calculate the inner blur.
-    std::unique_ptr<SkCanvas> canvas = std::make_unique<SkCanvas>(preview);
-    canvas->drawColor(SK_ColorBLACK, SkBlendMode::kSrcOut);
-    paint.setMaskFilter(SkMaskFilter::MakeBlur(SkBlurStyle::kOuter_SkBlurStyle,
-                                               kBlurSizeOutline));
-    SkIPoint thick_inner_blur_offset;
-    preview.extractAlpha(&thick_inner_blur, &paint, &thick_inner_blur_offset);
-
-    SkSamplingOptions sampling;
-    // Mask out the inner blur.
-    paint.setMaskFilter(nullptr);
-    paint.setBlendMode(SkBlendMode::kDstOut);
-    canvas = std::make_unique<SkCanvas>(thick_inner_blur);
-    canvas->drawImage(preview.asImage(), -thick_inner_blur_offset.fX,
-                      -thick_inner_blur_offset.fY, sampling, &paint);
-    canvas->drawRect(
-        SkRect{0, 0, -thick_inner_blur_offset.fX, thick_inner_blur.height()},
-        paint);
-    canvas->drawRect(
-        SkRect{0, 0, -thick_inner_blur.width(), thick_inner_blur_offset.fY},
-        paint);
-
-    // Draw the inner and outer blur.
-    paint.setBlendMode(SkBlendMode::kPlus);
-    canvas = std::make_unique<SkCanvas>(preview);
-    canvas->drawColor(0, SkBlendMode::kClear);
-    canvas->drawImage(thick_inner_blur.asImage(), thick_inner_blur_offset.fX,
-                      thick_inner_blur_offset.fY, sampling, &paint);
-    canvas->drawImage(thick_outer_blur.asImage(), outer_blur_offset.fX,
-                      outer_blur_offset.fY, sampling, &paint);
-
-    // Draw the bright outline.
-    canvas->drawImage(bright_outline.asImage(), bright_outline_offset.fX,
-                      bright_outline_offset.fY, sampling, &paint);
-
-    // Cleanup bitmaps.
-    canvas.reset();
-    bright_outline.reset();
-    thick_outer_blur.reset();
-    thick_inner_blur.reset();
-
-    // Set the color and maximum allowed alpha for each pixel in |preview|.
-    for (int x = 1; x < preview.width(); x++) {
-      for (int y = 1; y < preview.height(); y++) {
-        SkColor* current_color =
-            reinterpret_cast<SkColor*>(preview.getAddr32(0, y));
-
-        int current_alpha = SkColorGetA(current_color[x]);
-        const int maximum_allowed_alpha = kGhostColorOpacity;
-
-        if (current_alpha > maximum_allowed_alpha) {
-          // Cap the current alpha at the maximum allowed alpha.
-          current_alpha = maximum_allowed_alpha;
-        } else if (current_alpha > 0 && current_alpha < maximum_allowed_alpha) {
-          // To reduce blur on the edges of the outline, set the drop off of
-          // alpha values below the |maximum_allowed_alpha| according to the
-          // |kAlphaGradient|.
-          const int new_alpha = (kAlphaGradient * current_alpha) -
-                                (maximum_allowed_alpha * (kAlphaGradient - 1));
-          current_alpha = std::max(0, new_alpha);
-        }
-        current_color[x] = SkColorSetA(SK_ColorWHITE, current_alpha);
-      }
-    }
-
-    icon_outline.AddRepresentation(gfx::ImageSkiaRep(preview, rep.scale()));
-  }
-
-  const SkColor outline_color =
-      is_in_folder_ ? kInFolderGhostColor : kRootGridGhostColor;
-  return gfx::ImageSkiaOperations::CreateColorMask(icon_outline, outline_color);
-}
-
 }  // namespace ash
diff --git a/ash/app_list/views/ghost_image_view.h b/ash/app_list/views/ghost_image_view.h
index 10b3446c5..261f598 100644
--- a/ash/app_list/views/ghost_image_view.h
+++ b/ash/app_list/views/ghost_image_view.h
@@ -13,7 +13,6 @@
 #include "ui/views/controls/image_view.h"
 
 namespace gfx {
-class ImageSkia;
 class Point;
 }  // namespace gfx
 
@@ -58,9 +57,6 @@
   // ui::ImplicitAnimationObserver overrides:
   void OnImplicitAnimationsCompleted() override;
 
-  // Returns an ImageSkia with just an outline of the input ImageSkia.
-  gfx::ImageSkia GetIconOutline(const gfx::ImageSkia& original_icon);
-
   // Whether the view is hiding.
   bool is_hiding_;
 
@@ -73,19 +69,15 @@
   // Page this this view belongs to, used to calculate transition offset.
   int page_;
 
+  // The radius used for drawing the icons shown inside the folder ghost image.
+  int inner_icon_radius_;
+
   // Icon bounds used to determine size and placement of the GhostImageView.
   gfx::Rect icon_bounds_;
 
   // The number of items within the GhostImageView folder.
   absl::optional<size_t> num_items_;
 
-  // The outline of the dragged item's icon. Used as the ghost image.
-  gfx::ImageSkia outline_;
-
-  // The outlines of the top icons within a folder. Used for the folder ghost
-  // image.
-  std::vector<gfx::ImageSkia> inner_folder_icon_outlines_;
-
   // The origins of the top icons within a folder icon. Used for the folder
   // ghost image.
   std::vector<gfx::Point> inner_folder_icon_origins_;
diff --git a/ash/ash_prefs.cc b/ash/ash_prefs.cc
index d6a06e2d..b8a4436 100644
--- a/ash/ash_prefs.cc
+++ b/ash/ash_prefs.cc
@@ -6,7 +6,7 @@
 
 #include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/accessibility/accessibility_controller_impl.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/ambient/ambient_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller_impl.h"
@@ -67,7 +67,7 @@
   contextual_tooltip::RegisterProfilePrefs(registry);
   ClipboardNudgeController::RegisterProfilePrefs(registry);
   desks_restore_util::RegisterProfilePrefs(registry);
-  DockedMagnifierControllerImpl::RegisterProfilePrefs(registry);
+  DockedMagnifierController::RegisterProfilePrefs(registry);
   FullscreenController::RegisterProfilePrefs(registry);
   GestureEducationNotificationController::RegisterProfilePrefs(registry,
                                                                for_test);
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc
index b8e47e8..2305657 100644
--- a/ash/capture_mode/capture_mode_unittests.cc
+++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -4,7 +4,7 @@
 
 #include <memory>
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/accessibility/magnifier/magnifier_glass.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/capture_mode/capture_mode_bar_view.h"
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 8ce69f9..8d3882b 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -734,16 +734,6 @@
 const base::Feature kPluginVmFullscreen{"PluginVmFullscreen",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Controls whether the camera permissions should be shown in the Plugin
-// VM app settings.
-const base::Feature kPluginVmShowCameraPermissions{
-    "PluginVmShowCameraPermissions", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Controls whether the microphone permissions should be shown in the Plugin
-// VM app settings.
-const base::Feature kPluginVmShowMicrophonePermissions{
-    "PluginVmShowMicrophonePermissions", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enables or disables the preference of using constant frame rate for camera
 // when streaming.
 const base::Feature kPreferConstantFrameRate{"PreferConstantFrameRate",
@@ -960,10 +950,6 @@
 const base::Feature kVirtualKeyboardMultipaste{
     "VirtualKeyboardMultipaste", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enable or disable the camera/mic indicators/notifications for VMs.
-const base::Feature kVmCameraMicIndicatorsAndNotifications{
-    "VmCameraMicIndicatorsAndNotifications", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enable or disable the chrome://vm page
 const base::Feature kVmStatusPage{"VmStatusPage",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index 1d7335a..7000ebf 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -276,10 +276,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPipRoundedCorners;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPluginVmFullscreen;
 COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kPluginVmShowCameraPermissions;
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kPluginVmShowMicrophonePermissions;
-COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kPreferConstantFrameRate;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kProjector;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kProjectorFeaturePod;
@@ -358,8 +354,6 @@
 extern const base::Feature kVirtualKeyboardBorderedKey;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kVirtualKeyboardMultipaste;
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kVmCameraMicIndicatorsAndNotifications;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kVmStatusPage;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kWakeOnWifiAllowed;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kWallpaperWebUI;
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index 94072d7..02ad97f 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -4,7 +4,7 @@
 
 #include "ash/display/cursor_window_controller.h"
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/capture_mode/capture_mode_controller.h"
 #include "ash/capture_mode/capture_mode_session.h"
 #include "ash/constants/ash_constants.h"
@@ -165,7 +165,7 @@
     return true;
   }
 
-  if (shell->full_screen_magnifier_controller()->IsEnabled())
+  if (shell->fullscreen_magnifier_controller()->IsEnabled())
     return true;
 
   if (cursor_color_ != kDefaultCursorColor)
diff --git a/ash/display/display_highlight_controller.cc b/ash/display/display_highlight_controller.cc
index ff5fa16..118c8aa 100644
--- a/ash/display/display_highlight_controller.cc
+++ b/ash/display/display_highlight_controller.cc
@@ -4,7 +4,7 @@
 
 #include "ash/display/display_highlight_controller.h"
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/display/window_tree_host_manager.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/session/session_controller_impl.h"
@@ -59,12 +59,12 @@
   window->SetId(kShellWindowId_DisplayIdentificationHighlightWindow);
   ::wm::SetWindowVisibilityAnimationTransition(window, ::wm::ANIMATE_NONE);
 
-  FullScreenMagnifierController* magnification_controller =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnification_controller =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   // Forces a redraw of full-screen magnification in order to reverse
   // magnification on display highlight window performed in
-  // FullScreenMagnifierController::ReDraw(). If redraw is not forced, then the
+  // FullscreenMagnifierController::ReDraw(). If redraw is not forced, then the
   // highlight may not show up around the edges of the display properly until
   // the next redraw.
   if (magnification_controller->IsEnabled()) {
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc
index 0a8454c..d8282f1 100644
--- a/ash/display/root_window_transformers.cc
+++ b/ash/display/root_window_transformers.cc
@@ -6,7 +6,7 @@
 
 #include <cmath>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/host/root_window_transformer.h"
 #include "ash/shell.h"
 #include "ash/utility/transformer_util.h"
@@ -105,8 +105,8 @@
     transform_ = insets_and_rotation_transform;
     insets_and_scale_transform_ = CreateReverseRotatedInsetsTransform(
         display.panel_rotation(), host_insets_, display.device_scale_factor());
-    FullScreenMagnifierController* magnifier =
-        Shell::Get()->full_screen_magnifier_controller();
+    FullscreenMagnifierController* magnifier =
+        Shell::Get()->fullscreen_magnifier_controller();
     if (magnifier) {
       gfx::Transform magnifier_scale = magnifier->GetMagnifierTransform();
       transform_ *= magnifier_scale;
diff --git a/ash/display/root_window_transformers_unittest.cc b/ash/display/root_window_transformers_unittest.cc
index 0bd8ab0..8544e39 100644
--- a/ash/display/root_window_transformers_unittest.cc
+++ b/ash/display/root_window_transformers_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/display/display_util.h"
 #include "ash/display/mirror_window_test_api.h"
 #include "ash/host/root_window_transformer.h"
@@ -165,8 +165,8 @@
 }  // namespace
 
 TEST_F(RootWindowTransformersTest, RotateAndMagnify) {
-  FullScreenMagnifierController* magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   TestEventHandler event_handler;
   Shell::Get()->AddPreTargetHandler(&event_handler);
@@ -278,8 +278,8 @@
   display::test::DisplayManagerTestApi display_manager_test(display_manager());
   display::Display display2 = display_manager_test.GetSecondaryDisplay();
   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
-  FullScreenMagnifierController* magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   magnifier->SetEnabled(true);
   EXPECT_EQ(2.0f, magnifier->GetScale());
@@ -319,8 +319,8 @@
   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
   aura::Window* root_window = root_windows[0];
   ui::test::EventGenerator generator(root_window);
-  FullScreenMagnifierController* magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   magnifier->SetEnabled(true);
   EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
@@ -349,8 +349,8 @@
 TEST_F(RootWindowTransformersTest, ConvertHostToRootCoords) {
   TestEventHandler event_handler;
   Shell::Get()->AddPreTargetHandler(&event_handler);
-  FullScreenMagnifierController* magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
 
   // Test 1
   UpdateDisplay("600x400*2/r@0.8");
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc
index dc7eb2e..de388a6f 100644
--- a/ash/display/window_tree_host_manager.cc
+++ b/ash/display/window_tree_host_manager.cc
@@ -10,7 +10,7 @@
 #include <memory>
 #include <utility>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/magnifier/partial_magnifier_controller.h"
 #include "ash/display/cursor_window_controller.h"
 #include "ash/display/mirror_window_controller.h"
@@ -536,7 +536,7 @@
 
     // Magnifier controllers keep pointers to the current root window.
     // Update them here to avoid accessing them later.
-    Shell::Get()->full_screen_magnifier_controller()->SwitchTargetRootWindow(
+    Shell::Get()->fullscreen_magnifier_controller()->SwitchTargetRootWindow(
         ash_host->AsWindowTreeHost()->window(), false);
     Shell::Get()
         ->partial_magnifier_controller()
diff --git a/ash/events/accessibility_event_rewriter.cc b/ash/events/accessibility_event_rewriter.cc
index 0f163ecf..5d6ddb6 100644
--- a/ash/events/accessibility_event_rewriter.cc
+++ b/ash/events/accessibility_event_rewriter.cc
@@ -5,7 +5,7 @@
 #include "ash/events/accessibility_event_rewriter.h"
 
 #include "ash/accessibility/accessibility_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/switch_access/point_scan_controller.h"
 #include "ash/constants/ash_constants.h"
 #include "ash/keyboard/keyboard_util.h"
@@ -253,26 +253,26 @@
 
 void AccessibilityEventRewriter::OnMagnifierKeyPressed(
     const ui::KeyEvent* event) {
-  FullScreenMagnifierController* controller =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* controller =
+      Shell::Get()->fullscreen_magnifier_controller();
   switch (event->key_code()) {
     case ui::VKEY_UP:
-      controller->SetScrollDirection(FullScreenMagnifierController::SCROLL_UP);
+      controller->SetScrollDirection(FullscreenMagnifierController::SCROLL_UP);
       delegate_->SendMagnifierCommand(MagnifierCommand::kMoveUp);
       break;
     case ui::VKEY_DOWN:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_DOWN);
+          FullscreenMagnifierController::SCROLL_DOWN);
       delegate_->SendMagnifierCommand(MagnifierCommand::kMoveDown);
       break;
     case ui::VKEY_LEFT:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_LEFT);
+          FullscreenMagnifierController::SCROLL_LEFT);
       delegate_->SendMagnifierCommand(MagnifierCommand::kMoveLeft);
       break;
     case ui::VKEY_RIGHT:
       controller->SetScrollDirection(
-          FullScreenMagnifierController::SCROLL_RIGHT);
+          FullscreenMagnifierController::SCROLL_RIGHT);
       delegate_->SendMagnifierCommand(MagnifierCommand::kMoveRight);
       break;
     default:
@@ -282,9 +282,9 @@
 
 void AccessibilityEventRewriter::OnMagnifierKeyReleased(
     const ui::KeyEvent* event) {
-  FullScreenMagnifierController* controller =
-      Shell::Get()->full_screen_magnifier_controller();
-  controller->SetScrollDirection(FullScreenMagnifierController::SCROLL_NONE);
+  FullscreenMagnifierController* controller =
+      Shell::Get()->fullscreen_magnifier_controller();
+  controller->SetScrollDirection(FullscreenMagnifierController::SCROLL_NONE);
   delegate_->SendMagnifierCommand(MagnifierCommand::kMoveStop);
 }
 
@@ -292,7 +292,7 @@
   // Mouse moves are the only pertinent event for accessibility component
   // extensions.
   if (send_mouse_events_ && event.type() == ui::ET_MOUSE_MOVED &&
-      (Shell::Get()->full_screen_magnifier_controller()->IsEnabled() ||
+      (Shell::Get()->fullscreen_magnifier_controller()->IsEnabled() ||
        Shell::Get()->accessibility_controller()->spoken_feedback().enabled())) {
     delegate_->DispatchMouseEvent(ui::Event::Clone(event));
   }
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc
index 7cdcff0..a2640f5 100644
--- a/ash/public/cpp/app_list/app_list_features.cc
+++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -44,7 +44,7 @@
 const base::Feature kEnableAggregatedMlSearchRanking{
     "EnableAggregatedMlSearchRanking", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kNewDragSpecInLauncher{"NewDragSpecInLauncher",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableOmniboxRichEntities{
     "EnableOmniboxRichEntities", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableLauncherSearchNormalization{
diff --git a/ash/public/cpp/desks_helper.h b/ash/public/cpp/desks_helper.h
index fcfea55..905b68d 100644
--- a/ash/public/cpp/desks_helper.h
+++ b/ash/public/cpp/desks_helper.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "ash/public/cpp/ash_public_export.h"
+#include "base/files/file_path.h"
 #include "base/macros.h"
 #include "components/full_restore/restore_data.h"
 
@@ -73,6 +74,11 @@
   // |desk_index| is the active desk. |desk_index| must be valid.
   virtual void SendToDeskAtIndex(aura::Window* window, int desk_index) = 0;
 
+  // Captures the active desk and returns it as a desk template containing
+  // necessary information that can be used to create a same desk.
+  virtual std::unique_ptr<DeskTemplate> CaptureActiveDeskAsTemplate(
+      const base::FilePath& profile_path) = 0;
+
  protected:
   DesksHelper();
   virtual ~DesksHelper();
diff --git a/ash/public/cpp/docked_magnifier_controller.h b/ash/public/cpp/docked_magnifier_controller.h
deleted file mode 100644
index 0808c7c..0000000
--- a/ash/public/cpp/docked_magnifier_controller.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_PUBLIC_CPP_DOCKED_MAGNIFIER_CONTROLLER_H_
-#define ASH_PUBLIC_CPP_DOCKED_MAGNIFIER_CONTROLLER_H_
-
-#include "ash/ash_export.h"
-
-namespace gfx {
-class Point;
-class Rect;
-}
-
-namespace ash {
-
-// Used by Chrome to notify ash of focus change events of nodes in webpages.
-class ASH_EXPORT DockedMagnifierController {
- public:
-  // Returns the instance of docked magnifier.
-  static DockedMagnifierController* Get();
-
-  // Requests that the Docked Magnifier centers its viewport around this given
-  // screen point. This can be used by a client (e.g. Chrome) to notify ash of
-  // focus change events in e.g. webpages when feature is enabled. Note that ash
-  // observes the focus change events of the text input carets in editable nodes
-  // by itself.
-  virtual void CenterOnPoint(const gfx::Point& point_in_screen) = 0;
-
-  // Requests that the Docked Magnifier centers its viewport around the center
-  // of this rect OR aligns the left edge of the viewport with the left edge
-  // of the rect, if the rect is wider than the viewport.
-  virtual void MoveMagnifierToRect(const gfx::Rect& rect_in_screen) = 0;
-
-  // Returns docked magnifier height.
-  virtual int GetMagnifierHeightForTesting() const = 0;
-
- protected:
-  virtual ~DockedMagnifierController() = default;
-};
-
-}  // namespace ash
-
-#endif  // ASH_PUBLIC_CPP_DOCKED_MAGNIFIER_CONTROLLER_H_
diff --git a/ash/public/cpp/quick_answers/quick_answers_state.cc b/ash/public/cpp/quick_answers/quick_answers_state.cc
index 3054dab6..36a66ec5 100644
--- a/ash/public/cpp/quick_answers/quick_answers_state.cc
+++ b/ash/public/cpp/quick_answers/quick_answers_state.cc
@@ -79,9 +79,24 @@
       chromeos::quick_answers::prefs::kQuickAnswersConsented,
       base::BindRepeating(&QuickAnswersState::UpdateUserConsented,
                           base::Unretained(this)));
+  pref_change_registrar_->Add(
+      chromeos::quick_answers::prefs::kQuickAnswersDefinitionEnabled,
+      base::BindRepeating(&QuickAnswersState::UpdateDefinitionEnabled,
+                          base::Unretained(this)));
+  pref_change_registrar_->Add(
+      chromeos::quick_answers::prefs::kQuickAnswersTranslationEnabled,
+      base::BindRepeating(&QuickAnswersState::UpdateTranslationEnabled,
+                          base::Unretained(this)));
+  pref_change_registrar_->Add(
+      chromeos::quick_answers::prefs::kQuickAnswersUnitConverstionEnabled,
+      base::BindRepeating(&QuickAnswersState::UpdateUnitConverstionEnabled,
+                          base::Unretained(this)));
 
   UpdateSettingsEnabled();
   UpdateUserConsented();
+  UpdateDefinitionEnabled();
+  UpdateTranslationEnabled();
+  UpdateUnitConverstionEnabled();
 
   prefs_initialized_ = true;
 }
@@ -131,6 +146,33 @@
   user_consented_ = user_consented;
 }
 
+void QuickAnswersState::UpdateDefinitionEnabled() {
+  auto definition_enabled = pref_change_registrar_->prefs()->GetBoolean(
+      chromeos::quick_answers::prefs::kQuickAnswersDefinitionEnabled);
+  if (definition_enabled_ == definition_enabled) {
+    return;
+  }
+  definition_enabled_ = definition_enabled;
+}
+
+void QuickAnswersState::UpdateTranslationEnabled() {
+  auto translation_enabled = pref_change_registrar_->prefs()->GetBoolean(
+      chromeos::quick_answers::prefs::kQuickAnswersTranslationEnabled);
+  if (translation_enabled_ == translation_enabled) {
+    return;
+  }
+  translation_enabled_ = translation_enabled;
+}
+
+void QuickAnswersState::UpdateUnitConverstionEnabled() {
+  auto unit_conversion_enabled = pref_change_registrar_->prefs()->GetBoolean(
+      chromeos::quick_answers::prefs::kQuickAnswersUnitConverstionEnabled);
+  if (unit_conversion_enabled_ == unit_conversion_enabled) {
+    return;
+  }
+  unit_conversion_enabled_ = unit_conversion_enabled;
+}
+
 void QuickAnswersState::UpdateEligibility() {
   if (chromeos::features::IsQuickAnswersV2Enabled()) {
     if (!pref_change_registrar_)
diff --git a/ash/public/cpp/quick_answers/quick_answers_state.h b/ash/public/cpp/quick_answers/quick_answers_state.h
index e6a6e309..9fa5747f 100644
--- a/ash/public/cpp/quick_answers/quick_answers_state.h
+++ b/ash/public/cpp/quick_answers/quick_answers_state.h
@@ -54,6 +54,9 @@
 
   bool settings_enabled() const { return settings_enabled_; }
   bool user_consented() const { return user_consented_; }
+  bool definition_enabled() const { return definition_enabled_; }
+  bool translation_enabled() const { return translation_enabled_; }
+  bool unit_conversion_enabled() const { return unit_conversion_enabled_; }
   bool is_eligible() const { return is_eligible_; }
 
   void set_eligibility_for_testing(bool is_eligible) {
@@ -66,6 +69,9 @@
   // Called when the related preferences are obtained from the pref service.
   void UpdateSettingsEnabled();
   void UpdateUserConsented();
+  void UpdateDefinitionEnabled();
+  void UpdateTranslationEnabled();
+  void UpdateUnitConverstionEnabled();
 
   // Called when the feature eligibility might change.
   void UpdateEligibility();
@@ -76,6 +82,15 @@
   // Whether the Quick Answers feature has been consented by user.
   bool user_consented_ = false;
 
+  // Whether the Quick Answers definition is enabled.
+  bool definition_enabled_ = true;
+
+  // Whether the Quick Answers translation is enabled.
+  bool translation_enabled_ = true;
+
+  // Whether the Quick Answers unit conversion is enabled.
+  bool unit_conversion_enabled_ = true;
+
   // Whether the Quick Answers feature is eligible. The value is derived from a
   // number of other states.
   bool is_eligible_ = false;
diff --git a/ash/screen_util_unittest.cc b/ash/screen_util_unittest.cc
index 86feff1..783b2257 100644
--- a/ash/screen_util_unittest.cc
+++ b/ash/screen_util_unittest.cc
@@ -6,7 +6,7 @@
 
 #include <memory>
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/root_window_controller.h"
 #include "ash/shelf/shelf.h"
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc
index e792221..9b4b44d 100644
--- a/ash/shelf/scrollable_shelf_view.cc
+++ b/ash/shelf/scrollable_shelf_view.cc
@@ -1889,8 +1889,14 @@
   } else {
     DCHECK_EQ(layout_strategy, kShowLeftArrowButton);
     last_visible_view_index = visible_views_indices.size() - 1;
+
+    // In fuzz tests, `visible_size` may be smaller than
+    // `space_needed_for_button` although it never happens on real devices.
     first_visible_view_index =
-        last_visible_view_index - visible_size / space_needed_for_button + 1;
+        visible_size >= space_needed_for_button
+            ? last_visible_view_index - visible_size / space_needed_for_button +
+                  1
+            : last_visible_view_index;
   }
 
   DCHECK_GE(first_visible_view_index, 0);
diff --git a/ash/shell.cc b/ash/shell.cc
index 412d9990..078181ce 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -19,8 +19,8 @@
 #include "ash/accessibility/accessibility_delegate.h"
 #include "ash/accessibility/autoclick/autoclick_controller.h"
 #include "ash/accessibility/chromevox/key_accessibility_enabler.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/accessibility/magnifier/partial_magnifier_controller.h"
 #include "ash/accessibility/sticky_keys/sticky_keys_controller.h"
 #include "ash/accessibility/ui/accessibility_focus_ring_controller_impl.h"
@@ -439,10 +439,6 @@
       !display_configuration_observer_->save_preference());
 }
 
-DockedMagnifierControllerImpl* Shell::docked_magnifier_controller() {
-  return docked_magnifier_controller_.get();
-}
-
 ::wm::ActivationClient* Shell::activation_client() {
   return focus_controller_.get();
 }
@@ -760,7 +756,7 @@
   // delete them before invalidating the instance.
   // Alphabetical. TODO(oshima): sort.
   autoclick_controller_.reset();
-  full_screen_magnifier_controller_.reset();
+  fullscreen_magnifier_controller_.reset();
   tooltip_controller_.reset();
   event_client_.reset();
   toplevel_window_event_handler_.reset();
@@ -812,7 +808,7 @@
   // NightLightControllerImpl depends on the PrefService as well as the window
   // tree host manager, and must be destructed before them. crbug.com/724231.
   night_light_controller_ = nullptr;
-  // Similarly for DockedMagnifierControllerImpl.
+  // Similarly for DockedMagnifierController.
   docked_magnifier_controller_ = nullptr;
   // Similarly for PrivacyScreenController.
   privacy_screen_controller_ = nullptr;
@@ -1150,8 +1146,8 @@
       std::make_unique<PartialMagnifierController>();
   highlighter_controller_ = std::make_unique<HighlighterController>();
 
-  full_screen_magnifier_controller_ =
-      std::make_unique<FullScreenMagnifierController>();
+  fullscreen_magnifier_controller_ =
+      std::make_unique<FullscreenMagnifierController>();
   mru_window_tracker_ = std::make_unique<MruWindowTracker>();
   assistant_controller_ = std::make_unique<AssistantControllerImpl>();
   if (chromeos::features::IsQuickAnswersEnabled()) {
@@ -1178,7 +1174,7 @@
   high_contrast_controller_ = std::make_unique<HighContrastController>();
 
   docked_magnifier_controller_ =
-      std::make_unique<DockedMagnifierControllerImpl>();
+      std::make_unique<DockedMagnifierController>();
 
   video_detector_ = std::make_unique<VideoDetector>();
 
diff --git a/ash/shell.h b/ash/shell.h
index 1101a8a..e609482 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -115,7 +115,7 @@
 class DisplayPrefs;
 class DisplayShutdownObserver;
 class DisplaySpeakerController;
-class DockedMagnifierControllerImpl;
+class DockedMagnifierController;
 class DragDropController;
 class EventClientImpl;
 class EventRewriterControllerImpl;
@@ -123,7 +123,7 @@
 class FullRestoreController;
 class FocusCycler;
 class FrameThrottlingController;
-class FullScreenMagnifierController;
+class FullscreenMagnifierController;
 class HighContrastController;
 class HighlighterController;
 class HoldingSpaceController;
@@ -379,7 +379,9 @@
     return display_highlight_controller_.get();
   }
 
-  DockedMagnifierControllerImpl* docked_magnifier_controller();
+  DockedMagnifierController* docked_magnifier_controller() {
+    return docked_magnifier_controller_.get();
+  }
   ::wm::CompoundEventFilter* env_filter() { return env_filter_.get(); }
   EventRewriterControllerImpl* event_rewriter_controller() {
     return event_rewriter_controller_.get();
@@ -391,8 +393,8 @@
   ::wm::FocusController* focus_controller() { return focus_controller_.get(); }
   AshFocusRules* focus_rules() { return focus_rules_; }
   FocusCycler* focus_cycler() { return focus_cycler_.get(); }
-  FullScreenMagnifierController* full_screen_magnifier_controller() {
-    return full_screen_magnifier_controller_.get();
+  FullscreenMagnifierController* fullscreen_magnifier_controller() {
+    return fullscreen_magnifier_controller_.get();
   }
   HighlighterController* highlighter_controller() {
     return highlighter_controller_.get();
@@ -770,8 +772,8 @@
   std::unique_ptr<WindowTreeHostManager> window_tree_host_manager_;
   std::unique_ptr<PersistentWindowController> persistent_window_controller_;
   std::unique_ptr<HighContrastController> high_contrast_controller_;
-  std::unique_ptr<FullScreenMagnifierController>
-      full_screen_magnifier_controller_;
+  std::unique_ptr<FullscreenMagnifierController>
+      fullscreen_magnifier_controller_;
   std::unique_ptr<MarkerController> marker_controller_;
   std::unique_ptr<AutoclickController> autoclick_controller_;
   std::unique_ptr<::wm::FocusController> focus_controller_;
@@ -852,7 +854,7 @@
   std::unique_ptr<PartialMagnifierController> partial_magnifier_controller_;
   std::unique_ptr<HighlighterController> highlighter_controller_;
 
-  std::unique_ptr<DockedMagnifierControllerImpl> docked_magnifier_controller_;
+  std::unique_ptr<DockedMagnifierController> docked_magnifier_controller_;
 
   std::unique_ptr<chromeos::SnapController> snap_controller_;
 
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index f923691..ef26bd8 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "ash/ash_export.h"
 #include "base/callback.h"
@@ -17,6 +18,7 @@
 #include "services/device/public/mojom/fingerprint.mojom-forward.h"
 #include "services/media_session/public/cpp/media_session_service.h"
 #include "ui/gfx/native_widget_types.h"
+#include "url/gurl.h"
 
 namespace aura {
 class Window;
@@ -120,9 +122,13 @@
   // Returns true if Chrome was started with --disable-logging-redirect option.
   virtual bool IsLoggingRedirectDisabled() const = 0;
 
-  // Returns empty path is user session has not started yet, or path to the
+  // Returns empty path if user session has not started yet, or path to the
   // primary user Downloads folder if user has already logged in.
   virtual base::FilePath GetPrimaryUserDownloadsFolder() const = 0;
+
+  // Returns the list of URLs that open in the tabs of |window| if the given
+  // given |window| contains a browser frame, otherwise returns an empty list.
+  virtual std::vector<GURL> GetURLsIfApplicable(aura::Window* window) = 0;
 };
 
 }  // namespace ash
diff --git a/ash/system/accessibility/tray_accessibility.cc b/ash/system/accessibility/tray_accessibility.cc
index 2e6c5a4..987869b 100644
--- a/ash/system/accessibility/tray_accessibility.cc
+++ b/ash/system/accessibility/tray_accessibility.cc
@@ -9,7 +9,7 @@
 
 #include "ash/accessibility/accessibility_controller_impl.h"
 #include "ash/accessibility/accessibility_delegate.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/public/cpp/ash_view_ids.h"
 #include "ash/public/cpp/system_tray_client.h"
 #include "ash/resources/vector_icons/vector_icons.h"
diff --git a/ash/system/accessibility/tray_accessibility_unittest.cc b/ash/system/accessibility/tray_accessibility_unittest.cc
index 22122c22..385070cb 100644
--- a/ash/system/accessibility/tray_accessibility_unittest.cc
+++ b/ash/system/accessibility/tray_accessibility_unittest.cc
@@ -7,7 +7,7 @@
 
 #include "ash/accessibility/accessibility_controller_impl.h"
 #include "ash/accessibility/accessibility_observer.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
diff --git a/ash/system/unified/camera_mic_tray_item_view.cc b/ash/system/unified/camera_mic_tray_item_view.cc
index c9280db..dfeaa6e 100644
--- a/ash/system/unified/camera_mic_tray_item_view.cc
+++ b/ash/system/unified/camera_mic_tray_item_view.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <string>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/media_controller.h"
 #include "ash/public/cpp/vm_camera_mic_constants.h"
 #include "ash/session/session_controller_impl.h"
@@ -82,9 +81,7 @@
 void CameraMicTrayItemView::Update() {
   // Hide for non-primary session because we only show the indicators for VMs
   // for now, and VMs support only the primary session.
-  SetVisible(active_ && is_primary_session_ &&
-             base::FeatureList::IsEnabled(
-                 chromeos::features::kVmCameraMicIndicatorsAndNotifications));
+  SetVisible(active_ && is_primary_session_);
 }
 
 std::u16string CameraMicTrayItemView::GetAccessibleNameString() const {
diff --git a/ash/system/unified/camera_mic_tray_item_view_unittest.cc b/ash/system/unified/camera_mic_tray_item_view_unittest.cc
index d15c956..7111177 100644
--- a/ash/system/unified/camera_mic_tray_item_view_unittest.cc
+++ b/ash/system/unified/camera_mic_tray_item_view_unittest.cc
@@ -7,11 +7,9 @@
 #include <memory>
 #include <utility>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/media_controller.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/test/ash_test_base.h"
-#include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -24,8 +22,6 @@
 class BaseCameraMicTrayItemViewTest : public AshTestBase {
  public:
   void SetUpWithType(Type type) {
-    scoped_feature_list_.InitAndEnableFeature(
-        chromeos::features::kVmCameraMicIndicatorsAndNotifications);
     AshTestBase::SetUp();
 
     camera_mic_tray_item_view_ =
@@ -42,7 +38,6 @@
   }
 
  protected:
-  base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<CameraMicTrayItemView> camera_mic_tray_item_view_;
 };
 
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc
index 074690b..71c91d7 100644
--- a/ash/test_shell_delegate.cc
+++ b/ash/test_shell_delegate.cc
@@ -94,4 +94,8 @@
   return base::FilePath();
 }
 
+std::vector<GURL> TestShellDelegate::GetURLsIfApplicable(aura::Window* window) {
+  return std::vector<GURL>();
+}
+
 }  // namespace ash
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h
index 638bc57..fa20b1c3 100644
--- a/ash/test_shell_delegate.h
+++ b/ash/test_shell_delegate.h
@@ -54,6 +54,7 @@
   void SetSessionRestoreInProgress(bool in_progress);
   bool IsLoggingRedirectDisabled() const override;
   base::FilePath GetPrimaryUserDownloadsFolder() const override;
+  std::vector<GURL> GetURLsIfApplicable(aura::Window* window) override;
 
  private:
   // True if the current top window can go back.
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index b36745a2..072f0bb1 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -23,6 +23,7 @@
 #include "ash/wm/desks/desks_animations.h"
 #include "ash/wm/desks/desks_restore_util.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/full_restore/full_restore_util.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/overview/overview_grid.h"
@@ -35,14 +36,22 @@
 #include "ash/wm/window_util.h"
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/check.h"
 #include "base/check_op.h"
 #include "base/containers/contains.h"
 #include "base/containers/unique_ptr_adapters.h"
+#include "base/files/file_path.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
 #include "base/numerics/ranges.h"
 #include "base/timer/timer.h"
+#include "components/full_restore/app_launch_info.h"
+#include "components/full_restore/app_restore_data.h"
+#include "components/full_restore/full_restore_save_handler.h"
+#include "components/full_restore/full_restore_utils.h"
+#include "components/full_restore/restore_data.h"
+#include "components/full_restore/window_info.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/wm/public/activation_client.h"
@@ -819,6 +828,69 @@
                              DesksMoveWindowFromActiveDeskSource::kSendToDesk);
 }
 
+std::unique_ptr<DeskTemplate> DesksController::CaptureActiveDeskAsTemplate(
+    const base::FilePath& profile_path) {
+  DCHECK(!profile_path.empty());
+
+  // Get |full_restore_data| from FullRestoreSaveHandler which contains all
+  // restoring information for all apps running on the device.
+  const ::full_restore::RestoreData* full_restore_data =
+      ::full_restore::FullRestoreSaveHandler::GetInstance()->GetRestoreData(
+          profile_path);
+  DCHECK(full_restore_data);
+
+  std::unique_ptr<DeskTemplate> desk_template =
+      std::make_unique<DeskTemplate>();
+  desk_template->set_desk_name(active_desk_->name());
+
+  // Construct |restore_data| for |desk_template| from |full_restore_data|.
+  std::unique_ptr<full_restore::RestoreData> restore_data =
+      std::make_unique<full_restore::RestoreData>();
+  auto* shell = Shell::Get();
+  auto mru_windows =
+      shell->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
+  for (auto* window : mru_windows) {
+    const std::string* const app_id = window->GetProperty(kAppIDKey);
+    if (!app_id)
+      continue;
+
+    const int32_t window_id = window->GetProperty(full_restore::kWindowIdKey);
+
+    std::unique_ptr<full_restore::AppLaunchInfo> app_launch_info =
+        std::make_unique<full_restore::AppLaunchInfo>(*app_id, window_id);
+    // Use the latest urls for the window instead of reading it from
+    // |full_restore_data| as urls may have changed after app launch and
+    // currently urls are not tracked in |full_restore_data| anyway.
+    app_launch_info->urls =
+        shell->shell_delegate()->GetURLsIfApplicable(window);
+    // Read all other relevant app launching information from
+    // |full_restore_data| to |app_launch_info|.
+    const full_restore::AppRestoreData* app_restore_data =
+        full_restore_data->GetAppRestoreData(*app_id, window_id);
+    if (app_restore_data) {
+      app_launch_info->event_flag = app_restore_data->event_flag;
+      app_launch_info->container = app_restore_data->container;
+      app_launch_info->disposition = app_restore_data->disposition;
+      app_launch_info->file_paths = app_restore_data->file_paths;
+      if (app_restore_data->intent.has_value() &&
+          app_restore_data->intent.value()) {
+        app_launch_info->intent = app_restore_data->intent.value()->Clone();
+      }
+    }
+    restore_data->AddAppLaunchInfo(std::move(app_launch_info));
+
+    std::unique_ptr<full_restore::WindowInfo> window_info = BuildWindowInfo(
+        window, /*activation_index=*/absl::nullopt, mru_windows);
+    // Clear WindowInfo's |desk_id| as a window in template will always launch
+    // to a newly created desk.
+    window_info->desk_id.reset();
+    restore_data->ModifyWindowInfo(*app_id, window_id, *window_info);
+  }
+  desk_template->set_desk_restore_data(std::move(restore_data));
+
+  return desk_template;
+}
+
 void DesksController::UpdateDesksDefaultNames() {
   size_t i = 0;
   for (auto& desk : desks_) {
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 5bff12e02..0a0c4e05 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -238,6 +238,8 @@
   std::u16string GetDeskName(int index) const override;
   int GetNumberOfDesks() const override;
   void SendToDeskAtIndex(aura::Window* window, int desk_index) override;
+  std::unique_ptr<DeskTemplate> CaptureActiveDeskAsTemplate(
+      const base::FilePath& profile_path) override;
 
   // Updates the default names (e.g. "Desk 1", "Desk 2", ... etc.) given to the
   // desks. This is called when desks are added, removed or reordered to update
diff --git a/ash/wm/full_restore/full_restore_controller.cc b/ash/wm/full_restore/full_restore_controller.cc
index c823aab8..138a259 100644
--- a/ash/wm/full_restore/full_restore_controller.cc
+++ b/ash/wm/full_restore/full_restore_controller.cc
@@ -15,6 +15,7 @@
 #include "ash/shell.h"
 #include "ash/wm/container_finder.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/full_restore/full_restore_util.h"
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_positioning_utils.h"
@@ -432,80 +433,20 @@
     return;
   }
 
-  int window_activation_index;
-  if (activation_index) {
-    window_activation_index = *activation_index;
-  } else {
-    auto mru_windows =
+  aura::Window::Windows mru_windows;
+  // We only need |mru_windows| if |activation_index| is nullopt as
+  // |mru_windows| will be used to calculated the window's activation index when
+  // it's not provided by |activation_index|.
+  if (!activation_index.has_value()) {
+    mru_windows =
         Shell::Get()->mru_window_tracker()->BuildMruWindowList(kAllDesks);
-    auto it = std::find(mru_windows.begin(), mru_windows.end(), window);
-    if (it != mru_windows.end())
-      window_activation_index = it - mru_windows.begin();
   }
-
-  full_restore::WindowInfo window_info;
-  window_info.activation_index = window_activation_index;
-  window_info.window = window;
-  window_info.desk_id = window->GetProperty(aura::client::kWindowWorkspaceKey);
-  if (window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) {
-    // Only save |visible_on_all_workspaces| field if it's true to reduce file
-    // storage size.
-    window_info.visible_on_all_workspaces = true;
-  }
-
-  // If override bounds and window state are available (in tablet mode), save
-  // those bounds.
-  gfx::Rect* override_bounds = window->GetProperty(kRestoreBoundsOverrideKey);
-  if (override_bounds) {
-    window_info.current_bounds = *override_bounds;
-    // Snapped state can be restored from tablet onto clamshell, so we do not
-    // use the restore override state here.
-    window_info.window_state_type =
-        window_state->IsSnapped()
-            ? window_state->GetStateType()
-            : window->GetProperty(kRestoreWindowStateTypeOverrideKey);
-  } else {
-    // If there are restore bounds, use those as current bounds. On restore, for
-    // states with restore bounds (maximized, minimized, snapped, etc), they
-    // will take the current bounds as their restore bounds and have the current
-    // bounds determined by the system.
-    window_info.current_bounds = window_state->HasRestoreBounds()
-                                     ? window_state->GetRestoreBoundsInScreen()
-                                     : window->GetBoundsInScreen();
-    // Full restore does not support restoring fullscreen windows. If a window
-    // is fullscreen save the pre-fullscreen window state instead.
-    window_info.window_state_type =
-        window_state->IsFullscreen()
-            ? chromeos::ToWindowStateType(
-                  window->GetProperty(aura::client::kPreFullscreenShowStateKey))
-            : window_state->GetStateType();
-  }
-
-  // Populate the pre minimized show state field if the window is minimized.
-  if (window_state->IsMinimized()) {
-    window_info.pre_minimized_show_state_type =
-        window->GetProperty(aura::client::kPreMinimizedShowStateKey);
-  }
-
-  window_info.display_id =
-      display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
-
-  // Save window size restriction of ARC app window.
-  if (IsArcWindow(window)) {
-    views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
-    if (widget) {
-      auto extra = full_restore::WindowInfo::ArcExtraInfo();
-      extra.maximum_size = widget->GetMaximumSize();
-      extra.minimum_size = widget->GetMinimumSize();
-      extra.title = window->GetTitle();
-      window_info.arc_extra_info = extra;
-    }
-  }
-
-  full_restore::SaveWindowInfo(window_info);
+  std::unique_ptr<full_restore::WindowInfo> window_info =
+      BuildWindowInfo(window, activation_index, mru_windows);
+  full_restore::SaveWindowInfo(*window_info);
 
   if (g_save_window_callback_for_testing)
-    g_save_window_callback_for_testing.Run(window_info);
+    g_save_window_callback_for_testing.Run(*window_info);
 }
 
 void FullRestoreController::RestoreStateTypeAndClearLaunchedKey(
diff --git a/ash/wm/full_restore/full_restore_util.cc b/ash/wm/full_restore/full_restore_util.cc
new file mode 100644
index 0000000..ee54cb4
--- /dev/null
+++ b/ash/wm/full_restore/full_restore_util.cc
@@ -0,0 +1,98 @@
+// 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 "ash/wm/full_restore/full_restore_util.h"
+
+#include "ash/public/cpp/app_types_util.h"
+#include "ash/public/cpp/window_properties.h"
+#include "ash/shell.h"
+#include "ash/wm/mru_window_tracker.h"
+#include "ash/wm/window_state.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+std::unique_ptr<::full_restore::WindowInfo> BuildWindowInfo(
+    aura::Window* window,
+    absl::optional<int> activation_index,
+    const std::vector<aura::Window*>& mru_windows) {
+  std::unique_ptr<::full_restore::WindowInfo> window_info =
+      absl::make_unique<::full_restore::WindowInfo>();
+
+  int window_activation_index = -1;
+  if (activation_index) {
+    window_activation_index = *activation_index;
+  } else {
+    auto it = std::find(mru_windows.begin(), mru_windows.end(), window);
+    if (it != mru_windows.end())
+      window_activation_index = it - mru_windows.begin();
+  }
+  if (window_activation_index != -1)
+    window_info->activation_index = window_activation_index;
+  window_info->window = window;
+  window_info->desk_id = window->GetProperty(aura::client::kWindowWorkspaceKey);
+  if (window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey)) {
+    // Only save |visible_on_all_workspaces| field if it's true to reduce file
+    // storage size.
+    window_info->visible_on_all_workspaces = true;
+  }
+
+  // If override bounds and window state are available (in tablet mode), save
+  // those bounds.
+  gfx::Rect* override_bounds = window->GetProperty(kRestoreBoundsOverrideKey);
+  WindowState* window_state = WindowState::Get(window);
+  if (override_bounds) {
+    window_info->current_bounds = *override_bounds;
+    // Snapped state can be restored from tablet onto clamshell, so we do not
+    // use the restore override state here.
+    window_info->window_state_type =
+        window_state->IsSnapped()
+            ? window_state->GetStateType()
+            : window->GetProperty(kRestoreWindowStateTypeOverrideKey);
+  } else {
+    // If there are restore bounds, use those as current bounds. On restore, for
+    // states with restore bounds (maximized, minimized, snapped, etc), they
+    // will take the current bounds as their restore bounds and have the current
+    // bounds determined by the system.
+    window_info->current_bounds = window_state->HasRestoreBounds()
+                                      ? window_state->GetRestoreBoundsInScreen()
+                                      : window->GetBoundsInScreen();
+    // Full restore does not support restoring fullscreen windows. If a window
+    // is fullscreen save the pre-fullscreen window state instead.
+    window_info->window_state_type =
+        window_state->IsFullscreen()
+            ? chromeos::ToWindowStateType(
+                  window->GetProperty(aura::client::kPreFullscreenShowStateKey))
+            : window_state->GetStateType();
+  }
+
+  // Populate the pre minimized show state field if the window is minimized.
+  if (window_state->IsMinimized()) {
+    window_info->pre_minimized_show_state_type =
+        window->GetProperty(aura::client::kPreMinimizedShowStateKey);
+  }
+
+  window_info->display_id =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(window).id();
+
+  // Save window size restriction of ARC app window.
+  if (IsArcWindow(window)) {
+    views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
+    if (widget) {
+      auto extra = full_restore::WindowInfo::ArcExtraInfo();
+      extra.maximum_size = widget->GetMaximumSize();
+      extra.minimum_size = widget->GetMinimumSize();
+      extra.title = window->GetTitle();
+      window_info->arc_extra_info = extra;
+    }
+  }
+
+  return window_info;
+}
+
+}  // namespace ash
diff --git a/ash/wm/full_restore/full_restore_util.h b/ash/wm/full_restore/full_restore_util.h
new file mode 100644
index 0000000..a870b05
--- /dev/null
+++ b/ash/wm/full_restore/full_restore_util.h
@@ -0,0 +1,28 @@
+// 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 ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
+#define ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
+
+#include "ash/ash_export.h"
+#include "components/full_restore/window_info.h"
+
+namespace aura {
+class Window;
+}
+
+namespace ash {
+
+// Builds the WindowInfo for |window|. Optionally passes |activation_index|,
+// which is used to set |WindowInfo.activation_index| if it has value.
+// Otherwise, |WindowInfo.activation_index| will be calculated from
+// |mru_windows|.
+ASH_EXPORT std::unique_ptr<::full_restore::WindowInfo> BuildWindowInfo(
+    aura::Window* window,
+    absl::optional<int> activation_index,
+    const std::vector<aura::Window*>& mru_windows);
+
+}  // namespace ash
+
+#endif  // ASH_WM_FULL_RESTORE_FULL_RESTORE_UTIL_H_
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc
index 41d5ed8..6a25487 100644
--- a/ash/wm/overview/overview_highlight_controller.cc
+++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -4,8 +4,8 @@
 
 #include "ash/wm/overview/overview_highlight_controller.h"
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/shell.h"
 #include "ash/wm/desks/desk_mini_view.h"
 #include "ash/wm/desks/desk_name_view.h"
@@ -269,10 +269,10 @@
   // Note that both magnifiers are mutually exclusive. The overview "focus"
   // works differently from regular focusing so we need to update the magnifier
   // manually here.
-  DockedMagnifierControllerImpl* docked_magnifier =
+  DockedMagnifierController* docked_magnifier =
       Shell::Get()->docked_magnifier_controller();
-  FullScreenMagnifierController* fullscreen_magnifier =
-      Shell::Get()->full_screen_magnifier_controller();
+  FullscreenMagnifierController* fullscreen_magnifier =
+      Shell::Get()->fullscreen_magnifier_controller();
   const gfx::Point point_of_interest =
       highlighted_view_->GetMagnifierFocusPointInScreen();
   if (docked_magnifier->GetEnabled())
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index bd1be6d..3895d91 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -13,7 +13,7 @@
 #include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/accelerators/exit_warning_handler.h"
 #include "ash/accessibility/accessibility_controller_impl.h"
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/constants/app_types.h"
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index 78f478e..38b72dc4 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -10,7 +10,7 @@
 #include <utility>
 #include <vector>
 
-#include "ash/accessibility/magnifier/docked_magnifier_controller_impl.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/constants/app_types.h"
 #include "ash/display/screen_orientation_controller.h"
diff --git a/base/allocator/partition_allocator/partition_alloc-inl.h b/base/allocator/partition_allocator/partition_alloc-inl.h
index 4bceb2e7..43bcbed 100644
--- a/base/allocator/partition_allocator/partition_alloc-inl.h
+++ b/base/allocator/partition_allocator/partition_alloc-inl.h
@@ -12,10 +12,6 @@
 #include "base/allocator/partition_allocator/random.h"
 #include "build/build_config.h"
 
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
 // Prefetch *x into memory.
 #if defined(__clang__) || defined(COMPILER_GCC)
 #define PA_PREFETCH(x) __builtin_prefetch(x)
@@ -30,12 +26,6 @@
 // boringssl/src/crypto/mem.c. (Copying and pasting is bad, but //base can't
 // depend on //third_party, and this is small enough.)
 ALWAYS_INLINE void SecureMemset(void* ptr, uint8_t value, size_t size) {
-#if defined(OS_WIN)
-  if (value == 0) {
-    SecureZeroMemory(ptr, size);
-    return;
-  }
-#endif  // defined(OS_WIN)
   memset(ptr, value, size);
 
   // As best as we can tell, this is sufficient to break any optimisations that
diff --git a/base/timer/timer.cc b/base/timer/timer.cc
index 7e607145..d5a669d 100644
--- a/base/timer/timer.cc
+++ b/base/timer/timer.cc
@@ -11,13 +11,38 @@
 #include "base/check.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/tick_clock.h"
+#include "build/build_config.h"
 
 namespace base {
 namespace internal {
 
+namespace {
+
+// The reason for which the timer's scheduled task was invoked.
+enum ScheduledTaskInvokedReason {
+  kStopped,      // The timer fired for a stopped timer so nothing was done.
+  kRescheduled,  // The timer fired before the desired run time so the user task
+                 // was rescheduled for later. This can happens when the timer
+                 // is restarted while it is already running.
+  kReady,        // The timer fired at the desired run time so the task is ready
+                 // to be invoked.
+  kMaxValue
+};
+
+void RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason reason) {
+  // Recording this histogram breaks a fuchsia test.
+#if !defined(OS_FUCHSIA)
+  UMA_HISTOGRAM_ENUMERATION("Scheduler.TimerBase.ScheduledTaskInvokedReason",
+                            reason);
+#endif
+}
+
+}  // namespace
+
 // TaskDestructionDetector's role is to detect when the scheduled task is
 // deleted without being executed. It can be disabled when the timer no longer
 // wants to be notified.
@@ -193,8 +218,10 @@
   task_destruction_detector.reset();
 
   // The timer may have been stopped.
-  if (!is_running_)
+  if (!is_running_) {
+    RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason::kStopped);
     return;
+  }
 
   // First check if we need to delay the task because of a new target time.
   if (desired_run_time_ > scheduled_run_time_) {
@@ -204,12 +231,15 @@
     // Task runner may have called us late anyway, so only post a continuation
     // task if the |desired_run_time_| is in the future.
     if (desired_run_time_ > now) {
+      RecordScheduledTaskInvokedReason(
+          ScheduledTaskInvokedReason::kRescheduled);
       // Post a new task to span the remaining time.
       ScheduleNewTask(desired_run_time_ - now);
       return;
     }
   }
 
+  RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason::kReady);
   RunUserTask();
   // No more member accesses here: |this| could be deleted at this point.
 }
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index 2cf0602c..d88933f5 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -32,6 +32,7 @@
               r'.*_pb2\.py',
               r'.*list_java_targets\.py',  # crbug.com/1100664
               r'.*fast_local_dev_server\.py',  # crbug.com/1100664
+              r'.*incremental_javac_test_android_library.py', #crbug.com/1100664
           ] + build_pys,
           extra_paths_list=[
               J(),
diff --git a/build/android/gyp/compile_java.py b/build/android/gyp/compile_java.py
index 0d5f4da..ce57ea6 100755
--- a/build/android/gyp/compile_java.py
+++ b/build/android/gyp/compile_java.py
@@ -471,6 +471,11 @@
         if (all_changed_paths_are_java and not changes.HasStringChanges()
             and os.path.exists(jar_path)
             and (jar_info_path is None or os.path.exists(jar_info_path))):
+          # Log message is used by tests to determine whether partial javac
+          # optimization was used.
+          logging.info('Using partial javac optimization for %s compile' %
+                       (jar_path))
+
           # Header jar corresponding to |java_files| did not change.
           # As a build speed optimization (crbug.com/1170778), re-compile only
           # java files which have changed. Re-use old jar .info file.
diff --git a/build/android/java/test/IncrementalJavacTest.java b/build/android/java/test/IncrementalJavacTest.java
new file mode 100644
index 0000000..c83178aa
--- /dev/null
+++ b/build/android/java/test/IncrementalJavacTest.java
@@ -0,0 +1,32 @@
+// 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.
+
+package test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Checks that build picked up changes to
+ * {@link NoSignatureChangeIncrementalJavacTestHelper#foo()}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public final class IncrementalJavacTest {
+    @Test
+    public void testNoSignatureChange() {
+        NoSignatureChangeIncrementalJavacTestHelper helper =
+                new NoSignatureChangeIncrementalJavacTestHelper();
+        // #foo() should return updated value.
+        assertEquals("foo2", helper.foo());
+
+        // #bar() should not crash.
+        assertEquals("bar", helper.bar());
+    }
+}
diff --git a/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper.template b/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper.template
new file mode 100644
index 0000000..bb0f822
--- /dev/null
+++ b/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper.template
@@ -0,0 +1,18 @@
+// 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.
+
+package test;
+
+public class NoSignatureChangeIncrementalJavacTestHelper {
+    private NoSignatureChangeIncrementalJavacTestHelper2 mHelper2 =
+            new NoSignatureChangeIncrementalJavacTestHelper2();
+
+    public String foo() {
+      return "{{foo_return_value}}";
+  }
+
+  public String bar() {
+    return mHelper2.bar();
+  }
+}
diff --git a/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper2.java b/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper2.java
new file mode 100644
index 0000000..12d41ea
--- /dev/null
+++ b/build/android/java/test/NoSignatureChangeIncrementalJavacTestHelper2.java
@@ -0,0 +1,11 @@
+// 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.
+
+package test;
+
+public class NoSignatureChangeIncrementalJavacTestHelper2 {
+    public String bar() {
+        return "bar";
+    }
+}
diff --git a/build/android/test/BUILD.gn b/build/android/test/BUILD.gn
index ef8e3104..6adec19 100644
--- a/build/android/test/BUILD.gn
+++ b/build/android/test/BUILD.gn
@@ -84,4 +84,14 @@
       },
     ]
   }
+
+  # Tests that builds which use incremental javac are valid.
+  junit_binary("incremental_javac_junit_tests") {
+    sources = [ "../java/test/IncrementalJavacTest.java" ]
+    deps = [
+      "incremental_javac_gn:no_signature_change_prebuilt_java",
+      "//base:base_junit_test_support",
+      "//third_party/junit",
+    ]
+  }
 }
diff --git a/build/android/test/incremental_javac_gn/BUILD.gn b/build/android/test/incremental_javac_gn/BUILD.gn
new file mode 100644
index 0000000..18c6374
--- /dev/null
+++ b/build/android/test/incremental_javac_gn/BUILD.gn
@@ -0,0 +1,98 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+declare_args() {
+  incremental_javac_test_toggle_gn = false
+}
+
+all_test_sources = [
+  "../../java/test/NoSignatureChangeIncrementalJavacTestHelper.template",
+  "../../java/test/NoSignatureChangeIncrementalJavacTestHelper2.java",
+]
+
+template("incremental_javac_prebuilt") {
+  _out_jar = "${target_gen_dir}/${target_name}.jar"
+
+  action(target_name) {
+    script = "incremental_javac_test_android_library.py"
+    forward_variables_from(invoker,
+                           [
+                             "sources",
+                             "testonly",
+                           ])
+    deps = [ invoker.toggle_gn_target ]
+
+    inputs = []
+    if (defined(invoker.pydeps)) {
+      foreach(_pydeps_file, invoker.pydeps) {
+        _pydeps_file_lines = []
+        _pydeps_file_lines = read_file(_pydeps_file, "list lines")
+        _pydeps_entries = []
+        _pydeps_entries = filter_exclude(_pydeps_file_lines, [ "#*" ])
+        _pydeps_file_dir = get_path_info(_pydeps_file, "dir")
+        inputs += rebase_path(_pydeps_entries, ".", _pydeps_file_dir)
+      }
+    }
+
+    outputs = [ _out_jar ]
+
+    args = [
+      "--target-name",
+      get_label_info("${invoker.toggle_gn_target}", "label_no_toolchain"),
+      "--gn-args-path",
+      "args.gn",
+      "--out-dir",
+      rebase_path("${target_out_dir}/${target_name}/incremental_javac_out",
+                  root_build_dir),
+      "--out-jar",
+      rebase_path(_out_jar, root_build_dir),
+    ]
+  }
+}
+
+# Use jinja_template() instead of java_cpp_template() because incremental builds
+# are not done when non-.java files change.
+jinja_template("changing_javagen") {
+  input = "../../java/test/NoSignatureChangeIncrementalJavacTestHelper.template"
+  assert(filter_include(all_test_sources, [ input ]) != [])
+  output =
+      "${target_gen_dir}/test/NoSignatureChangeIncrementalJavacTestHelper.java"
+  if (incremental_javac_test_toggle_gn) {
+    variables = [ "foo_return_value=foo2" ]
+  } else {
+    variables = [ "foo_return_value=foo" ]
+  }
+}
+
+android_library("changing_java") {
+  testonly = true
+
+  # Should not be re-compiled during incremental build.
+  sources =
+      [ "../../java/test/NoSignatureChangeIncrementalJavacTestHelper2.java" ]
+  assert(filter_include(all_test_sources, sources) != [])
+
+  # Should be recompiled during incremental build.
+  sources += get_target_outputs(":changing_javagen")
+  deps = [ ":changing_javagen" ]
+}
+
+# Compiles :changing_java with and without |incremental_javac_test_toggle_gn|.
+incremental_javac_prebuilt("no_signature_change_prebuilt_generator") {
+  testonly = true
+  sources = all_test_sources
+  toggle_gn_target = ":changing_java"
+  pydeps = [ "//build/android/gyp/compile_java.pydeps" ]
+}
+
+android_java_prebuilt("no_signature_change_prebuilt_java") {
+  testonly = true
+  _generator_outputs =
+      get_target_outputs(":no_signature_change_prebuilt_generator")
+  jar_paths = filter_include(_generator_outputs, [ "*.jar" ])
+  jar_path = jar_paths[0]
+  deps = [ ":no_signature_change_prebuilt_generator" ]
+}
diff --git a/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py b/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py
new file mode 100755
index 0000000..c84cff0d
--- /dev/null
+++ b/build/android/test/incremental_javac_gn/incremental_javac_test_android_library.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+#
+# 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.
+"""Compiles twice: With incremental_javac_test_toggle_gn=[false, true]
+
+The purpose of compiling the target twice is to test that builds generated by
+the incremental build code path are valid.
+"""
+
+import argparse
+import os
+import pathlib
+import subprocess
+import shutil
+
+_CHROMIUM_SRC = pathlib.Path(__file__).resolve().parents[4].resolve()
+_NINJA_PATH = _CHROMIUM_SRC / 'third_party' / 'depot_tools' / 'ninja'
+
+# Relative to _CHROMIUM_SRC
+_GN_SRC_REL_PATH = 'third_party/depot_tools/gn'
+
+_USING_PARTIAL_JAVAC_MSG = 'Using partial javac optimization'
+
+
+def _raise_command_exception(args, returncode, output):
+  """Raises an exception whose message describes a command failure.
+
+    Args:
+      args: shell command-line (as passed to subprocess.Popen())
+      returncode: status code.
+      output: command output.
+    Raises:
+      a new Exception.
+    """
+  message = ('Command failed with status {}: {}\n'
+             'Output:-----------------------------------------\n{}\n'
+             '------------------------------------------------\n').format(
+                 returncode, args, output)
+  raise Exception(message)
+
+
+def _run_command(args, check_returncode=True, cwd=None, env=None):
+  """Runs shell command. Raises exception if command fails."""
+  p = subprocess.Popen(args,
+                       stdout=subprocess.PIPE,
+                       stderr=subprocess.STDOUT,
+                       cwd=cwd,
+                       env=env,
+                       universal_newlines=True)
+  pout, _ = p.communicate()
+  if check_returncode and p.returncode != 0:
+    _raise_command_exception(args, p.returncode, pout)
+  return pout
+
+
+def _copy_and_append_gn_args(src_args_path, dest_args_path, extra_args):
+  """Copies args.gn.
+
+    Args:
+      src_args_path: args.gn file to copy.
+      dest_args_path: Copy file destination.
+      extra_args: Text to append to args.gn after copy.
+    """
+  with open(src_args_path) as f:
+    initial_args_str = f.read()
+
+  with open(dest_args_path, 'w') as f:
+    f.write(initial_args_str)
+    f.write('\n')
+
+    # Write |extra_args| after |initial_args_str| so that |extra_args|
+    # overwrites |initial_args_str| in the case of duplicate entries.
+    f.write('\n'.join(extra_args))
+
+
+def _run_gn(args, check_returncode=True):
+  _run_command([_GN_SRC_REL_PATH] + args,
+               check_returncode=check_returncode,
+               cwd=_CHROMIUM_SRC)
+
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--target-name',
+                      required=True,
+                      help='name of target to build with and without ' +
+                      'incremental_javac_test_toggle_gn=true')
+  parser.add_argument('--gn-args-path',
+                      required=True,
+                      help='Path to args.gn file to copy args from.')
+  parser.add_argument('--out-dir',
+                      required=True,
+                      help='Path to output directory to use for compilation.')
+  parser.add_argument('--out-jar',
+                      required=True,
+                      help='Path where output jar should be stored.')
+  options = parser.parse_args()
+
+  options.out_dir = pathlib.Path(options.out_dir).resolve()
+
+  options.out_dir.mkdir(parents=True, exist_ok=True)
+
+  # Clear the output directory so that first compile is not an incremental
+  # build.
+  # This will make the test fail in the scenario that:
+  # - The output directory contains a previous build generated by this script.
+  # - Incremental builds are broken and are a no-op.
+  _run_gn(['clean', options.out_dir.relative_to(_CHROMIUM_SRC)],
+          check_returncode=False)
+
+  out_gn_args_path = options.out_dir / 'args.gn'
+  extra_gn_args = [
+      'treat_warnings_as_errors = true',
+      # GOMA does not work with non-standard output directories.
+      'use_goma = false',
+  ]
+  _copy_and_append_gn_args(options.gn_args_path, out_gn_args_path,
+                           extra_gn_args)
+
+  _run_gn([
+      '--root-target=' + options.target_name, 'gen',
+      options.out_dir.relative_to(_CHROMIUM_SRC)
+  ])
+
+  ninja_env = os.environ.copy()
+  ninja_env['JAVAC_DEBUG'] = '1'
+
+  # Strip leading '//'
+  gn_path = options.target_name[2:]
+  ninja_args = [_NINJA_PATH, '-C', options.out_dir, gn_path]
+  ninja_output = _run_command(ninja_args, env=ninja_env)
+  if _USING_PARTIAL_JAVAC_MSG in ninja_output:
+    raise Exception("Incorrectly using partial javac for clean compile.")
+
+  _copy_and_append_gn_args(
+      options.gn_args_path, out_gn_args_path,
+      extra_gn_args + ['incremental_javac_test_toggle_gn = true'])
+  ninja_output = _run_command(ninja_args, env=ninja_env)
+  if _USING_PARTIAL_JAVAC_MSG not in ninja_output:
+    raise Exception("Not using partial javac for incremental compile.")
+
+  expected_output_path = "{}/lib.java/{}.jar".format(options.out_dir,
+                                                     gn_path.replace(':', '/'))
+  if not os.path.exists(expected_output_path):
+    raise Exception("{} not created.".format(expected_output_path))
+
+  shutil.copyfile(expected_output_path, options.out_jar)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni
index 04ad162b..0ccbcb2 100644
--- a/build/config/chromeos/rules.gni
+++ b/build/config/chromeos/rules.gni
@@ -366,7 +366,7 @@
     # The following expression filters out all non-critical tests. See the link
     # below for more details:
     # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md
-    tast_attr_expr = "\"group:mainline\" && \"dep:chrome\" && !\"dep:lacros\""
+    tast_attr_expr = "\"group:mainline\" && \"dep:chrome\""
 
     if (defined(enable_tast_informational_tests) &&
         enable_tast_informational_tests) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 9673438..6961f27 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-5.20210616.2.1
+5.20210616.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 9673438..6961f27 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-5.20210616.2.1
+5.20210616.3.1
diff --git a/build/toolchain/rbe.gni b/build/toolchain/rbe.gni
index 9f6380e..97d5518e 100644
--- a/build/toolchain/rbe.gni
+++ b/build/toolchain/rbe.gni
@@ -27,7 +27,7 @@
 }
 
 # Configuration file selection based on operating system.
-if (is_linux || is_android) {
+if (is_linux || is_android || is_chromeos) {
   rbe_cc_cfg_file = "${rbe_cfg_dir}/rewrapper_linux.cfg"
 }
 if (is_win) {
diff --git a/buildtools/reclient_cfgs/win-cross-experiments/rewrapper_windows.cfg b/buildtools/reclient_cfgs/win-cross-experiments/rewrapper_windows.cfg
index aa639377..cc19ec6 100644
--- a/buildtools/reclient_cfgs/win-cross-experiments/rewrapper_windows.cfg
+++ b/buildtools/reclient_cfgs/win-cross-experiments/rewrapper_windows.cfg
@@ -1,5 +1,5 @@
-# llvmorg-13-init-12576-g643b6407-1

-platform=container-image=docker://gcr.io/goma-foundry-experiments/re-client/chromium-win-cross@sha256:49865ac8a5052081ea38b764645b54ee9bf1707f70cd58fb8b526aaea8fb238a,OSFamily=Linux

+# llvmorg-13-init-12881-g4017d033-1

+platform=container-image=docker://gcr.io/goma-foundry-experiments/re-client/chromium-win-cross@sha256:681c742fdc89c79aaafde0ebf3e3e9e026643e37e6d06a32665109e754c6531f,OSFamily=Linux

 server_address=pipe://reproxy.pipe

 labels=type=compile,compiler=clang-cl,lang=cpp

 exec_strategy=remote_local_fallback

diff --git a/chrome/VERSION b/chrome/VERSION
index cdf95e28..cf8d3cd 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=93
 MINOR=0
-BUILD=4545
+BUILD=4546
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 1d86513..fa07f2b 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -208,6 +208,7 @@
     "//chrome/browser/tab:java_resources",
     "//chrome/browser/ui/android/appmenu:java_resources",
     "//chrome/browser/ui/android/favicon:java_resources",
+    "//chrome/browser/ui/android/omnibox:java_resources",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//chrome/browser/ui/android/theme:java_resources",
     "//chrome/browser/ui/android/toolbar:java_resources",
@@ -283,7 +284,6 @@
     ":chrome_app_java_resources",
     ":chrome_public_android_manifest",
     ":chrome_public_apk_template_resources",
-    ":partner_location_descriptor_proto_java",
     ":update_proto_java",
     ":usage_stats_proto_java",
     "$google_play_services_package:google_play_services_auth_base_java",
@@ -761,6 +761,7 @@
     "//chrome/browser/tab:jni_headers",
     "//chrome/browser/touch_to_fill/android:jni_headers",
     "//chrome/browser/ui/android/favicon:jni_headers",
+    "//chrome/browser/ui/android/omnibox:jni_headers",
     "//chrome/browser/ui/android/toolbar:jni_headers",
     "//chrome/browser/ui/android/webid:jni_headers",
     "//chrome/browser/ui/messages/android:jni_headers",
@@ -816,11 +817,6 @@
   sources = [ "//components/sync/driver/sync_user_settings.h" ]
 }
 
-proto_java_library("partner_location_descriptor_proto_java") {
-  proto_path = "java/src/org/chromium/chrome/browser/omnibox/geo"
-  sources = [ "$proto_path/partner_location_descriptor.proto" ]
-}
-
 proto_java_library("update_proto_java") {
   proto_path = "java/src/org/chromium/chrome/browser/omaha/metrics"
   sources = [ "$proto_path/update_success_tracking.proto" ]
@@ -865,7 +861,6 @@
     ":chrome_app_java_resources",
     ":chrome_java",
     ":chrome_public_android_manifest",
-    ":partner_location_descriptor_proto_java",
     "$google_play_services_package:google_play_services_base_java",
     "$google_play_services_package:google_play_services_basement_java",
     "$google_play_services_package:google_play_services_cast_framework_java",
@@ -967,6 +962,7 @@
     "//chrome/browser/ui/android/native_page:junit",
     "//chrome/browser/ui/android/night_mode:java",
     "//chrome/browser/ui/android/omnibox:java",
+    "//chrome/browser/ui/android/omnibox:junit",
     "//chrome/browser/ui/android/theme:java",
     "//chrome/browser/ui/android/toolbar:java",
     "//chrome/browser/ui/android/toolbar:junit",
@@ -1165,7 +1161,6 @@
     ":chrome_app_java_resources",
     ":chrome_test_util_java",
     ":chrome_test_util_jni",
-    ":partner_location_descriptor_proto_java",
     "$google_play_services_package:google_play_services_base_java",
     "$google_play_services_package:google_play_services_basement_java",
     "$google_play_services_package:google_play_services_cast_framework_java",
@@ -1460,7 +1455,6 @@
     "//ui/base/mojom:mojom_java",
     "//url:gurl_java",
     "//url:gurl_javatests",
-    "//url:gurl_junit_test_support",
     "//url:origin_java",
     "//url/mojom:url_mojom_gurl_java",
   ]
@@ -3602,12 +3596,6 @@
     "java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java",
     "java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskScheduler.java",
     "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java",
-    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java",
-    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java",
-    "java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java",
-    "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
-    "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
-    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
     "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java",
     "java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java",
     "java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index ca9581d..24a0cfc1 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -28,18 +28,14 @@
   "java/res/drawable-hdpi/bg_tabstrip_background_tab_outline.9.png",
   "java/res/drawable-hdpi/bg_tabstrip_tab.9.png",
   "java/res/drawable-hdpi/bookmark_check_gray.png",
-  "java/res/drawable-hdpi/bookmark_edit_active.png",
   "java/res/drawable-hdpi/bookmark_move_active.png",
   "java/res/drawable-hdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-hdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-hdpi/btn_bg_holo_pressed.png",
   "java/res/drawable-hdpi/btn_close_white.png",
   "java/res/drawable-hdpi/btn_left.png",
-  "java/res/drawable-hdpi/btn_mic.png",
   "java/res/drawable-hdpi/btn_normal_tabs.png",
   "java/res/drawable-hdpi/btn_right.png",
-  "java/res/drawable-hdpi/btn_star.png",
-  "java/res/drawable-hdpi/btn_suggestion_refine.png",
   "java/res/drawable-hdpi/btn_tab_close_normal.png",
   "java/res/drawable-hdpi/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-hdpi/btn_tabstrip_new_tab_normal.png",
@@ -70,14 +66,12 @@
   "java/res/drawable-hdpi/ic_event_googblue_36dp.png",
   "java/res/drawable-hdpi/ic_exit_to_app_white_24dp.png",
   "java/res/drawable-hdpi/ic_file_download_white_24dp.png",
-  "java/res/drawable-hdpi/ic_history_googblue_24dp.png",
   "java/res/drawable-hdpi/ic_link_grey600_36dp.png",
   "java/res/drawable-hdpi/ic_mobile_friendly_grey600_24dp.png",
   "java/res/drawable-hdpi/ic_most_visited_placeholder.png",
   "java/res/drawable-hdpi/ic_phone_googblue_36dp.png",
   "java/res/drawable-hdpi/ic_photo_camera.png",
   "java/res/drawable-hdpi/ic_place_googblue_36dp.png",
-  "java/res/drawable-hdpi/ic_suggestion_magnifier.png",
   "java/res/drawable-hdpi/ic_warning_white_24dp.png",
   "java/res/drawable-hdpi/ic_watch_later_24dp.png",
   "java/res/drawable-hdpi/incognito_small.png",
@@ -117,35 +111,25 @@
   "java/res/drawable-hdpi/troy_card.png",
   "java/res/drawable-hdpi/unionpay_card.png",
   "java/res/drawable-hdpi/verify_checkmark.png",
-  "java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png",
   "java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-ldrtl-hdpi-v17/btn_tabstrip_new_tab_pressed.png",
   "java/res/drawable-ldrtl-hdpi-v17/btn_toolbar_reload.png",
-  "java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png",
-  "java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png",
   "java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-ldrtl-mdpi-v17/btn_tabstrip_new_tab_pressed.png",
   "java/res/drawable-ldrtl-mdpi-v17/btn_toolbar_reload.png",
-  "java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png",
   "java/res/drawable-ldrtl-sw600dp-night-xhdpi/toolbar_background.9.png",
   "java/res/drawable-ldrtl-sw600dp-xhdpi-v17/toolbar_background.9.png",
   "java/res/drawable-ldrtl-v17/btn_back.xml",
   "java/res/drawable-ldrtl-v17/btn_forward.xml",
-  "java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png",
   "java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-ldrtl-xhdpi-v17/btn_tabstrip_new_tab_pressed.png",
   "java/res/drawable-ldrtl-xhdpi-v17/btn_toolbar_reload.png",
-  "java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png",
-  "java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png",
   "java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-ldrtl-xxhdpi-v17/btn_tabstrip_new_tab_pressed.png",
   "java/res/drawable-ldrtl-xxhdpi-v17/btn_toolbar_reload.png",
-  "java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png",
-  "java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png",
   "java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-ldrtl-xxxhdpi-v17/btn_tabstrip_new_tab_pressed.png",
   "java/res/drawable-ldrtl-xxxhdpi-v17/btn_toolbar_reload.png",
-  "java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png",
   "java/res/drawable-ldrtl/google_pay_with_divider.xml",
   "java/res/drawable-mdpi/amex_card.png",
   "java/res/drawable-mdpi/badge_update_dark.png",
@@ -153,18 +137,14 @@
   "java/res/drawable-mdpi/bg_tabstrip_background_tab_outline.9.png",
   "java/res/drawable-mdpi/bg_tabstrip_tab.9.png",
   "java/res/drawable-mdpi/bookmark_check_gray.png",
-  "java/res/drawable-mdpi/bookmark_edit_active.png",
   "java/res/drawable-mdpi/bookmark_move_active.png",
   "java/res/drawable-mdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-mdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-mdpi/btn_bg_holo_pressed.png",
   "java/res/drawable-mdpi/btn_close_white.png",
   "java/res/drawable-mdpi/btn_left.png",
-  "java/res/drawable-mdpi/btn_mic.png",
   "java/res/drawable-mdpi/btn_normal_tabs.png",
   "java/res/drawable-mdpi/btn_right.png",
-  "java/res/drawable-mdpi/btn_star.png",
-  "java/res/drawable-mdpi/btn_suggestion_refine.png",
   "java/res/drawable-mdpi/btn_tab_close_normal.png",
   "java/res/drawable-mdpi/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-mdpi/btn_tabstrip_new_tab_normal.png",
@@ -195,14 +175,12 @@
   "java/res/drawable-mdpi/ic_event_googblue_36dp.png",
   "java/res/drawable-mdpi/ic_exit_to_app_white_24dp.png",
   "java/res/drawable-mdpi/ic_file_download_white_24dp.png",
-  "java/res/drawable-mdpi/ic_history_googblue_24dp.png",
   "java/res/drawable-mdpi/ic_link_grey600_36dp.png",
   "java/res/drawable-mdpi/ic_mobile_friendly_grey600_24dp.png",
   "java/res/drawable-mdpi/ic_most_visited_placeholder.png",
   "java/res/drawable-mdpi/ic_phone_googblue_36dp.png",
   "java/res/drawable-mdpi/ic_photo_camera.png",
   "java/res/drawable-mdpi/ic_place_googblue_36dp.png",
-  "java/res/drawable-mdpi/ic_suggestion_magnifier.png",
   "java/res/drawable-mdpi/ic_warning_white_24dp.png",
   "java/res/drawable-mdpi/ic_watch_later_24dp.png",
   "java/res/drawable-mdpi/incognito_small.png",
@@ -266,18 +244,14 @@
   "java/res/drawable-xhdpi/bg_tabstrip_background_tab_outline.9.png",
   "java/res/drawable-xhdpi/bg_tabstrip_tab.9.png",
   "java/res/drawable-xhdpi/bookmark_check_gray.png",
-  "java/res/drawable-xhdpi/bookmark_edit_active.png",
   "java/res/drawable-xhdpi/bookmark_move_active.png",
   "java/res/drawable-xhdpi/btn_bg_holo_active_normal.png",
   "java/res/drawable-xhdpi/btn_bg_holo_active_pressed.png",
   "java/res/drawable-xhdpi/btn_bg_holo_pressed.png",
   "java/res/drawable-xhdpi/btn_close_white.png",
   "java/res/drawable-xhdpi/btn_left.png",
-  "java/res/drawable-xhdpi/btn_mic.png",
   "java/res/drawable-xhdpi/btn_normal_tabs.png",
   "java/res/drawable-xhdpi/btn_right.png",
-  "java/res/drawable-xhdpi/btn_star.png",
-  "java/res/drawable-xhdpi/btn_suggestion_refine.png",
   "java/res/drawable-xhdpi/btn_tab_close_normal.png",
   "java/res/drawable-xhdpi/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-xhdpi/btn_tabstrip_new_tab_normal.png",
@@ -308,14 +282,12 @@
   "java/res/drawable-xhdpi/ic_event_googblue_36dp.png",
   "java/res/drawable-xhdpi/ic_exit_to_app_white_24dp.png",
   "java/res/drawable-xhdpi/ic_file_download_white_24dp.png",
-  "java/res/drawable-xhdpi/ic_history_googblue_24dp.png",
   "java/res/drawable-xhdpi/ic_link_grey600_36dp.png",
   "java/res/drawable-xhdpi/ic_mobile_friendly_grey600_24dp.png",
   "java/res/drawable-xhdpi/ic_most_visited_placeholder.png",
   "java/res/drawable-xhdpi/ic_phone_googblue_36dp.png",
   "java/res/drawable-xhdpi/ic_photo_camera.png",
   "java/res/drawable-xhdpi/ic_place_googblue_36dp.png",
-  "java/res/drawable-xhdpi/ic_suggestion_magnifier.png",
   "java/res/drawable-xhdpi/ic_warning_white_24dp.png",
   "java/res/drawable-xhdpi/ic_watch_later_24dp.png",
   "java/res/drawable-xhdpi/incognito_small.png",
@@ -361,15 +333,11 @@
   "java/res/drawable-xxhdpi/bg_tabstrip_background_tab_outline.9.png",
   "java/res/drawable-xxhdpi/bg_tabstrip_tab.9.png",
   "java/res/drawable-xxhdpi/bookmark_check_gray.png",
-  "java/res/drawable-xxhdpi/bookmark_edit_active.png",
   "java/res/drawable-xxhdpi/bookmark_move_active.png",
   "java/res/drawable-xxhdpi/btn_close_white.png",
   "java/res/drawable-xxhdpi/btn_left.png",
-  "java/res/drawable-xxhdpi/btn_mic.png",
   "java/res/drawable-xxhdpi/btn_normal_tabs.png",
   "java/res/drawable-xxhdpi/btn_right.png",
-  "java/res/drawable-xxhdpi/btn_star.png",
-  "java/res/drawable-xxhdpi/btn_suggestion_refine.png",
   "java/res/drawable-xxhdpi/btn_tab_close_normal.png",
   "java/res/drawable-xxhdpi/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-xxhdpi/btn_tabstrip_new_tab_normal.png",
@@ -400,14 +368,12 @@
   "java/res/drawable-xxhdpi/ic_event_googblue_36dp.png",
   "java/res/drawable-xxhdpi/ic_exit_to_app_white_24dp.png",
   "java/res/drawable-xxhdpi/ic_file_download_white_24dp.png",
-  "java/res/drawable-xxhdpi/ic_history_googblue_24dp.png",
   "java/res/drawable-xxhdpi/ic_link_grey600_36dp.png",
   "java/res/drawable-xxhdpi/ic_mobile_friendly_grey600_24dp.png",
   "java/res/drawable-xxhdpi/ic_most_visited_placeholder.png",
   "java/res/drawable-xxhdpi/ic_phone_googblue_36dp.png",
   "java/res/drawable-xxhdpi/ic_photo_camera.png",
   "java/res/drawable-xxhdpi/ic_place_googblue_36dp.png",
-  "java/res/drawable-xxhdpi/ic_suggestion_magnifier.png",
   "java/res/drawable-xxhdpi/ic_warning_white_24dp.png",
   "java/res/drawable-xxhdpi/ic_watch_later_24dp.png",
   "java/res/drawable-xxhdpi/incognito_small.png",
@@ -452,15 +418,11 @@
   "java/res/drawable-xxxhdpi/bg_tabstrip_background_tab_outline.9.png",
   "java/res/drawable-xxxhdpi/bg_tabstrip_tab.9.png",
   "java/res/drawable-xxxhdpi/bookmark_check_gray.png",
-  "java/res/drawable-xxxhdpi/bookmark_edit_active.png",
   "java/res/drawable-xxxhdpi/bookmark_move_active.png",
   "java/res/drawable-xxxhdpi/btn_close_white.png",
   "java/res/drawable-xxxhdpi/btn_left.png",
-  "java/res/drawable-xxxhdpi/btn_mic.png",
   "java/res/drawable-xxxhdpi/btn_normal_tabs.png",
   "java/res/drawable-xxxhdpi/btn_right.png",
-  "java/res/drawable-xxxhdpi/btn_star.png",
-  "java/res/drawable-xxxhdpi/btn_suggestion_refine.png",
   "java/res/drawable-xxxhdpi/btn_tab_close_normal.png",
   "java/res/drawable-xxxhdpi/btn_tabstrip_new_incognito_tab_normal.png",
   "java/res/drawable-xxxhdpi/btn_tabstrip_new_tab_normal.png",
@@ -489,14 +451,12 @@
   "java/res/drawable-xxxhdpi/ic_event_googblue_36dp.png",
   "java/res/drawable-xxxhdpi/ic_exit_to_app_white_24dp.png",
   "java/res/drawable-xxxhdpi/ic_file_download_white_24dp.png",
-  "java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png",
   "java/res/drawable-xxxhdpi/ic_link_grey600_36dp.png",
   "java/res/drawable-xxxhdpi/ic_mobile_friendly_grey600_24dp.png",
   "java/res/drawable-xxxhdpi/ic_most_visited_placeholder.png",
   "java/res/drawable-xxxhdpi/ic_phone_googblue_36dp.png",
   "java/res/drawable-xxxhdpi/ic_photo_camera.png",
   "java/res/drawable-xxxhdpi/ic_place_googblue_36dp.png",
-  "java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png",
   "java/res/drawable-xxxhdpi/ic_warning_white_24dp.png",
   "java/res/drawable-xxxhdpi/ic_watch_later_24dp.png",
   "java/res/drawable-xxxhdpi/incognito_small.png",
@@ -570,30 +530,22 @@
   "java/res/drawable/ic_auto_awesome.xml",
   "java/res/drawable/ic_block_red.xml",
   "java/res/drawable/ic_bluetooth_connected.xml",
-  "java/res/drawable/ic_book_round.xml",
   "java/res/drawable/ic_cancel_circle.xml",
   "java/res/drawable/ic_checkmark_24dp.xml",
   "java/res/drawable/ic_cloud_offline_24dp.xml",
-  "java/res/drawable/ic_colorful_mic.xml",
-  "java/res/drawable/ic_content_copy_black.xml",
   "java/res/drawable/ic_credit_card_black.xml",
   "java/res/drawable/ic_desktop_windows.xml",
   "java/res/drawable/ic_done_googblue_36dp.xml",
-  "java/res/drawable/ic_equals_sign_round.xml",
   "java/res/drawable/ic_error.xml",
   "java/res/drawable/ic_error_googred_36dp.xml",
-  "java/res/drawable/ic_event_round.xml",
   "java/res/drawable/ic_file_download_scheduled_24dp.xml",
   "java/res/drawable/ic_find_in_page.xml",
   "java/res/drawable/ic_fingerprint_grey500_36dp.xml",
   "java/res/drawable/ic_forward_arrow_black_24dp.xml",
-  "java/res/drawable/ic_google_round.xml",
   "java/res/drawable/ic_google_services_48dp.xml",
   "java/res/drawable/ic_image_descriptions.xml",
   "java/res/drawable/ic_incognito_cct_24dp.xml",
   "java/res/drawable/ic_logo_assistant_24dp.xml",
-  "java/res/drawable/ic_logo_googleg_20dp.xml",
-  "java/res/drawable/ic_loop_round.xml",
   "java/res/drawable/ic_new_window.xml",
   "java/res/drawable/ic_offer_tag.xml",
   "java/res/drawable/ic_offline_pin_white.xml",
@@ -609,7 +561,6 @@
   "java/res/drawable/ic_signal_cellular_4_bar.xml",
   "java/res/drawable/ic_signout_40dp.xml",
   "java/res/drawable/ic_site_timer.xml",
-  "java/res/drawable/ic_swap_vert_round.xml",
   "java/res/drawable/ic_sync_badge_error_20dp.xml",
   "java/res/drawable/ic_sync_error_48dp.xml",
   "java/res/drawable/ic_sync_error_legacy_40dp.xml",
@@ -621,7 +572,6 @@
   "java/res/drawable/ic_trending_down_black.xml",
   "java/res/drawable/ic_tv_options_input_settings_rotated_grey.xml",
   "java/res/drawable/ic_vpn_key_blue.xml",
-  "java/res/drawable/ic_wb_sunny_round.xml",
   "java/res/drawable/ic_widgets.xml",
   "java/res/drawable/incognito_history_placeholder_image.xml",
   "java/res/drawable/incognito_switch_track.xml",
@@ -632,8 +582,6 @@
   "java/res/drawable/infobar_downloading_sweep_animation.xml",
   "java/res/drawable/item_chooser_row_background.xml",
   "java/res/drawable/lens_camera_icon.xml",
-  "java/res/drawable/logo_partly_cloudy.xml",
-  "java/res/drawable/logo_translate_round.xml",
   "java/res/drawable/long_screenshot.xml",
   "java/res/drawable/material_tooltip_background.xml",
   "java/res/drawable/mir_card.xml",
@@ -649,24 +597,20 @@
   "java/res/drawable/sharing_print.xml",
   "java/res/drawable/signin_header_animation.xml",
   "java/res/drawable/store_locally_tooltip_background.xml",
-  "java/res/drawable/switch_to_tab.xml",
   "java/res/drawable/tab_indicator.xml",
   "java/res/drawable/thumbnail_gradient_top_left.xml",
   "java/res/drawable/thumbnail_gradient_top_right.xml",
   "java/res/drawable/tile_view_hairline_border_background.xml",
   "java/res/drawable/toolbar_shadow.xml",
-  "java/res/drawable/trending_up_black_24dp.xml",
   "java/res/drawable/visa_card.xml",
   "java/res/layout-sw360dp/preference_spinner_single_line.xml",
   "java/res/layout-sw600dp/find_toolbar.xml",
-  "java/res/layout-sw600dp/location_bar.xml",
   "java/res/layout/accessibility_tab_switcher.xml",
   "java/res/layout/accessibility_tab_switcher_list_item.xml",
   "java/res/layout/account_chooser_dialog_item.xml",
   "java/res/layout/account_chooser_dialog_title.xml",
   "java/res/layout/account_divider_preference.xml",
   "java/res/layout/account_management_account_row.xml",
-  "java/res/layout/assistant_voice_search_consent_ui.xml",
   "java/res/layout/auto_sign_in_first_run_dialog.xml",
   "java/res/layout/autofill_billing_address_dropdown.xml",
   "java/res/layout/autofill_card_unmask_prompt.xml",
@@ -771,11 +715,6 @@
   "java/res/layout/item_chooser_dialog_row.xml",
   "java/res/layout/lightweight_fre_tos.xml",
   "java/res/layout/list_menu_button.xml",
-  "java/res/layout/location_bar.xml",
-  "java/res/layout/location_bar_base.xml",
-  "java/res/layout/location_status.xml",
-  "java/res/layout/location_status_icon.xml",
-  "java/res/layout/location_status_incognito_badge.xml",
   "java/res/layout/long_screenshots_area_selection_dialog.xml",
   "java/res/layout/manage_space_activity.xml",
   "java/res/layout/manage_sync_settings_bottom_bar.xml",
@@ -794,11 +733,6 @@
   "java/res/layout/new_tab_page_multi_feed_header.xml",
   "java/res/layout/new_tab_page_section_tab.xml",
   "java/res/layout/new_tab_page_tile_grid_placeholder.xml",
-  "java/res/layout/omnibox_answer_suggestion.xml",
-  "java/res/layout/omnibox_basic_suggestion.xml",
-  "java/res/layout/omnibox_entity_suggestion.xml",
-  "java/res/layout/omnibox_query_tiles_suggestion.xml",
-  "java/res/layout/omnibox_results_container.xml",
   "java/res/layout/optional_toolbar_button.xml",
   "java/res/layout/os_version_unsupported_text.xml",
   "java/res/layout/other_forms_of_history_dialog.xml",
@@ -835,7 +769,6 @@
   "java/res/layout/start_top_toolbar.xml",
   "java/res/layout/status_indicator_container.xml",
   "java/res/layout/suggestions_site_tile_grid_modern.xml",
-  "java/res/layout/suggestions_tile_view.xml",
   "java/res/layout/suggestions_tile_view_condensed.xml",
   "java/res/layout/suspended_tab.xml",
   "java/res/layout/sync_custom_passphrase.xml",
@@ -848,7 +781,6 @@
   "java/res/layout/top_sites_tile_view.xml",
   "java/res/layout/top_sites_tile_view_condensed.xml",
   "java/res/layout/update_menu_item.xml",
-  "java/res/layout/url_action_container.xml",
   "java/res/layout/url_bar.xml",
   "java/res/layout/webapk_icon_name_update_dialog.xml",
   "java/res/layout/webapk_update_report_abuse_custom_view.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index dd13a9b..1d8b49b 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -897,118 +897,6 @@
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationControllerImpl.java",
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateNotificationServiceBridge.java",
   "java/src/org/chromium/chrome/browser/omaha/notification/UpdateUtils.java",
-  "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java",
-  "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java",
-  "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java",
-  "java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java",
-  "java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java",
-  "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java",
-  "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java",
-  "java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBar.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java",
-  "java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java",
-  "java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java",
-  "java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java",
-  "java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java",
-  "java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java",
-  "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
-  "java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java",
-  "java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java",
-  "java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBar.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java",
-  "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
-  "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java",
-  "java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java",
-  "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java",
-  "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java",
-  "java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java",
-  "java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java",
-  "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java",
-  "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java",
-  "java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java",
   "java/src/org/chromium/chrome/browser/page_info/ChromePageInfo.java",
   "java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java",
   "java/src/org/chromium/chrome/browser/page_info/PageInfoHistoryController.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index f482479..c6443e9 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -164,30 +164,6 @@
   "junit/src/org/chromium/chrome/browser/omaha/VersionNumberTest.java",
   "junit/src/org/chromium/chrome/browser/omaha/metrics/HistogramUtilsTest.java",
   "junit/src/org/chromium/chrome/browser/omaha/metrics/UpdateSuccessMetricsTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java",
-  "junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java",
   "junit/src/org/chromium/chrome/browser/page_info/PageInfoPermissionsControllerUnitTest.java",
   "junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java",
   "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index de4a28b..ce84e9c1 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -45,6 +45,7 @@
     "//chrome/browser/signin/services/android:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/ui/android/favicon:java",
+    "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
     "//chrome/browser/version:java",
@@ -342,6 +343,7 @@
     "//chrome/browser/signin/services/android:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
+    "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/util:java",
     "//chrome/test/android:chrome_java_test_support",
     "//components/autofill_assistant/browser:proto_java",
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn
index 43aeb873..f2d918c2 100644
--- a/chrome/android/features/start_surface/internal/BUILD.gn
+++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -79,6 +79,7 @@
     "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/android/layouts:java",
     "//chrome/browser/ui/android/layouts/third_party/float_property:java",
+    "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
     "//chrome/browser/version:java",
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
index c60478e..1e4a48c 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -1092,8 +1092,7 @@
     }
 
     private void startAndWaitNativeInitialization() {
-        Assert.assertFalse(
-                NativeLibraryLoadedStatus.getProviderForTesting().areMainDexNativeMethodsReady());
+        Assert.assertFalse(LibraryLoader.getInstance().isInitialized());
 
         CommandLine.getInstance().removeSwitch(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION);
         TestThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
index b9e390c..afc8ee9 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
@@ -62,7 +62,6 @@
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.url.GURL;
-import org.chromium.url.JUnitTestGURLs;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -361,18 +360,14 @@
      */
     public static List<SiteSuggestion> createFakeSiteSuggestions() {
         List<SiteSuggestion> siteSuggestions = new ArrayList<>();
-        siteSuggestions.add(new SiteSuggestion("0 EXPLORE_SITES",
-                // Use pre-serialized GURL to avoid loading native.
-                JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL), "", TileTitleSource.UNKNOWN,
-                TileSource.EXPLORE, TileSectionType.PERSONALIZED, new Date()));
+        siteSuggestions.add(new SiteSuggestion("0 EXPLORE_SITES", new GURL("https://www.bar.com"),
+                "", TileTitleSource.UNKNOWN, TileSource.EXPLORE, TileSectionType.PERSONALIZED,
+                new Date()));
 
-        String urlTemplate = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1_NUMERAL).serialize();
         for (int i = 0; i < 7; i++) {
             siteSuggestions.add(new SiteSuggestion(String.valueOf(i),
-                    // Use pre-serialized GURL to avoid loading native.
-                    GURL.deserialize(urlTemplate.replace("www.1.com", "www." + i + ".com")), "",
-                    TileTitleSource.TITLE_TAG, TileSource.TOP_SITES, TileSectionType.PERSONALIZED,
-                    new Date()));
+                    new GURL("https://www." + i + ".com"), "", TileTitleSource.TITLE_TAG,
+                    TileSource.TOP_SITES, TileSectionType.PERSONALIZED, new Date()));
         }
 
         return siteSuggestions;
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 599ec864..01912c4 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -216,6 +216,7 @@
     "//chrome/browser/ui/android/favicon:java",
     "//chrome/browser/ui/android/native_page:java",
     "//chrome/browser/ui/android/night_mode:java",
+    "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//chrome/browser/ui/android/theme:java",
     "//chrome/browser/ui/android/toolbar:java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
index 48735d9..eb91cd6 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediator.java
@@ -133,7 +133,8 @@
 
     private void updateFavicon(Tab tab) {
         assert mTabListFaviconProvider.isInitialized();
-        mTabListFaviconProvider.getFaviconForUrlAsync(tab.getUrl(), false,
+        // TODO(crbug/783819): convert TabListFaviconProvider to GURL
+        mTabListFaviconProvider.getFaviconForUrlAsync(tab.getUrl().getSpec(), false,
                 (Drawable favicon) -> { mPropertyModel.set(FAVICON, favicon); });
     }
 
@@ -252,7 +253,7 @@
 
     private void updateSelectedTab(Tab tab) {
         mPropertyModel.set(TITLE, tab.getTitle());
-        mTabListFaviconProvider.getFaviconForUrlAsync(tab.getUrl(), false,
+        mTabListFaviconProvider.getFaviconForUrlAsync(tab.getUrl().getSpec(), false,
                 (Drawable favicon) -> { mPropertyModel.set(FAVICON, favicon); });
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
index a2551a0c..39c4dc8 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
@@ -26,7 +26,6 @@
 import org.chromium.chrome.browser.tabpersistence.TabStateDirectory;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.components.embedder_support.util.UrlUtilities;
-import org.chromium.url.GURL;
 
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
@@ -180,9 +179,10 @@
      * Get the URL of the {@link PseudoTab}.
      * @return The URL
      */
-    public GURL getUrl() {
+    public String getUrl() {
+        // TODO(crbug/783819): Return the GURL directly.
         if (mTab != null && mTab.get() != null && mTab.get().isInitialized()) {
-            return mTab.get().getUrl();
+            return mTab.get().getUrl() != null ? mTab.get().getUrl().getSpec() : null;
         }
         assert mTabId != null;
         return TabAttributeCache.getUrl(mTabId);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
index 2d44b0a..86b1932 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCache.java
@@ -65,7 +65,8 @@
             @Override
             public void onUrlUpdated(Tab tab) {
                 if (tab.isIncognito()) return;
-                cacheUrl(tab.getId(), tab.getUrl());
+                String url = tab.getUrl().getSpec();
+                cacheUrl(tab.getId(), url);
             }
 
             @Override
@@ -106,7 +107,6 @@
                 int id = tab.getId();
                 getSharedPreferences()
                         .edit()
-                        .remove(getDeprecatedUrlKey(id))
                         .remove(getUrlKey(id))
                         .remove(getTitleKey(id))
                         .remove(getRootIdKey(id))
@@ -126,7 +126,7 @@
                         mTabModelSelector.getTabModelFilterProvider().getTabModelFilter(false);
                 for (int i = 0; i < filter.getCount(); i++) {
                     Tab tab = filter.getTabAt(i);
-                    cacheUrl(tab.getId(), tab.getUrl());
+                    cacheUrl(tab.getId(), tab.getUrl().getSpec());
                     cacheTitle(tab.getId(), tab.getTitle());
                     cacheRootId(tab.getId(), CriticalPersistedTabData.from(tab).getRootId());
                     cacheTimestampMillis(
@@ -168,11 +168,6 @@
     }
 
     private static String getUrlKey(int id) {
-        return id + "_gurl";
-    }
-
-    // Legacy from when URL was serialized as raw string.
-    private static String getDeprecatedUrlKey(int id) {
         return id + "_url";
     }
 
@@ -181,16 +176,13 @@
      * @param id The ID of the {@link PseudoTab}.
      * @return The URL
      */
-    public static GURL getUrl(int id) {
-        String url = getSharedPreferences().getString(getUrlKey(id), "");
-        if (!url.isEmpty()) {
-            return GURL.deserialize(url);
-        }
-        return new GURL(getSharedPreferences().getString(getDeprecatedUrlKey(id), ""));
+    public static String getUrl(int id) {
+        return getSharedPreferences().getString(getUrlKey(id), "");
     }
 
-    private static void cacheUrl(int id, GURL url) {
-        getSharedPreferences().edit().putString(getUrlKey(id), url.serialize()).apply();
+    private static void cacheUrl(int id, String url) {
+        // TODO(crbug/783819): Use GURL directly.
+        getSharedPreferences().edit().putString(getUrlKey(id), url).apply();
     }
 
     /**
@@ -198,7 +190,7 @@
      * @param id The ID of the {@link PseudoTab}.
      * @param url The URL
      */
-    static void setUrlForTesting(int id, GURL url) {
+    static void setUrlForTesting(int id, String url) {
         cacheUrl(id, url);
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
index 58abf0d8..cbf2cde1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.url.GURL;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -116,7 +115,7 @@
             for (int i = 0; i < 4; i++) {
                 if (mTabs.get(i) != null) {
                     final int index = i;
-                    final GURL url = mTabs.get(i).getUrl();
+                    final String url = mTabs.get(i).getUrl();
                     final boolean isIncognito = mTabs.get(i).isIncognito();
                     // getTabThumbnailWithCallback() might call the callback up to twice,
                     // so use |lastFavicon| to avoid fetching the favicon the second time.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
index 21d9c76..b872456 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java
@@ -13,17 +13,16 @@
 import android.graphics.drawable.LayerDrawable;
 
 import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
 import androidx.appcompat.content.res.AppCompatResources;
 
 import org.chromium.base.Callback;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.ui.favicon.FaviconHelper;
 import org.chromium.chrome.browser.ui.favicon.FaviconUtils;
-import org.chromium.chrome.browser.ui.native_page.NativePage;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 import org.chromium.ui.base.ViewUtils;
-import org.chromium.url.GURL;
 
 import java.util.List;
 
@@ -154,7 +153,7 @@
      * @param faviconCallback The callback that requests for favicon.
      */
     public void getFaviconForUrlAsync(
-            GURL url, boolean isIncognito, Callback<Drawable> faviconCallback) {
+            String url, boolean isIncognito, Callback<Drawable> faviconCallback) {
         if (mFaviconHelper == null || UrlUtilities.isNTPUrl(url)) {
             faviconCallback.onResult(getRoundedChromeDrawable(isIncognito));
         } else {
@@ -171,19 +170,11 @@
 
     /**
      * Synchronously get the processed favicon Drawable.
-     * @param url The URL whose favicon is requested.
-     * @param isIncognito Whether the tab is incognito or not.
      * @param icon The favicon that was received.
      * @return The processed favicon.
      */
-    public Drawable getFaviconForUrlSync(GURL url, boolean isIncognito, Bitmap icon) {
-        if (icon == null) {
-            boolean isNativeUrl = NativePage.isNativePageUrl(url, isIncognito);
-            return isNativeUrl ? getRoundedChromeDrawable(isIncognito)
-                               : getRoundedGlobeDrawable(isIncognito);
-        } else {
-            return processBitmap(icon, mIsTabStrip);
-        }
+    public Drawable getFaviconForUrlSync(@NonNull Bitmap icon) {
+        return processBitmap(icon, mIsTabStrip);
     }
 
     /**
@@ -193,7 +184,7 @@
      * @param faviconCallback The callback that requests for the composed favicon.
      */
     public void getComposedFaviconImageAsync(
-            List<GURL> urls, boolean isIncognito, Callback<Drawable> faviconCallback) {
+            List<String> urls, boolean isIncognito, Callback<Drawable> faviconCallback) {
         assert urls != null && urls.size() > 1 && urls.size() <= 4;
 
         mFaviconHelper.getComposedFaviconImage(mProfile, urls, mFaviconSize, (image, iconUrl) -> {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 828d1bef..31f2c61 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -1614,11 +1614,11 @@
             }
 
             // The order of the url list matches the multi-thumbnail.
-            List<GURL> urls = new ArrayList<>();
+            List<String> urls = new ArrayList<>();
             urls.add(pseudoTab.getUrl());
             for (int i = 0; urls.size() < 4 && i < relatedTabList.size(); i++) {
                 if (pseudoTab.getId() == relatedTabList.get(i).getId()) continue;
-                urls.add(relatedTabList.get(i).getUrl());
+                urls.add(relatedTabList.get(i).getUrl().getSpec());
             }
 
             // For tab group card in grid tab switcher, the favicon is the composed favicon.
@@ -1633,8 +1633,7 @@
 
         // If there is an available icon, we fetch favicon synchronously; otherwise asynchronously.
         if (icon != null) {
-            Drawable drawable = mTabListFaviconProvider.getFaviconForUrlSync(
-                    pseudoTab.getUrl(), pseudoTab.isIncognito(), icon);
+            Drawable drawable = mTabListFaviconProvider.getFaviconForUrlSync(icon);
             mModel.get(modelIndex).model.set(TabProperties.FAVICON, drawable);
             return;
         }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
index f14b85f5..3c1b611 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherMediatorUnitTest.java
@@ -44,7 +44,6 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabListFaviconProvider;
 import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.url.GURL;
 import org.chromium.url.JUnitTestGURLs;
 
 /** Tests for {@link SingleTabSwitcherMediator}. */
@@ -53,10 +52,10 @@
 public class SingleTabSwitcherMediatorUnitTest {
     private final int mTabId = 1;
     private final String mTitle = "test";
-    private final GURL mUrl = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1);
+    private final String mUrlString = JUnitTestGURLs.URL_1;
     private final int mTabId2 = 2;
     private final String mTitle2 = "test2";
-    private final GURL mUrl2 = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2);
+    private final String mUrlString2 = JUnitTestGURLs.URL_2;
     private SingleTabSwitcherMediator mMediator;
     private PropertyModel mPropertyModel;
 
@@ -100,10 +99,10 @@
         doReturn(0).when(mNormalTabModel).index();
         doReturn(1).when(mNormalTabModel).getCount();
         doReturn(false).when(mNormalTabModel).isIncognito();
-        doReturn(mUrl).when(mTab).getUrl();
+        doReturn(JUnitTestGURLs.getGURL(mUrlString)).when(mTab).getUrl();
         doReturn(mTabId).when(mTab).getId();
         doReturn(mTitle).when(mTab).getTitle();
-        doReturn(mUrl2).when(mTab2).getUrl();
+        doReturn(JUnitTestGURLs.getGURL(mUrlString2)).when(mTab2).getUrl();
         doReturn(mTabId2).when(mTab2).getId();
         doReturn(mTitle2).when(mTab2).getTitle();
         doReturn(true).when(mIncognitoTabModel).isIncognito();
@@ -131,7 +130,7 @@
                 .addTabModelFilterObserver(mTabModelObserverCaptor.capture());
         verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
         verify(mTabListFaviconProvider)
-                .getFaviconForUrlAsync(eq(mUrl), eq(false), mFaviconCallbackCaptor.capture());
+                .getFaviconForUrlAsync(eq(mUrlString), eq(false), mFaviconCallbackCaptor.capture());
         assertTrue(mMediator.overviewVisible());
         verify(mOverviewModeObserver).startedShowing();
         verify(mOverviewModeObserver).finishedShowing();
@@ -161,7 +160,7 @@
                 .addTabModelFilterObserver(mTabModelObserverCaptor.capture());
         verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
         verify(mTabListFaviconProvider)
-                .getFaviconForUrlAsync(eq(mUrl), eq(false), mFaviconCallbackCaptor.capture());
+                .getFaviconForUrlAsync(eq(mUrlString), eq(false), mFaviconCallbackCaptor.capture());
         assertTrue(mMediator.overviewVisible());
         verify(mOverviewModeObserver).startedShowing();
         verify(mOverviewModeObserver).finishedShowing();
@@ -200,7 +199,7 @@
                 .addTabModelFilterObserver(mTabModelObserverCaptor.capture());
         verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
         verify(mTabListFaviconProvider)
-                .getFaviconForUrlAsync(eq(mUrl), eq(false), mFaviconCallbackCaptor.capture());
+                .getFaviconForUrlAsync(eq(mUrlString), eq(false), mFaviconCallbackCaptor.capture());
         assertTrue(mMediator.overviewVisible());
         verify(mOverviewModeObserver).startedShowing();
         verify(mOverviewModeObserver).finishedShowing();
@@ -229,7 +228,7 @@
                 .addTabModelFilterObserver(mTabModelObserverCaptor.capture());
         verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture());
         verify(mTabListFaviconProvider)
-                .getFaviconForUrlAsync(eq(mUrl), eq(false), mFaviconCallbackCaptor.capture());
+                .getFaviconForUrlAsync(eq(mUrlString), eq(false), mFaviconCallbackCaptor.capture());
         assertEquals(mPropertyModel.get(TITLE), mTitle);
 
         mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
index 4c22b02..5c3a890 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTabUnitTest.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
-import org.chromium.url.GURL;
 import org.chromium.url.JUnitTestGURLs;
 
 import java.util.ArrayList;
@@ -251,11 +250,11 @@
 
     @Test
     public void getUrl_real() {
-        GURL url = JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL);
-        doReturn(url).when(mTab1).getUrl();
+        String url = JUnitTestGURLs.EXAMPLE_URL;
+        doReturn(JUnitTestGURLs.getGURL(url)).when(mTab1).getUrl();
 
         PseudoTab tab = PseudoTab.fromTabId(TAB1_ID);
-        Assert.assertEquals(GURL.emptyGURL(), tab.getUrl());
+        Assert.assertEquals("", tab.getUrl());
 
         PseudoTab realTab = PseudoTab.fromTab(mTab1);
         Assert.assertNotEquals(tab, realTab);
@@ -264,11 +263,11 @@
 
     @Test
     public void getUrl_cache() {
-        String url = JUnitTestGURLs.URL_1;
-        TabAttributeCache.setUrlForTesting(TAB1_ID, JUnitTestGURLs.getGURL(url));
+        String url = "url 1";
+        TabAttributeCache.setUrlForTesting(TAB1_ID, url);
 
         PseudoTab tab = PseudoTab.fromTabId(TAB1_ID);
-        Assert.assertEquals(url, tab.getUrl().getSpec());
+        Assert.assertEquals(url, tab.getUrl());
 
         PseudoTab realTab = PseudoTab.fromTab(mTab1);
         Assert.assertNotEquals(tab, realTab);
@@ -467,7 +466,7 @@
         // Url was not set. Without the isInitialized() check,
         // pseudoTab.getUrl() would crash here with
         // UnsupportedOperationException
-        Assert.assertEquals("", pseudoTab.getUrl().getSpec());
+        Assert.assertEquals("", pseudoTab.getUrl());
     }
 
     @Test
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java
index 7f43c4e..600a0e9f 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/pseudotab/TabAttributeCacheUnitTest.java
@@ -130,8 +130,8 @@
 
     @Test
     public void updateUrl() {
-        GURL url = JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL);
-        doReturn(url).when(mTab1).getUrl();
+        String url = JUnitTestGURLs.EXAMPLE_URL;
+        doReturn(JUnitTestGURLs.getGURL(url)).when(mTab1).getUrl();
 
         Assert.assertNotEquals(url, TabAttributeCache.getUrl(TAB1_ID));
 
@@ -359,8 +359,8 @@
 
     @Test
     public void onTabStateInitialized() {
-        GURL url1 = JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL);
-        doReturn(url1).when(mTab1).getUrl();
+        String url1 = JUnitTestGURLs.EXAMPLE_URL;
+        doReturn(JUnitTestGURLs.getGURL(url1)).when(mTab1).getUrl();
         String title1 = "title 1";
         doReturn(title1).when(mTab1).getTitle();
         int rootId1 = 1337;
@@ -368,8 +368,8 @@
         long timestamp1 = 123456;
         doReturn(timestamp1).when(mCriticalPersistedTabData1).getTimestampMillis();
 
-        GURL url2 = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2);
-        doReturn(url2).when(mTab2).getUrl();
+        String url2 = JUnitTestGURLs.URL_2;
+        doReturn(JUnitTestGURLs.getGURL(url2)).when(mTab2).getUrl();
         String title2 = "title 2";
         doReturn(title2).when(mTab2).getTitle();
         int rootId2 = 42;
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java
index 65bf7949..1d05f8b 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtilsUnitTest.java
@@ -36,7 +36,6 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabUiUnitTestUtils;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
-import org.chromium.url.GURL;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -91,9 +90,9 @@
 
         MockitoAnnotations.initMocks(this);
 
-        mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE, GURL.emptyGURL());
-        mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, TAB2_TITLE, GURL.emptyGURL());
-        mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE, GURL.emptyGURL());
+        mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE, "");
+        mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, TAB2_TITLE, "");
+        mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE, "");
 
         doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider();
         doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getCurrentTabModelFilter();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index a8f8bd5..27383be 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -64,7 +64,6 @@
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.KeyboardVisibilityDelegate;
 import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.url.GURL;
 import org.chromium.url.JUnitTestGURLs;
 
 import java.util.ArrayList;
@@ -1073,7 +1072,7 @@
     }
 
     private TabImpl prepareTab(int id, String title) {
-        TabImpl tab = TabUiUnitTestUtils.prepareTab(id, title, GURL.emptyGURL());
+        TabImpl tab = TabUiUnitTestUtils.prepareTab(id, title, "");
         doReturn(true).when(tab).isIncognito();
         return tab;
     }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 5c9116b..d545507 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -19,7 +19,6 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.contains;
 import static org.mockito.ArgumentMatchers.eq;
@@ -178,9 +177,9 @@
     private static final String NEW_TITLE = "New title";
     private static final String CUSTOMIZED_DIALOG_TITLE1 = "Cool Tabs";
     private static final String TAB_GROUP_TITLES_FILE_NAME = "tab_group_titles";
-    private static final GURL TAB1_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1);
-    private static final GURL TAB2_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2);
-    private static final GURL TAB3_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_3);
+    private static final String TAB1_URL = JUnitTestGURLs.URL_1;
+    private static final String TAB2_URL = JUnitTestGURLs.URL_2;
+    private static final String TAB3_URL = JUnitTestGURLs.URL_3;
     private static final String NEW_URL = JUnitTestGURLs.EXAMPLE_URL;
     private static final int TAB1_ID = 456;
     private static final int TAB2_ID = 789;
@@ -316,9 +315,9 @@
         // Ensure native pointer is initialized
         doReturn(1L).when(mOptimizationGuideBridgeJniMock).init();
 
-        mTab1Domain = TAB1_URL.getHost().replace("www.", "");
-        mTab2Domain = TAB2_URL.getHost().replace("www.", "");
-        mTab3Domain = TAB3_URL.getHost().replace("www.", "");
+        mTab1Domain = JUnitTestGURLs.getGURL(TAB1_URL).getHost().replace("www.", "");
+        mTab2Domain = JUnitTestGURLs.getGURL(TAB2_URL).getHost().replace("www.", "");
+        mTab3Domain = JUnitTestGURLs.getGURL(TAB3_URL).getHost().replace("www.", "");
         mNewDomain = JUnitTestGURLs.getGURL(NEW_URL).getHost().replace("www.", "");
 
         CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, false);
@@ -357,10 +356,10 @@
         doReturn(2).when(mTabModel).getCount();
         doNothing()
                 .when(mTabListFaviconProvider)
-                .getFaviconForUrlAsync(anyObject(), anyBoolean(), mCallbackCaptor.capture());
+                .getFaviconForUrlAsync(anyString(), anyBoolean(), mCallbackCaptor.capture());
         doReturn(mFaviconDrawable)
                 .when(mTabListFaviconProvider)
-                .getFaviconForUrlSync(anyObject(), anyBoolean(), any(Bitmap.class));
+                .getFaviconForUrlSync(any(Bitmap.class));
         doReturn(mTab1).when(mTabModelSelector).getTabById(TAB1_ID);
         doReturn(mTab2).when(mTabModelSelector).getTabById(TAB2_ID);
         doReturn(tabs1).when(mTabGroupModelFilter).getRelatedTabList(TAB1_ID);
@@ -380,13 +379,13 @@
         doReturn(mSpanSizeLookup).when(mGridLayoutManager).getSpanSizeLookup();
         doReturn(mTab1Domain)
                 .when(mUrlUtilitiesJniMock)
-                .getDomainAndRegistry(eq(TAB1_URL.getSpec()), anyBoolean());
+                .getDomainAndRegistry(eq(TAB1_URL), anyBoolean());
         doReturn(mTab2Domain)
                 .when(mUrlUtilitiesJniMock)
-                .getDomainAndRegistry(eq(TAB2_URL.getSpec()), anyBoolean());
+                .getDomainAndRegistry(eq(TAB2_URL), anyBoolean());
         doReturn(mTab3Domain)
                 .when(mUrlUtilitiesJniMock)
-                .getDomainAndRegistry(eq(TAB3_URL.getSpec()), anyBoolean());
+                .getDomainAndRegistry(eq(TAB3_URL), anyBoolean());
         doNothing().when(mTemplateUrlService).addObserver(mTemplateUrlServiceObserver.capture());
         doReturn(true).when(mTabListFaviconProvider).isInitialized();
 
@@ -1920,8 +1919,10 @@
                             PriceTrackingUtilities.TRACK_PRICES_ON_TABS, priceTrackingEnabled);
                     Profile.setLastUsedProfileForTesting(mProfile);
                     Map<GURL, Any> responses = new HashMap<>();
-                    responses.put(TAB1_URL, ANY_BUYABLE_PRODUCT_INITIAL);
-                    responses.put(TAB2_URL, ANY_EMPTY);
+                    GURL gurl1 = JUnitTestGURLs.getGURL(TAB1_URL);
+                    GURL gurl2 = JUnitTestGURLs.getGURL(TAB2_URL);
+                    responses.put(gurl1, ANY_BUYABLE_PRODUCT_INITIAL);
+                    responses.put(gurl2, ANY_EMPTY);
                     mockOptimizationGuideResponse(OptimizationGuideDecision.TRUE, responses);
                     PersistedTabDataConfiguration.setUseTestConfig(true);
                     initAndAssertAllProperties(mMediatorSpy);
@@ -2435,7 +2436,7 @@
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, tab3));
         createTabGroup(tabs, TAB1_ID);
         mTabObserverCaptor.getValue().onFaviconUpdated(mTab1, mFaviconBitmap);
-        List<GURL> urls = new ArrayList<>(Arrays.asList(TAB1_URL, TAB2_URL, TAB3_URL));
+        List<String> urls = new ArrayList<>(Arrays.asList(TAB1_URL, TAB2_URL, TAB3_URL));
         verify(mTabListFaviconProvider).getComposedFaviconImageAsync(eq(urls), anyBoolean(), any());
         mCallbackCaptor.getValue().onResult(mFaviconDrawable);
         assertThat(mModel.get(0).model.get(TabProperties.FAVICON), equalTo(mFaviconDrawable));
@@ -2443,12 +2444,11 @@
         // Test a group of five.
         mModel.get(1).model.set(TabProperties.FAVICON, null);
         TabImpl tab4 = prepareTab(0, "tab 4", TAB2_URL);
-        TabImpl tab5 = prepareTab(1, "tab 5", JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+        TabImpl tab5 = prepareTab(1, "tab 5", "www.tab5.com");
         tabs.addAll(Arrays.asList(tab4, tab5));
         createTabGroup(tabs, TAB2_ID);
         mTabObserverCaptor.getValue().onFaviconUpdated(mTab2, mFaviconBitmap);
         urls = new ArrayList<>(Arrays.asList(TAB2_URL, TAB1_URL, TAB3_URL, TAB2_URL));
-
         verify(mTabListFaviconProvider).getComposedFaviconImageAsync(eq(urls), anyBoolean(), any());
         mCallbackCaptor.getValue().onResult(mFaviconDrawable);
         assertThat(mModel.get(1).model.get(TabProperties.FAVICON), equalTo(mFaviconDrawable));
@@ -2704,7 +2704,7 @@
                 instanceOf(TabListMediator.TabActionListener.class));
     }
 
-    private TabImpl prepareTab(int id, String title, GURL url) {
+    private TabImpl prepareTab(int id, String title, String url) {
         TabImpl tab = TabUiUnitTestUtils.prepareTab(id, title, url);
         when(tab.getView()).thenReturn(mock(View.class));
         doReturn(true).when(tab).isIncognito();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
index 2974cb4..30844ef 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiUnitTestUtils.java
@@ -53,13 +53,17 @@
         doReturn(userDataHost).when(tab).getUserDataHost();
     }
 
-    public static TabImpl prepareTab(int id, String title, GURL url) {
+    public static TabImpl prepareTab(int id, String title, String urlString) {
         CriticalPersistedTabData criticalPersistedTabData = mock(CriticalPersistedTabData.class);
         TabImpl tab = prepareTab(id, criticalPersistedTabData);
         doReturn(id).when(criticalPersistedTabData).getRootId();
         doReturn(title).when(tab).getTitle();
-        doReturn(url).when(tab).getOriginalUrl();
-        doReturn(url).when(tab).getUrl();
+
+        // TODO(crbug/783819): don't mock GURL here.
+        GURL gurl = mock(GURL.class);
+        doReturn(urlString).when(gurl).getSpec();
+        doReturn(gurl).when(tab).getOriginalUrl();
+        doReturn(gurl).when(tab).getUrl();
         return tab;
     }
 
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index 226b4ef..aae62c1 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -20,12 +20,6 @@
     <!-- App menu colors -->
     <color name="update_menu_item_text_color">@color/default_red</color>
 
-    <!-- Omnibox Suggestion colors -->
-    <color name="suggestion_url_dark_modern">@color/default_text_color_link</color>
-    <color name="suggestion_url_light_modern">@color/modern_blue_300</color>
-    <color name="answers_description_text_negative">@color/default_red</color>
-    <color name="answers_description_text_positive">@color/default_green</color>
-
     <!--  Distilled Page Prefs colors -->
     <color name="distilled_page_prefs_selected">#999999</color>
     <color name="distilled_page_prefs_unselected">@color/popup_bg_color</color>
@@ -70,16 +64,6 @@
     <color name="contextual_search_promo_background_color">@color/default_bg_color_elev_0</color>
     <color name="contextual_search_promo_border_color">#C2C2C2</color>
 
-    <!-- LocationBar colors -->
-    <color name="locationbar_dark_hint_text">@color/search_box_hint</color>
-    <color name="locationbar_light_hint_text">@color/white_alpha_70</color>
-    <color name="locationbar_status_offline_color">@color/modern_grey_900</color>
-    <color name="locationbar_status_offline_color_light">@android:color/white</color>
-    <color name="locationbar_status_preview_color">@color/modern_blue_600</color>
-    <color name="locationbar_status_preview_color_light">@color/modern_blue_300</color>
-    <color name="omnibox_focused_fading_background_color">@color/black_alpha_65</color>
-    <color name="omnibox_focused_fading_background_color_light">@color/white_alpha_65</color>
-
     <!-- Find in Page colors -->
     <color name="find_in_page_query_white_color">@android:color/white</color>
     <color name="find_in_page_query_incognito_hint_color">@color/white_alpha_70</color>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 5169d2c..3ac54d5 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -163,80 +163,10 @@
     <dimen name="find_in_page_popup_height">60dp</dimen>
     <dimen name="find_in_page_popup_margin_end">62dp</dimen>
 
-    <!-- Toolbar dimensions -->
-    <dimen name="toolbar_height_no_shadow">56dp</dimen>
-    <dimen name="toolbar_progress_bar_height">2dp</dimen>
-    <dimen name="toolbar_button_width">48dp</dimen>
-    <dimen name="toolbar_identity_disc_size">24dp</dimen>
-    <dimen name="toolbar_identity_disc_size_duet">32dp</dimen>
-    <dimen name="toolbar_url_focus_translation_x">10dp</dimen>
-
-    <!-- Bottom Toolbar -->
-    <dimen name="split_toolbar_button_height">56dp</dimen>
-    <dimen name="split_toolbar_button_width">@dimen/split_toolbar_button_height</dimen>
-    <dimen name="bottom_toolbar_button_wrapper_width">56dp</dimen>
-
-    <dimen name="toolbar_edge_padding">8dp</dimen>
-    <dimen name="location_bar_vertical_margin">8dp</dimen>
-    <dimen name="location_bar_url_text_size">16sp</dimen>
-    <dimen name="location_bar_icon_width">28dp</dimen>
-    <dimen name="location_bar_action_icon_width">48dp</dimen>
-    <dimen name="location_bar_icon_margin_end">4dp</dimen>
-    <dimen name="location_bar_status_separator_width">1dp</dimen>
-    <dimen name="location_bar_status_separator_spacer">8dp</dimen>
-    <dimen name="location_bar_min_url_width">68dp</dimen>
-    <dimen name="location_bar_min_verbose_status_text_width">48dp</dimen>
-
-    <dimen name="location_bar_lateral_padding">8dp</dimen>
-    <dimen name="fake_search_box_lateral_padding">10dp</dimen>
-    <dimen name="location_bar_status_icon_width">24dp</dimen>
-    <dimen name="location_bar_icon_end_padding">4dp</dimen>
-    <dimen name="location_bar_icon_end_padding_focused">16dp</dimen>
-    <dimen name="location_bar_verbose_start_padding_verbose_text">4dp</dimen>
-    <dimen name="location_bar_status_extra_padding">4dp</dimen>
-    <dimen name="location_bar_url_action_offset">-8dp</dimen>
-
-    <dimen name="tablet_toolbar_start_padding">4dp</dimen>
-    <dimen name="toolbar_optional_button_animation_translation">10dp</dimen>
-
     <!-- Start surface toolbar dimensions -->
     <dimen name="start_surface_toolbar_button_padding_to_button">8dp</dimen>
     <dimen name="start_surface_toolbar_button_padding_to_edge">16dp</dimen>
 
-    <!-- Omnibox suggestions -->
-    <dimen name="omnibox_suggestion_header_margin_start">
-        @dimen/omnibox_suggestion_24dp_icon_margin_start
-    </dimen>
-    <dimen name="omnibox_suggestion_header_height">48dp</dimen>
-    <dimen name="omnibox_suggestion_comfortable_height">60dp</dimen>
-    <dimen name="omnibox_suggestion_semicompact_height">56dp</dimen>
-    <dimen name="omnibox_suggestion_compact_height">52dp</dimen>
-    <dimen name="omnibox_suggestion_comfortable_padding">10dp</dimen>
-    <dimen name="omnibox_suggestion_semicompact_padding">8dp</dimen>
-    <dimen name="omnibox_suggestion_compact_padding">6dp</dimen>
-    <dimen name="omnibox_suggestion_list_padding_bottom">8dp</dimen>
-    <dimen name="omnibox_suggestion_start_offset_without_icon">18dp</dimen>
-    <dimen name="omnibox_carousel_suggestion_padding">12dp</dimen>
-
-    <dimen name="omnibox_suggestion_36dp_icon_size">36dp</dimen>
-    <dimen name="omnibox_suggestion_24dp_icon_size">24dp</dimen>
-    <dimen name="omnibox_suggestion_36dp_icon_margin_start">10dp</dimen>
-    <dimen name="omnibox_suggestion_36dp_icon_margin_end">10dp</dimen>
-    <dimen name="omnibox_suggestion_24dp_icon_margin_start">16dp</dimen>
-    <dimen name="omnibox_suggestion_24dp_icon_margin_end">16dp</dimen>
-    <dimen name="omnibox_suggestion_favicon_size">24dp</dimen>
-    <dimen name="omnibox_suggestion_decoration_image_size">36dp</dimen>
-    <dimen name="omnibox_suggestion_icon_area_size">56dp</dimen>
-
-    <dimen name="omnibox_suggestion_action_icon_width">48dp</dimen>
-    <dimen name="omnibox_suggestion_refine_view_modern_end_padding">4dp</dimen>
-    <dimen name="omnibox_suggestion_carousel_horizontal_spacing">8dp</dimen>
-
-    <!-- Adding search engine logo to the omnibox. -->
-    <!-- Max size which will fit completely in the composed/rounded bg. -->
-    <dimen name="omnibox_search_engine_logo_favicon_size">17dp</dimen>
-    <dimen name="omnibox_search_engine_logo_composed_size">24dp</dimen>
-
     <!-- NTP dimensions -->
     <dimen name="tile_grid_layout_max_width">504dp</dimen>
     <dimen name="tile_grid_layout_padding_top">24dp</dimen>
diff --git a/chrome/android/java/res/values/styles.xml b/chrome/android/java/res/values/styles.xml
index 1ef1b97..457a1f0 100644
--- a/chrome/android/java/res/values/styles.xml
+++ b/chrome/android/java/res/values/styles.xml
@@ -74,12 +74,6 @@
          navigation bar colors from being applied -->
     <style name="Theme.Chromium.SearchActivity" parent="Base.Theme.Chromium.WithWindowAnimation" />
 
-    <style name="Base.Theme.Chromium.TabbedMode" parent="Theme.Chromium.WithWindowAnimation">
-        <!-- Attributes for material design component. See https://crbug.com/1186712 -->
-        <item name="colorSurface">@color/material_color_surface</item>
-    </style>
-    <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode" />
-
     <!-- Web app themes -->
     <!-- Extend base theme rather than Theme.Chromium.WithWindowAnimation to avoid values-v27
         navigation bar colors from being applied -->
@@ -519,27 +513,6 @@
         <item name="android:textAllCaps">false</item>
     </style>
 
-    <!-- Omnibox -->
-    <style name="TextAppearance.OmniboxVerboseStatus" parent="@android:style/TextAppearance.Medium">
-        <item name="android:textSize">@dimen/location_bar_url_text_size</item>
-    </style>
-
-    <!-- Omnibox suggestions -->
-    <style name="TextAppearance.OmniboxAnswerDescriptionNegativeSmall">
-        <item name="android:textSize">@dimen/text_size_small</item>
-        <item name="android:textColor">@color/answers_description_text_negative</item>
-    </style>
-
-    <style name="TextAppearance.OmniboxAnswerDescriptionPositiveSmall">
-        <item name="android:textSize">@dimen/text_size_small</item>
-        <item name="android:textColor">@color/answers_description_text_positive</item>
-    </style>
-
-    <style name="OmniboxIcon" parent="LocationBarButton">
-        <item name="android:layout_width">@dimen/location_bar_status_icon_width</item>
-        <item name="android:layout_height">match_parent</item>
-    </style>
-
     <!-- Context menu -->
     <style name="ContextMenuItemText">
         <item name="android:background">?attr/selectableItemBackground</item>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
index 5122ac3..45f03028 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchBarControl.java
@@ -113,6 +113,12 @@
     /** The animator that controls touch highlighting. */
     private CompositorAnimator mTouchHighlightAnimation;
 
+    /** The animator that gradually exposes the Related Searches in the Bar. */
+    private CompositorAnimator mInBarRelatedSearchesAnimation;
+
+    /** The height of the Related Searches section of the Bar, as adjusted during animation. */
+    private float mInBarRelatedSearchesAnimatedHeight;
+
     /**
      * Constructs a new bottom bar control container by inflating views from XML.
      *
@@ -540,4 +546,38 @@
         mSearchBarContextOpacity = fadingOutPercentage;
         mSearchBarTermOpacity = fadingInPercentage;
     }
+
+    /** Animates showing Related Searches in the bottom part of the Bar. */
+    public void animateInBarRelatedSearches() {
+        if (mInBarRelatedSearchesAnimation == null) {
+            mInBarRelatedSearchesAnimation =
+                    CompositorAnimator.ofFloat(mContextualSearchPanel.getAnimationHandler(), 0.f,
+                            1.f, OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null);
+            mInBarRelatedSearchesAnimation.addUpdateListener(
+                    animator -> updateInBarRelatedSearchesSize(animator.getAnimatedValue()));
+            mInBarRelatedSearchesAnimation.start();
+        }
+    }
+
+    /**
+     * Updates the portion of the Related Searches UI that is shown.
+     * @param percentage The percentage (from 0 to 1) of the UI to expose.
+     */
+    private void updateInBarRelatedSearchesSize(float percentage) {
+        mInBarRelatedSearchesAnimatedHeight = getInBarRelatedSearchesMaximumHeight() * percentage;
+        mContextualSearchPanel.setClampedPanelHeight(mInBarRelatedSearchesAnimatedHeight);
+    }
+
+    /** Returns the maximum height of the Related Searches UI that we show right in the Bar. */
+    private float getInBarRelatedSearchesMaximumHeight() {
+        return mContextualSearchPanel.getRelatedSearchesMaximumHeight();
+    }
+
+    /**
+     * Returns the current height of the portion of the Related Searches UI that is visible
+     * due to animation.
+     */
+    float getInBarRelatedSearchesAnimatedHeight() {
+        return mInBarRelatedSearchesAnimatedHeight;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index bd99b4d..e3db1c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchUma;
 import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag;
 import org.chromium.chrome.browser.flags.ActivityType;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
@@ -443,7 +444,7 @@
     @Override
     public float getContentY() {
         return getOffsetY() + getBarContainerHeight() + getPanelHelpHeight()
-                + getRelatedSearchesHeight() + getPromoHeightPx() * mPxToDp;
+                + getRelatedSearchesMaximumHeight() + getPromoHeightPx() * mPxToDp;
     }
 
     @Override
@@ -462,6 +463,17 @@
         return getTabHeight() * MAXIMIZED_HEIGHT_FRACTION;
     }
 
+    @Override
+    public float getBarHeight() {
+        return super.getBarHeight() + getInBarRelatedSearchesAnimatedHeight();
+    }
+
+    @Override
+    public void setClampedPanelHeight(float height) {
+        // TODO(donnd): better to just expose the super method to be public?
+        super.setClampedPanelHeight(height);
+    }
+
     // ============================================================================================
     // Animation Handling
     // ============================================================================================
@@ -707,6 +719,11 @@
         getSearchBarControl().setQuickAction(
                 quickActionUri, quickActionCategory, mToolbarManager.getPrimaryColor());
         getImageControl().setThumbnailUrl(thumbnailUrl);
+
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.RELATED_SEARCHES_IN_BAR)
+                && relatedSearches.size() > 0) {
+            getSearchBarControl().animateInBarRelatedSearches();
+        }
     }
 
     /**
@@ -919,6 +936,11 @@
         }
     }
 
+    /** Returns whether we currently have a Search Bar created. */
+    private boolean haveSearchBarControl() {
+        return mSearchBarControl != null;
+    }
+
     // ============================================================================================
     // Image Control
     // ============================================================================================
@@ -1010,8 +1032,9 @@
                 @Override
                 public float getYPositionPx() {
                     // Needs to enumerate anything that can appear above it in the panel.
-                    return Math.round((getOffsetY() + getBarContainerHeight()
-                                              + getRelatedSearchesHeight() + getPanelHelpHeight())
+                    return Math.round(
+                            (getOffsetY() + getBarContainerHeight()
+                                    + getRelatedSearchesMaximumHeight() + getPanelHelpHeight())
                             / mPxToDp);
                 }
 
@@ -1082,8 +1105,8 @@
                 @Override
                 public float getYPositionPx() {
                     // Needs to enumerate anything that can appear above it in the panel.
-                    return Math.round(
-                            (getOffsetY() + getBarContainerHeight() + getRelatedSearchesHeight())
+                    return Math.round((getOffsetY() + getBarContainerHeight()
+                                              + getRelatedSearchesMaximumHeight())
                             / mPxToDp);
                 }
 
@@ -1129,13 +1152,22 @@
     }
 
     /**
-     * @return Height of this section of the panel in DPs.
+     * @return Total height of this section of the panel in DPs (once fully exposed by animation).
      */
-    private float getRelatedSearchesHeight() {
+    float getRelatedSearchesMaximumHeight() {
         return getRelatedSearchesControl().getHeightPx() * mPxToDp;
     }
 
     /**
+     * @return Height of the Related Searches UI as currently show right inside the Bar, in DPs.
+     */
+    public float getInBarRelatedSearchesAnimatedHeight() {
+        return haveSearchBarControl()
+                ? getSearchBarControl().getInBarRelatedSearchesAnimatedHeight()
+                : 0.f;
+    }
+
+    /**
      * Destroys the RelatedSearchesControl.
      */
     private void destroyRelatedSearchesControl() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
index b891a77..7cb1455 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -174,6 +174,7 @@
                 panelHelpContainerBackgroundColor,
                 // Related Searches
                 relatedSearchesViewId, relatedSearchesVisible, relatedSearchesHeightPx,
+                panel.getInBarRelatedSearchesAnimatedHeight() * mDpToPx,
                 // Banner etc.
                 searchBarBannerVisible, searchBarBannerHeightPx, searchBarBannerPaddingPx,
                 searchBarBannerRippleWidthPx, searchBarBannerRippleOpacity,
@@ -254,7 +255,7 @@
                 float panelHelpOpacity, int panelHelpBackgroundColor,
                 // Related Searches
                 int relatedSearchesResourceId, boolean relatedSearchesVisible,
-                float relatedSearchesHeight,
+                float relatedSearchesHeight, float inBarRelatedSearchesHeight,
                 // Banner etc
                 boolean searchBarBannerVisible, float searchBarBannerHeight,
                 float searchBarBannerPaddingPx, float searchBarBannerRippleWidth,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS
deleted file mode 100644
index 61d47932..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DEPS
+++ /dev/null
@@ -1,30 +0,0 @@
-noparent = True
-
-include_rules = [
-  "-chrome/android/java/src/org/chromium/chrome/browser",
-  "+chrome/android/java/src/org/chromium/chrome/browser/omnibox",
-
-  "+base/android/java/src/org/chromium/base",
-  "+chrome/browser/feature_engagement",
-  "+chrome/browser/flags",
-  "+chrome/browser/lens",
-  "+chrome/browser/locale",
-  "+chrome/browser/privacy/settings",
-  "+chrome/browser/profiles/android",
-  "+chrome/browser/search_engines/android",
-  "+chrome/browser/share/android",
-  "+chrome/browser/signin/services/android",
-  "+chrome/browser/tab",
-  "+chrome/browser/tabmodel/android",
-  "+chrome/browser/ui/android",
-  "+chrome/browser/user_education",
-  "+components/browser_ui/settings/android",
-  "+components/browser_ui/share/android",
-  "+components/embedder_support/android",
-  "+components/feature_engagement/public/android",
-  "+components/omnibox/browser/android",
-  "+components/page_info/android/java/src/org/chromium/components/page_info",
-  "+components/signin/public/android",
-  "+ui/android/java/src/org/chromium/ui/base",
-  "+url/android",
-]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OWNERS
deleted file mode 100644
index 13e593d..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ender@google.com
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
index 16cc72c..91c078ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
@@ -1046,6 +1046,14 @@
         return true;
     }
 
+    // Implements PaymentUiServiceTestInterface:
+    @Override
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    public boolean closeDialogForTest() {
+        if (!mHasClosed) close();
+        return true;
+    }
+
     /** Provide PaymentInformation to the PaymentRequest UI. */
     public void providePaymentInformationToPaymentRequestUI() {
         // Do not display service worker payment apps summary in single line so as to display its
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/sms_fetcher/SmsFetcherMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/sms_fetcher/SmsFetcherMessageHandler.java
index 5feffbc..848bc59 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/sms_fetcher/SmsFetcherMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/sms_fetcher/SmsFetcherMessageHandler.java
@@ -31,7 +31,8 @@
     private static final String TAG = "SmsMessageHandler";
     private static final boolean DEBUG = false;
     private static long sSmsFetcherMessageHandlerAndroid;
-    private static String sOrigin;
+    private static String sTopOrigin;
+    private static String sEmbeddedOrigin;
 
     /**
      * Handles the interaction of an incoming notification when an expected SMS arrives.
@@ -53,12 +54,12 @@
                 case NOTIFICATION_ACTION_CONFIRM:
                     if (DEBUG) Log.d(TAG, "Notification confirmed");
                     SmsFetcherMessageHandlerJni.get().onConfirm(
-                            sSmsFetcherMessageHandlerAndroid, sOrigin);
+                            sSmsFetcherMessageHandlerAndroid, sTopOrigin, sEmbeddedOrigin);
                     break;
                 case NOTIFICATION_ACTION_CANCEL:
                     if (DEBUG) Log.d(TAG, "Notification canceled");
                     SmsFetcherMessageHandlerJni.get().onDismiss(
-                            sSmsFetcherMessageHandlerAndroid, sOrigin);
+                            sSmsFetcherMessageHandlerAndroid, sTopOrigin, sEmbeddedOrigin);
                     break;
             }
         }
@@ -69,14 +70,17 @@
      * device.
      *
      * @param oneTimeCode The one time code from SMS
-     * @param origin The origin from the SMS
+     * @param topOrigin The top frame origin from the SMS
+     * @param embeddedOrigin The embedded frame origin from the SMS. Null if the SMS does not
+     *         contain an iframe origin.
      * @param clientName The client name where the remote request comes from
      * @param smsFetcherMessageHandlerAndroid The native handler
      */
     @CalledByNative
-    private static void showNotification(String oneTimeCode, String origin, String clientName,
-            long smsFetcherMessageHandlerAndroid) {
-        sOrigin = origin;
+    private static void showNotification(String oneTimeCode, String topOrigin,
+            String embeddedOrigin, String clientName, long smsFetcherMessageHandlerAndroid) {
+        sTopOrigin = topOrigin;
+        sEmbeddedOrigin = embeddedOrigin;
         sSmsFetcherMessageHandlerAndroid = smsFetcherMessageHandlerAndroid;
         Context context = ContextUtils.getApplicationContext();
         PendingIntentProvider confirmIntent = PendingIntentProvider.getBroadcast(context,
@@ -93,8 +97,11 @@
         String notificationTitle = TextUtils.isEmpty(clientName)
                 ? resources.getString(R.string.sms_fetcher_notification_title_unknown_device)
                 : resources.getString(R.string.sms_fetcher_notification_title, clientName);
-        String notificationText =
-                resources.getString(R.string.sms_fetcher_notification_text, oneTimeCode, origin);
+        String notificationText = embeddedOrigin != null
+                ? resources.getString(R.string.sms_fetcher_notification_text_for_embedded_frame,
+                        oneTimeCode, topOrigin, embeddedOrigin)
+                : resources.getString(
+                        R.string.sms_fetcher_notification_text, oneTimeCode, topOrigin);
         SharingNotificationUtil.showNotification(
                 NotificationUmaTracker.SystemNotificationType.SMS_FETCHER,
                 NotificationConstants.GROUP_SMS_FETCHER,
@@ -114,12 +121,13 @@
     @CalledByNative
     private static void reset() {
         sSmsFetcherMessageHandlerAndroid = 0;
-        sOrigin = "";
+        sTopOrigin = null;
+        sEmbeddedOrigin = null;
     }
 
     @NativeMethods
     interface Natives {
-        void onConfirm(long nativeSmsFetchRequestHandler, String origin);
-        void onDismiss(long nativeSmsFetchRequestHandler, String origin);
+        void onConfirm(long nativeSmsFetchRequestHandler, String topOrigin, String embeddedOrigin);
+        void onDismiss(long nativeSmsFetchRequestHandler, String topOrigin, String embeddedOrigin);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
index d36a507..0e134a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
@@ -20,6 +20,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
@@ -76,7 +77,7 @@
             FilteringResult.FORCE_SURVEY_ON_COMMAND_PRESENT,
             FilteringResult.USER_ALREADY_SAMPLED_TODAY, FilteringResult.MAX_NUMBER_MISSING,
             FilteringResult.ROLLED_NON_ZERO_NUMBER, FilteringResult.USER_SELECTED_FOR_SURVEY,
-            FilteringResult.SURVEY_ALREADY_EXISTS})
+            FilteringResult.FIRST_TIME_USER})
     @Retention(RetentionPolicy.SOURCE)
     public @interface FilteringResult {
         int SURVEY_INFOBAR_ALREADY_DISPLAYED = 0;
@@ -85,9 +86,9 @@
         int MAX_NUMBER_MISSING = 4;
         int ROLLED_NON_ZERO_NUMBER = 5;
         int USER_SELECTED_FOR_SURVEY = 6;
-        int SURVEY_ALREADY_EXISTS = 7;
+        int FIRST_TIME_USER = 8;
         // Number of entries
-        int NUM_ENTRIES = 8;
+        int NUM_ENTRIES = 9;
     }
 
     /**
@@ -311,11 +312,21 @@
     }
 
     /**
-     * Rolls a random number to see if the user was eligible for the survey.
+     * Rolls a random number to see if the user was eligible for the survey. The user will skip the
+     * roll if:
+     *  1. User is a first time user
+     *  2. User as performed the roll today
+     *  3. Max number is not setup correctly
+     *
      * @return Whether the user is eligible (i.e. the random number rolled was 0).
      */
     @VisibleForTesting
     boolean isRandomlySelectedForSurvey() {
+        if (FirstRunStatus.isFirstRunTriggered()) {
+            recordSurveyFilteringResult(FilteringResult.FIRST_TIME_USER);
+            return false;
+        }
+
         SharedPreferencesManager preferences = SharedPreferencesManager.getInstance();
         int lastDate = preferences.readInt(ChromePreferenceKeys.SURVEY_DATE_LAST_ROLLED, -1);
         int today = getDayOfYear();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
index 3bfa8f7e..aae7e8d7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabBuilder.java
@@ -12,6 +12,8 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 
+import java.nio.ByteBuffer;
+
 /**
  * Builds {@link Tab} using builder pattern. All Tab classes should be instantiated
  * through this builder.
@@ -31,7 +33,7 @@
     private TabDelegateFactory mDelegateFactory;
     private boolean mInitiallyHidden;
     private TabState mTabState;
-    private byte[] mSerializedCriticalPersistedTabData;
+    private ByteBuffer mSerializedCriticalPersistedTabData;
     private Callback<Tab> mPreInitializeAction;
 
     /**
@@ -153,7 +155,7 @@
      * @return {@link TabBuilder} creating the Tab
      */
     public TabBuilder setSerializedCriticalPersistedTabData(
-            @Nullable byte[] serializedCriticalPersistedTabData) {
+            @Nullable ByteBuffer serializedCriticalPersistedTabData) {
         mSerializedCriticalPersistedTabData = serializedCriticalPersistedTabData;
         return this;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 1527179..91d4759 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -66,6 +66,8 @@
 import org.chromium.ui.util.ColorUtils;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /**
  * Implementation of the interface {@link Tab}. Contains and manages a {@link ContentView}.
  * This class is not intended to be extended.
@@ -224,7 +226,7 @@
      */
     @SuppressLint("HandlerLeak")
     TabImpl(int id, boolean incognito, @Nullable @TabLaunchType Integer launchType,
-            @Nullable byte[] serializedCriticalPersistedTabData) {
+            @Nullable ByteBuffer serializedCriticalPersistedTabData) {
         mIsTabSaveEnabledSupplier.set(false);
         mId = TabIdManager.getInstance().generateValidId(id);
         mIncognito = incognito;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
index 3b53f57..84b61143 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -431,7 +431,7 @@
 
         mMerchantTrustSignalsCoordinator = new MerchantTrustSignalsCoordinator(mActivity,
                 mActivity.getWindowAndroid(), getBottomSheetController(),
-                mActivity.getWindow().getDecorView(), mActivity.getTabModelSelector(),
+                mActivity.getWindow().getDecorView(),
                 MessageDispatcherProvider.from(mActivity.getWindowAndroid()),
                 mActivity.getActivityTabProvider(), mProfileSupplier, new MerchantTrustMetrics());
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index 2990fc5..2afc525 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -43,6 +43,8 @@
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /**
  * This class creates various kinds of new tabs and adds them to the right {@link TabModel}.
  */
@@ -378,8 +380,8 @@
     }
 
     @Override
-    public Tab createFrozenTab(TabState state, byte[] serializedCriticalPersistedTabData, int id,
-            boolean isIncognito, int index) {
+    public Tab createFrozenTab(TabState state, ByteBuffer serializedCriticalPersistedTabData,
+            int id, boolean isIncognito, int index) {
         TabModelSelector selector = mTabModelSelectorSupplier.get();
         TabResolver resolver = (tabId) -> {
             return selector != null ? selector.getTabById(tabId) : null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
index a1a1c8c6..d87c1cda 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -67,6 +67,7 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -646,7 +647,7 @@
         }
     }
 
-    private static byte[] maybeRestoreCriticalPersistedTabDataSynchronously(
+    private static ByteBuffer maybeRestoreCriticalPersistedTabDataSynchronously(
             TabRestoreDetails tabToRestore) {
         if (!isCriticalPersistedTabDataEnabled()) return null;
         Boolean isIncognito = isIncognitoWithCPTDFallback(tabToRestore);
@@ -666,7 +667,7 @@
      */
     @VisibleForTesting
     protected void restoreTab(TabRestoreDetails tabToRestore, TabState tabState,
-            byte[] serializedCriticalPersistedTabData, boolean setAsActive) {
+            ByteBuffer serializedCriticalPersistedTabData, boolean setAsActive) {
         // If we don't have enough information about the Tab, bail out.
         boolean isIncognito = isIncognitoTabBeingRestored(
                 tabToRestore, tabState, serializedCriticalPersistedTabData);
@@ -1613,7 +1614,7 @@
     }
 
     private void completeLoad(TabRestoreDetails tabToRestore, TabState tabState,
-            byte[] serializedCriticalPersistedTabData) {
+            ByteBuffer serializedCriticalPersistedTabData) {
         boolean isIncognito = isIncognitoTabBeingRestored(
                 tabToRestore, tabState, serializedCriticalPersistedTabData);
         if (isIncognito) {
@@ -1665,7 +1666,7 @@
      * @return True if the tab is definitely Incognito, false if it's not or if it's undecideable.
      */
     private boolean isIncognitoTabBeingRestored(TabRestoreDetails tabDetails, TabState tabState,
-            byte[] serializedCriticalPersistedTabData) {
+            ByteBuffer serializedCriticalPersistedTabData) {
         if (tabState != null) {
             Log.i(TAG, "#isIncognitoTabBeingRestored from tabState:  " + tabState.isIncognito());
             // The Tab's previous state was completely restored.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
index 031eb43ff..81c6021 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java
@@ -36,6 +36,8 @@
 import org.chromium.ui.base.PageTransition;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /**
  * Asynchronously creates Tabs by creating/starting up Activities.
  */
@@ -74,7 +76,7 @@
      * The index is ignored in DocumentMode because Android handles the ordering of Tabs.
      */
     @Override
-    public Tab createFrozenTab(TabState state, byte[] criticalPersistedTabData, int id,
+    public Tab createFrozenTab(TabState state, ByteBuffer criticalPersistedTabData, int id,
             boolean isIncognito, int index) {
         if (isIncognito != mIsIncognito) {
             throw new IllegalStateException("Incognito state mismatch. isIncognito: " + isIncognito
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
index 2f84255..52d3bf9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
 import org.chromium.chrome.browser.tab.TabLaunchType;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.tab.WebContentsState;
 import org.chromium.chrome.browser.tab.proto.CriticalPersistedTabData.CriticalPersistedTabDataProto;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
@@ -257,7 +258,8 @@
         CriticalPersistedTabData criticalPersistedTabData = new CriticalPersistedTabData(tab, "",
                 "", PARENT_ID, ROOT_ID, TIMESTAMP, WEB_CONTENTS_STATE, CONTENT_STATE_VERSION,
                 OPENER_APP_ID, THEME_COLOR, LAUNCH_TYPE_AT_CREATION);
-        byte[] serialized = criticalPersistedTabData.getSerializeSupplier().get();
+        ByteBuffer serialized =
+                TabTestUtils.toByteBuffer(criticalPersistedTabData.getSerializeSupplier().get());
         PersistedTabDataConfiguration config = PersistedTabDataConfiguration.get(
                 ShoppingPersistedTabData.class, tab.isIncognito());
         CriticalPersistedTabData deserialized =
@@ -283,7 +285,8 @@
         CriticalPersistedTabData criticalPersistedTabData = new CriticalPersistedTabData(tab, "",
                 "", PARENT_ID, ROOT_ID, TIMESTAMP, WEB_CONTENTS_STATE, CONTENT_STATE_VERSION, null,
                 THEME_COLOR, LAUNCH_TYPE_AT_CREATION);
-        byte[] serialized = criticalPersistedTabData.getSerializeSupplier().get();
+        ByteBuffer serialized =
+                TabTestUtils.toByteBuffer(criticalPersistedTabData.getSerializeSupplier().get());
         PersistedTabDataConfiguration config = PersistedTabDataConfiguration.get(
                 ShoppingPersistedTabData.class, tab.isIncognito());
         CriticalPersistedTabData deserialized =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java
index dc0c0cb..d7ecd58 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorageTest.java
@@ -17,6 +17,7 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
 import org.chromium.chrome.browser.crypto.CipherFactory;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.tab.state.FilePersistedTabDataStorage.FileSaveRequest;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 
@@ -88,7 +89,10 @@
         });
         semaphore.acquire();
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            persistedTabDataStorage.restore(TAB_ID_1, DATA_ID_1, (res) -> {
+            persistedTabDataStorage.restore(TAB_ID_1, DATA_ID_1, (resByteBuffer) -> {
+                // TODO(crbug.com/1220763) update tests to use ByteBuffer#get to avoid
+                // ByteBuffer/byte[] conversions (and just use ByteBuffer).
+                byte[] res = TabTestUtils.toByteArray(resByteBuffer);
                 Assert.assertEquals(res.length, 2);
                 Assert.assertArrayEquals(res, DATA_A);
                 semaphore.release();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
index 2a7254e0..cdf07e00 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageTest.java
@@ -20,6 +20,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
@@ -144,7 +145,8 @@
         LoadCallbackHelper ch = new LoadCallbackHelper();
         int chCount = ch.getCallCount();
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            mPersistedTabDataStorage.restore(tabId, dataId, (res) -> { ch.notifyCalled(res); });
+            mPersistedTabDataStorage.restore(
+                    tabId, dataId, (res) -> { ch.notifyCalled(TabTestUtils.toByteArray(res)); });
         });
         ch.waitForCallback(chCount);
         Assert.assertArrayEquals(expected, ch.getRes());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
index 67d1072..e62a699 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
@@ -31,6 +31,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
@@ -38,6 +39,7 @@
 import org.chromium.components.optimization_guide.proto.HintsProto;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import java.nio.ByteBuffer;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
@@ -96,7 +98,8 @@
                 ShoppingPersistedTabDataTestUtils.PRICE_MICROS, null);
         byte[] serialized = shoppingPersistedTabData.getSerializeSupplier().get();
         ShoppingPersistedTabData deserialized = new ShoppingPersistedTabData(tab);
-        deserialized.deserialize(serialized);
+        ByteBuffer byteBuffer = TabTestUtils.toByteBuffer(serialized);
+        deserialized.deserialize(byteBuffer);
         Assert.assertEquals(
                 ShoppingPersistedTabDataTestUtils.PRICE_MICROS, deserialized.getPriceMicros());
         Assert.assertEquals(
@@ -525,7 +528,8 @@
                 ShoppingPersistedTabDataTestUtils.IS_INCOGNITO);
         ShoppingPersistedTabData shoppingPersistedTabData = new ShoppingPersistedTabData(tab);
         shoppingPersistedTabData.setPriceMicros(42_000_000L, null);
-        byte[] serialized = shoppingPersistedTabData.getSerializeSupplier().get();
+        ByteBuffer serialized =
+                TabTestUtils.toByteBuffer(shoppingPersistedTabData.getSerializeSupplier().get());
         PersistedTabDataConfiguration config = PersistedTabDataConfiguration.get(
                 ShoppingPersistedTabData.class, tab.isIncognito());
         ShoppingPersistedTabData deserialized =
@@ -544,8 +548,8 @@
         supplier.set(true);
         shoppingPersistedTabData.registerIsTabSaveEnabledSupplier(supplier);
         shoppingPersistedTabData.setMainOfferId(ShoppingPersistedTabDataTestUtils.FAKE_OFFER_ID);
-
-        byte[] serialized = shoppingPersistedTabData.getSerializeSupplier().get();
+        ByteBuffer serialized =
+                TabTestUtils.toByteBuffer(shoppingPersistedTabData.getSerializeSupplier().get());
         ShoppingPersistedTabData deserialized = new ShoppingPersistedTabData(tab);
         deserialized.deserialize(serialized);
         Assert.assertEquals(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/StorePersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/StorePersistedTabDataTest.java
index c563ffa1..c1d4076 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/StorePersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/StorePersistedTabDataTest.java
@@ -33,10 +33,12 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import java.nio.ByteBuffer;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -291,7 +293,8 @@
         StorePersistedTabData storePersistedTabData = new StorePersistedTabData(tab,
                 new StorePersistedTabData.StoreHours(
                         SERIALIZE_DESERIALIZE_OPENING_TIME, SERIALIZE_DESERIALIZE_CLOSING_TIME));
-        byte[] serialized = storePersistedTabData.getSerializeSupplier().get();
+        ByteBuffer serialized =
+                TabTestUtils.toByteBuffer(storePersistedTabData.getSerializeSupplier().get());
         StorePersistedTabData deserialized = new StorePersistedTabData(tab);
         deserialized.deserialize(serialized);
         Assert.assertEquals(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
index e8d857d3..f1f81df 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -52,6 +52,7 @@
 import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tab.TabStateFileManager;
+import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tab.state.LoadCallbackHelper;
 import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier;
@@ -428,8 +429,8 @@
         LoadCallbackHelper callbackHelper = new LoadCallbackHelper();
         int chCount = callbackHelper.getCallCount();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            CriticalPersistedTabData.restore(
-                    tabId, isIncognito, (res) -> { callbackHelper.notifyCalled(res); });
+            CriticalPersistedTabData.restore(tabId, isIncognito,
+                    (res) -> { callbackHelper.notifyCalled(TabTestUtils.toByteArray(res)); });
         });
         callbackHelper.waitForCallback(chCount);
         if (isNull) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DEPS b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DEPS
deleted file mode 100644
index de5cac7b..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-    "+chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar",
-]
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DIR_METADATA b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DIR_METADATA
deleted file mode 100644
index 07a4669..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
-  component: "UI>Browser>Omnibox"
-}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/OWNERS
deleted file mode 100644
index a7cc05d..0000000
--- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://chrome/android/java/src/org/chromium/chrome/browser/omnibox/OWNERS
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
index 49492ecc..0c9c85cf 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
@@ -10,6 +10,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -23,6 +24,7 @@
 
 import org.chromium.base.metrics.test.ShadowRecordHistogram;
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.survey.ChromeSurveyController.FilteringResult;
@@ -63,6 +65,11 @@
         Assert.assertNull("Tab should be null", mTestController.getLastTabInfobarShown());
     }
 
+    @After
+    public void after() {
+        FirstRunStatus.setFirstRunTriggered(false);
+    }
+
     @Test
     public void testInfoBarDisplayedBefore() {
         final String triggerId1 = "triggerId1";
@@ -183,6 +190,15 @@
     }
 
     @Test
+    public void testEligibilityFirstRun() {
+        FirstRunStatus.setFirstRunTriggered(true);
+        mRiggedController = new RiggedSurveyController(0, 1, 10);
+        Assert.assertFalse("Random selection should be false",
+                mRiggedController.isRandomlySelectedForSurvey());
+        verifyFilteringResultRecorded(FilteringResult.FIRST_TIME_USER, 1);
+    }
+
+    @Test
     public void testEligibilityRolledYesterday() {
         mRiggedController = new RiggedSurveyController(0, 5, 10);
         mSharedPreferences.writeInt(ChromePreferenceKeys.SURVEY_DATE_LAST_ROLLED, 4);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 287316c..aa6f1df 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5441,11 +5441,6 @@
       <message name="IDS_OMNIBOX_REMOVE_SUGGESTION_BUBBLE_DESCRIPTION" desc="The description of a bubble to delete an omnibox suggestion.">
         This page will also be removed from your history and <ph name="SEARCH_ENGINE">$1<ex>Google</ex></ph> activity.
       </message>
-      <if expr="is_android">
-      <message name="IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD" desc="A message within a modal dialog that confirms the user wants to delete a clipboard suggestion from the list dropdown in the omnibox." formatter_data="android_java">
-        Remove suggestion from clipboard?
-      </message>
-      </if>
       <if expr="use_titlecase">
         <message name="IDS_CONTEXT_MENU_SHOW_FULL_URLS" desc="In Title Case: The text label of the omnibox context menu option to show full URLs">
           Always Show Full URLs
@@ -7089,9 +7084,18 @@
       <message name="IDS_TAB_SEARCH_OPEN_TABS" desc="The label on the tab search list section corresponding to open tabs.">
         Open Tabs
       </message>
+      <message name="IDS_TAB_SEARCH_RECENTLY_CLOSED" desc="The label on the tab search list section corresponding to recently closed entries.">
+        Recently Closed
+      </message>
       <message name="IDS_TAB_SEARCH_RECENTLY_CLOSED_TABS" desc="The label on the tab search list section corresponding to recently closed tabs.">
         Recently Closed Tabs
       </message>
+      <message name="IDS_TAB_SEARCH_ONE_TAB" desc="Singular form of a message indicating the presence of a single tab.">
+        <ph name="NUM">$1<ex>1</ex></ph> Tab
+      </message>
+      <message name="IDS_TAB_SEARCH_TAB_COUNT" desc="Plural form of a message indicating the presence of a number of tabs greater than one.">
+        <ph name="NUM">$1<ex>2</ex></ph> Tabs
+      </message>
 
       <!-- Strings for Window Titles in Menus -->
       <if expr="not use_titlecase">
@@ -11240,6 +11244,9 @@
     <message name="IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE" desc="Message shown around the custom message provided by the administrator when deep scanning returns a failure.">
       Your administrator says "<ph name="CUSTOM_MESSAGE">$1<ex>Please don't upload this type of data.</ex></ph>".
     </message>
+    <message name="IDS_DEEP_SCANNING_DIALOG_DOWNLOADS_CUSTOM_MESSAGE" desc="Message shown around the custom message provided by the administrator when deep scanning returns a failure on a downloaded file.">
+      <ph name="FILE_NAME">$1<ex>foo.txt</ex></ph> has sensitive or dangerous data. Your administrator says "<ph name="CUSTOM_MESSAGE">$2<ex>Please don't upload this type of data.</ex></ph>".
+    </message>
     <message name="IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE_LEARN_MORE_LINK" desc="Text value of the link passed for the custom message set by the administrator when deep scanning returns a failure.">
       Learn more
     </message>
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_ONE_TAB.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_ONE_TAB.png.sha1
new file mode 100644
index 0000000..5ff8670
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_ONE_TAB.png.sha1
@@ -0,0 +1 @@
+8530c4b17eb5ab301fb77ea28ae52e8f3f39961a
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_RECENTLY_CLOSED.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_RECENTLY_CLOSED.png.sha1
new file mode 100644
index 0000000..00893290
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_RECENTLY_CLOSED.png.sha1
@@ -0,0 +1 @@
+6ce3516d030557d940b7d0fe4f78a4886cc0cab1
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_TAB_COUNT.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_TAB_COUNT.png.sha1
new file mode 100644
index 0000000..16655955
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_TAB_SEARCH_TAB_COUNT.png.sha1
@@ -0,0 +1 @@
+b89df5cf4190d642747db0a3b1583e5302b7c906
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index 5fbea96..a1ebf981 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -538,6 +538,15 @@
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_EDIT_USER_DICT" desc="The label for the input method option to let the users edit their personal dictionary.">
     Edit dictionary entries
   </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT">
+    Physical keyboard layout
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS">
+    Selection keys
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE">
+    Number of candidates to display per page
+  </message>
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_CHINESE_PUNCTUATION" desc="The label for the pinyin input method option for whether to output full-width or half-with punctuation.">
     Initial punctuation width is Full
   </message>
@@ -568,6 +577,15 @@
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_US" desc="The label for the choice to use US keyboard.">
     US
   </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT" desc="The label for the choice to use for Zhuyin keyboard.">
+    Default
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM" desc="The label for the choice to use for Zhuyin keyboard.">
+    IBM
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN" desc="The label for the choice to use for Zhuyin keyboard.">
+    Eten
+  </message>
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_DVORAK" desc="The label for the choice to use Dvorak keyboard.">
     Dvorak
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT.png.sha1
new file mode 100644
index 0000000..fc850b16
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT.png.sha1
@@ -0,0 +1 @@
+0e43eaeeb03b82400c628de017b3c343dbe5aefc
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT.png.sha1
new file mode 100644
index 0000000..ffb14fe
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT.png.sha1
@@ -0,0 +1 @@
+e7f2ba3c64d00d4658a1c20b723ffbd98f99a1d1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN.png.sha1
new file mode 100644
index 0000000..ffb14fe
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN.png.sha1
@@ -0,0 +1 @@
+e7f2ba3c64d00d4658a1c20b723ffbd98f99a1d1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM.png.sha1
new file mode 100644
index 0000000..ffb14fe
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM.png.sha1
@@ -0,0 +1 @@
+e7f2ba3c64d00d4658a1c20b723ffbd98f99a1d1
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE.png.sha1
new file mode 100644
index 0000000..fc850b16
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE.png.sha1
@@ -0,0 +1 @@
+0e43eaeeb03b82400c628de017b3c343dbe5aefc
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS.png.sha1
new file mode 100644
index 0000000..fc850b16
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS.png.sha1
@@ -0,0 +1 @@
+0e43eaeeb03b82400c628de017b3c343dbe5aefc
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 791e073..3a4d656c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2948,6 +2948,8 @@
       "chrome_browser_main_android.h",
       "commerce/merchant_viewer/web_contents_helper.cc",
       "content_creation/notes/internal/android/note_service_bridge_factory.cc",
+      "content_creation/notes/internal/note_service_factory.cc",
+      "content_creation/notes/internal/note_service_factory.h",
       "crash_upload_list/crash_upload_list_android.cc",
       "crash_upload_list/crash_upload_list_android.h",
       "data_reduction_proxy/data_reduction_promo_infobar_delegate_android.cc",
@@ -3223,7 +3225,6 @@
       "//chrome/browser/commerce/subscriptions:commerce_subscription_db_content_proto",
       "//chrome/browser/commerce/subscriptions/android:jni_headers",
       "//chrome/browser/consent_auditor/android:jni_headers",
-      "//chrome/browser/content_creation/notes/internal",
       "//chrome/browser/content_creation/notes/internal/android:jni_headers",
       "//chrome/browser/continuous_search:jni_headers",
       "//chrome/browser/continuous_search/internal",
@@ -3279,7 +3280,10 @@
       "//components/component_updater/android:native_background_task_update_scheduler",
       "//components/content_capture/android",
       "//components/content_creation/notes/android",
+      "//components/content_creation/notes/core",
       "//components/content_creation/notes/core:features",
+      "//components/content_creation/notes/core/server",
+      "//components/content_creation/notes/core/templates",
       "//components/content_settings/android",
       "//components/crash/android:crash_android",
       "//components/embedder_support/android:browser_context",
@@ -4803,6 +4807,7 @@
       "apps/app_service/app_web_contents_data.h",
       "apps/app_service/media_requests.cc",
       "apps/app_service/media_requests.h",
+      "apps/app_service/menu_item_constants.h",
     ]
   }
 
@@ -5753,8 +5758,6 @@
 
   if (enable_extensions) {
     sources += [
-      "accessibility/accessibility_extension_api.cc",
-      "accessibility/accessibility_extension_api.h",
       "accessibility/animation_policy_prefs.cc",
       "accessibility/animation_policy_prefs.h",
       "autocomplete/keyword_extensions_delegate_impl.cc",
@@ -5966,6 +5969,8 @@
     ]
     if (is_chromeos_ash) {
       sources += [
+        "accessibility/accessibility_extension_api_chromeos.cc",
+        "accessibility/accessibility_extension_api_chromeos.h",
         "speech/extension_api/tts_engine_extension_api_chromeos.cc",
         "speech/extension_api/tts_engine_extension_api_chromeos.h",
         "speech/extension_api/tts_engine_extension_observer_chromeos.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 946e1dc3..14a7a87 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2882,6 +2882,9 @@
     {"screen-capture", flag_descriptions::kScreenCaptureTestName,
      flag_descriptions::kScreenCaptureTestDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kCaptureMode)},
+    {"ash-bento-bar", flag_descriptions::kBentoBarName,
+     flag_descriptions::kBentoBarDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(ash::features::kBentoBar)},
     {"ash-window-follow-cursor-multi-display",
      flag_descriptions::kWindowsFollowCursorName,
      flag_descriptions::kWindowsFollowCursorDescription, kOsCrOS,
@@ -3355,21 +3358,6 @@
     {"pluginvm-fullscreen", flag_descriptions::kPluginVmFullscreenName,
      flag_descriptions::kPluginVmFullscreenDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kPluginVmFullscreen)},
-    {"pluginvm-show-camera-permissions",
-     flag_descriptions::kPluginVmShowCameraPermissionsName,
-     flag_descriptions::kPluginVmShowCameraPermissionsDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(chromeos::features::kPluginVmShowCameraPermissions)},
-    {"pluginvm-show-microphone-permissions",
-     flag_descriptions::kPluginVmShowMicrophonePermissionsName,
-     flag_descriptions::kPluginVmShowMicrophonePermissionsDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(
-         chromeos::features::kPluginVmShowMicrophonePermissions)},
-    {"vm-camera-mic-indicators-and-notifications",
-     flag_descriptions::kVmCameraMicIndicatorsAndNotificationsName,
-     flag_descriptions::kVmCameraMicIndicatorsAndNotificationsDescription,
-     kOsCrOS,
-     FEATURE_VALUE_TYPE(
-         chromeos::features::kVmCameraMicIndicatorsAndNotifications)},
     {"vm-status-page", flag_descriptions::kVmStatusPageName,
      flag_descriptions::kVmStatusPageDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kVmStatusPage)},
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
similarity index 95%
rename from chrome/browser/accessibility/accessibility_extension_api.cc
rename to chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
index 8a7d5015..d73dc3e 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.cc
+++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
@@ -2,13 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/accessibility/accessibility_extension_api.h"
+#include "chrome/browser/accessibility/accessibility_extension_api_chromeos.h"
 
 #include <stddef.h>
 #include <memory>
 #include <set>
 #include <vector>
 
+#include "ash/public/cpp/accessibility_controller.h"
+#include "ash/public/cpp/accessibility_controller_enums.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
+#include "ash/public/cpp/event_rewriter_controller.h"
+#include "ash/public/cpp/window_tree_host_lookup.h"
 #include "base/bind.h"
 #include "base/json/json_writer.h"
 #include "base/strings/string_number_conversions.h"
@@ -16,11 +21,16 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/ash/accessibility/accessibility_manager.h"
+#include "chrome/browser/ash/accessibility/magnification_manager.h"
+#include "chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#include "chrome/browser/ui/webui/settings/chromeos/constants/routes_util.h"
 #include "chrome/common/extensions/api/accessibility_private.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/webui_url_constants.h"
@@ -36,36 +46,18 @@
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/accessibility/accessibility_switches.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/public/cpp/accessibility_controller.h"
-#include "ash/public/cpp/accessibility_controller_enums.h"
-#include "ash/public/cpp/accessibility_focus_ring_info.h"
-#include "ash/public/cpp/event_rewriter_controller.h"
-#include "ash/public/cpp/window_tree_host_lookup.h"
-#include "chrome/browser/ash/accessibility/accessibility_manager.h"
-#include "chrome/browser/ash/accessibility/magnification_manager.h"
-#include "chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h"
-#include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/ui/webui/settings/chromeos/constants/routes_util.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/wm/core/coordinate_conversion.h"
-#endif
 
 namespace {
 
 namespace accessibility_private = ::extensions::api::accessibility_private;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
 using ::ash::AccessibilityManager;
-#endif
-
-const char kErrorNotSupported[] = "This API is not supported on this platform.";
 
 }  // namespace
 
@@ -74,11 +66,9 @@
   bool enabled = false;
   EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
   if (enabled) {
-    content::BrowserAccessibilityState::GetInstance()->
-        EnableAccessibility();
+    content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
   } else {
-    content::BrowserAccessibilityState::GetInstance()->
-        DisableAccessibility();
+    content::BrowserAccessibilityState::GetInstance()->DisableAccessibility();
   }
   return RespondNow(NoArguments());
 }
@@ -89,7 +79,6 @@
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO(chrome-a11y-core): we can't open a settings page when you're on the
   // signin profile, but maybe we should notify the user and explain why?
   Profile* profile = AccessibilityManager::Get()->profile();
@@ -98,16 +87,12 @@
     chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
         profile, params->subpage);
   }
-#else
-  // This function should only be available on ChromeOS.
-  EXTENSION_FUNCTION_VALIDATE(false);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   return RespondNow(NoArguments());
 }
 
 ExtensionFunction::ResponseAction
 AccessibilityPrivateSetFocusRingsFunction::Run() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<accessibility_private::SetFocusRings::Params> params(
       accessibility_private::SetFocusRings::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
@@ -193,14 +178,10 @@
   }
 
   return RespondNow(NoArguments());
-#else
-  return RespondNow(Error(kErrorNotSupported));
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 }
 
 ExtensionFunction::ResponseAction
 AccessibilityPrivateSetHighlightsFunction::Run() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
   std::unique_ptr<accessibility_private::SetHighlights::Params> params(
       accessibility_private::SetHighlights::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
@@ -218,16 +199,12 @@
   AccessibilityManager::Get()->SetHighlights(rects, color);
 
   return RespondNow(NoArguments());
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-  return RespondNow(Error(kErrorNotSupported));
 }
 
 ExtensionFunction::ResponseAction
 AccessibilityPrivateSetKeyboardListenerFunction::Run() {
   CHECK(extension());
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool enabled;
   bool capture;
   EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &enabled));
@@ -246,24 +223,16 @@
   ash::EventRewriterController::Get()->CaptureAllKeysForSpokenFeedback(
       enabled && capture);
   return RespondNow(NoArguments());
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-  return RespondNow(Error(kErrorNotSupported));
 }
 
 ExtensionFunction::ResponseAction
 AccessibilityPrivateDarkenScreenFunction::Run() {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
   bool darken = false;
   EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &darken));
   AccessibilityManager::Get()->SetDarkenScreen(darken);
   return RespondNow(NoArguments());
-#else
-  return RespondNow(Error(kErrorNotSupported));
-#endif
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
 ExtensionFunction::ResponseAction
 AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction::Run() {
   std::unique_ptr<
@@ -705,5 +674,3 @@
     bool confirmed) {
   Respond(OneArgument(base::Value(confirmed)));
 }
-
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/accessibility/accessibility_extension_api.h b/chrome/browser/accessibility/accessibility_extension_api_chromeos.h
similarity index 98%
rename from chrome/browser/accessibility/accessibility_extension_api.h
rename to chrome/browser/accessibility/accessibility_extension_api_chromeos.h
index fd71432c..bf8708f 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.h
+++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_H_
-#define CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_H_
+#ifndef CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_CHROMEOS_H_
+#define CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_CHROMEOS_H_
 
 #include "build/chromeos_buildflags.h"
 #include "extensions/browser/extension_function.h"
@@ -60,7 +60,6 @@
                              ACCESSIBILITY_PRIVATE_OPENSETTINGSSUBPAGE)
 };
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
 // API function that sets native ChromeVox ARC support.
 class AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction
     : public ExtensionFunction {
@@ -224,6 +223,5 @@
   DECLARE_EXTENSION_FUNCTION("accessibilityPrivate.showConfirmationDialog",
                              ACCESSIBILITY_PRIVATE_SHOWCONFIRMATIONDIALOG)
 };
-#endif  // defined (OS_CHROMEOS)
 
-#endif  // CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_H_
+#endif  // CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_CHROMEOS_H_
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.cc b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
index bc67533..73b8006 100644
--- a/chrome/browser/android/compositor/layer/contextual_search_layer.cc
+++ b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
@@ -65,6 +65,7 @@
     int related_searches_resource_id,
     bool related_searches_visible,
     float related_searches_height,
+    float in_bar_related_searches_height,
     // Banner etc
     bool search_bar_banner_visible,
     float search_bar_banner_height,
@@ -132,13 +133,14 @@
       search_bar_margin_side, search_bar_margin_top, search_bar_height,
       search_bar_top, search_term_opacity, should_render_bar_border,
       search_bar_border_height, icon_color, drag_handlebar_color,
-      close_icon_opacity, separator_line_color);
+      close_icon_opacity, separator_line_color, in_bar_related_searches_height);
 
   // -----------------------------------------------------------------
   // Content setup, to center in space below drag handle (when present).
   // -----------------------------------------------------------------
   bool is_rtl = l10n_util::IsLayoutRtl();
-  int content_height = search_bar_height - search_bar_margin_top;
+  int content_height = search_bar_height - search_bar_margin_top -
+                       in_bar_related_searches_height;
   int content_top = search_bar_top + search_bar_margin_top;
 
   // -----------------------------------------------------------------
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.h b/chrome/browser/android/compositor/layer/contextual_search_layer.h
index b24cf4b..a5ab5af 100644
--- a/chrome/browser/android/compositor/layer/contextual_search_layer.h
+++ b/chrome/browser/android/compositor/layer/contextual_search_layer.h
@@ -65,6 +65,7 @@
                      int related_searches_resource_id,
                      bool related_searches_visible,
                      float related_searches_height,
+                     float in_bar_related_searches_height,
                      // Banner etc
                      bool search_bar_banner_visible,
                      float search_bar_banner_height,
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
index 9372031ff..6a4fb23 100644
--- a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
+++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
@@ -78,12 +78,15 @@
     int icon_tint,
     int drag_handlebar_tint,
     float icon_opacity,
-    int separator_line_color) {
+    int separator_line_color,
+    float in_bar_related_searches_height) {
   // Round values to avoid pixel gap between layers.
   bar_height = floor(bar_height);
 
   // ---------------------------------------------------------------------------
   // Content setup, to center in space below drag handle (when present).
+  // When Related Searches are shown in the Bar they appear below the rest of
+  // this content.
   // ---------------------------------------------------------------------------
   float bar_top_y = bar_offset_y;
   float bar_bottom = bar_top_y + bar_height;
@@ -91,7 +94,7 @@
   bool is_rtl = l10n_util::IsLayoutRtl();
 
   int content_top_y = bar_top_y;
-  int content_height = bar_height;
+  int content_height = bar_height - in_bar_related_searches_height;
   int rounded_top_height = 0;
   gfx::Size rounded_bar_top_size;
   gfx::PointF rounded_bar_top_position;
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.h b/chrome/browser/android/compositor/layer/overlay_panel_layer.h
index 582c78c9..cdd78fd 100644
--- a/chrome/browser/android/compositor/layer/overlay_panel_layer.h
+++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.h
@@ -55,7 +55,8 @@
                      int icon_tint,
                      int drag_handlebar_tint,
                      float icon_opacity,
-                     int separator_line_color);
+                     int separator_line_color,
+                     float in_bar_related_searches_height);
 
   void SetProgressBar(int progress_bar_background_resource_id,
                       int progress_bar_resource_id,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
index 75f1e98..4b5ae8c4 100644
--- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -104,6 +104,7 @@
     jint related_searches_resource_id,
     jboolean related_searches_visible,
     jfloat related_searches_height,
+    jfloat in_bar_related_searches_height,
     // Banner etc
     jboolean search_bar_banner_visible,
     jfloat search_bar_banner_height,
@@ -185,7 +186,7 @@
       panel_help_opacity, panel_help_container_background_color,
       // Related Searches
       related_searches_resource_id, related_searches_visible,
-      related_searches_height,
+      related_searches_height, in_bar_related_searches_height,
       // Banner etc
       search_bar_banner_visible, search_bar_banner_height,
       search_bar_banner_padding, search_bar_banner_ripple_width,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
index 34ce6be..a5a0ed2 100644
--- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.h
@@ -79,6 +79,7 @@
       jint related_searches_resource_id,
       jboolean related_searches_visible,
       jfloat related_searches_height,
+      jfloat in_bar_related_searches_height,
       // Banner etc
       jboolean search_bar_banner_visible,
       jfloat search_bar_banner_height,
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index 49569362..ce6c271 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -58,7 +58,7 @@
  public:
   Job(FaviconHelper* favicon_helper,
       favicon::FaviconService* favicon_service,
-      std::vector<GURL> urls,
+      std::vector<std::string> urls,
       int desire_size_in_pixel,
       JobFinishedCallback job_finished_callback,
       favicon_base::FaviconResultsCallback result_callback);
@@ -73,7 +73,7 @@
                           const favicon_base::FaviconRawBitmapResult& result);
   FaviconHelper* favicon_helper_;
   favicon::FaviconService* favicon_service_;
-  std::vector<GURL> urls_;
+  std::vector<std::string> urls_;
   int desire_size_in_pixel_;
   JobFinishedCallback job_finished_callback_;
   favicon_base::FaviconResultsCallback result_callback_;
@@ -86,7 +86,7 @@
 
 FaviconHelper::Job::Job(FaviconHelper* favicon_helper,
                         favicon::FaviconService* favicon_service,
-                        std::vector<GURL> urls,
+                        std::vector<std::string> urls,
                         int desire_size_in_pixel,
                         JobFinishedCallback job_finished_callback,
                         favicon_base::FaviconResultsCallback result_callback)
@@ -113,7 +113,7 @@
                        weak_ptr_factory_.GetWeakPtr(), i);
 
     favicon_helper_->GetLocalFaviconImageForURLInternal(
-        favicon_service_, urls_.at(i), desire_size_in_pixel_,
+        favicon_service_, GURL(urls_.at(i)), desire_size_in_pixel_,
         std::move(callback));
   }
 }
@@ -180,8 +180,8 @@
                      ScopedJavaGlobalRef<jobject>(j_favicon_image_callback),
                      desired_size_in_pixel);
 
-  std::vector<GURL> urls;
-  url::GURLAndroid::JavaGURLArrayToGURLVector(env, j_urls, &urls);
+  std::vector<std::string> urls;
+  base::android::AppendJavaStringArrayToStringVector(env, j_urls, &urls);
 
   GetComposedFaviconImageInternal(favicon_service, urls,
                                   static_cast<int>(j_desired_size_in_pixel),
@@ -192,7 +192,7 @@
 
 void FaviconHelper::GetComposedFaviconImageInternal(
     favicon::FaviconService* favicon_service,
-    std::vector<GURL> urls,
+    std::vector<std::string> urls,
     int desired_size_in_pixel,
     favicon_base::FaviconResultsCallback callback_runner) {
   DCHECK(favicon_service);
diff --git a/chrome/browser/android/favicon_helper.h b/chrome/browser/android/favicon_helper.h
index 63f3d0e..cf3b992 100644
--- a/chrome/browser/android/favicon_helper.h
+++ b/chrome/browser/android/favicon_helper.h
@@ -48,7 +48,7 @@
       favicon_base::FaviconRawBitmapCallback callback_runner);
   void GetComposedFaviconImageInternal(
       favicon::FaviconService* favicon_service,
-      std::vector<GURL> urls,
+      std::vector<std::string> urls,
       int desired_size_in_pixel,
       favicon_base::FaviconResultsCallback callback_runner);
   void OnJobFinished(int job_id);
diff --git a/chrome/browser/android/favicon_helper_unittest.cc b/chrome/browser/android/favicon_helper_unittest.cc
index b32cf4e9..e86be60 100644
--- a/chrome/browser/android/favicon_helper_unittest.cc
+++ b/chrome/browser/android/favicon_helper_unittest.cc
@@ -89,9 +89,10 @@
 
 TEST_F(FaviconHelperTest, GetComposedFaviconImage) {
   raw_bitmap_results_.clear();
-  GURL url1 = GURL("http://www.tab1.com");
-  GURL url2 = GURL("http://www.tab2.com");
-  std::vector<GURL> urls = {url1, url2};
+  std::vector<std::string> urls = {"http://www.tab1.com",
+                                   "http://www.tab2.com"};
+  GURL url1 = GURL(urls[0]);
+  GURL url2 = GURL(urls[1]);
 
   EXPECT_CALL(mock_favicon_service_,
               GetRawFaviconForPageURL(url1, _, _, 16, _, _))
@@ -111,10 +112,11 @@
 
 TEST_F(FaviconHelperTest, GetComposedFaviconImageWithOneFaviconFailed) {
   raw_bitmap_results_.clear();
-  GURL url1 = GURL("http://www.tab1.com");
-  GURL url2 = GURL("http://www.tab2.com");
-  GURL url3 = GURL("http://www.tab3.com");
-  std::vector<GURL> urls = {url1, url2, url3};
+  std::vector<std::string> urls = {"http://www.tab1.com", "http://www.tab2.com",
+                                   "http://www.tab3.com"};
+  GURL url1 = GURL(urls[0]);
+  GURL url2 = GURL(urls[1]);
+  GURL url3 = GURL(urls[2]);
 
   EXPECT_CALL(mock_favicon_service_,
               GetRawFaviconForPageURL(url1, _, _, 16, _, _))
@@ -142,10 +144,11 @@
 
 TEST_F(FaviconHelperTest, GetComposedFaviconImageOrderMatchesInput) {
   raw_bitmap_results_.clear();
-  GURL url1 = GURL("http://www.tab1.com");
-  GURL url2 = GURL("http://www.tab2.com");
-  GURL url3 = GURL("http://www.tab3.com");
-  std::vector<GURL> urls = {url1, url2, url3};
+  std::vector<std::string> urls = {"http://www.tab1.com", "http://www.tab2.com",
+                                   "http://www.tab3.com"};
+  GURL url1 = GURL(urls[0]);
+  GURL url2 = GURL(urls[1]);
+  GURL url3 = GURL(urls[2]);
 
   EXPECT_CALL(mock_favicon_service_,
               GetRawFaviconForPageURL(url1, _, _, 16, _, _))
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
index 031dd6ac..5faaceb3 100644
--- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc
+++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -24,7 +24,6 @@
 #include "base/task/post_task.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chrome/android/chrome_jni_headers/AutocompleteController_jni.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
@@ -37,6 +36,7 @@
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/android/omnibox/jni_headers/AutocompleteController_jni.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/browser_ui/util/android/url_constants.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
diff --git a/chrome/browser/android/omnibox/geolocation_header.cc b/chrome/browser/android/omnibox/geolocation_header.cc
index 896b0c5..1963e7a 100644
--- a/chrome/browser/android/omnibox/geolocation_header.cc
+++ b/chrome/browser/android/omnibox/geolocation_header.cc
@@ -6,9 +6,9 @@
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
-#include "chrome/android/chrome_jni_headers/GeolocationHeader_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/ui/android/omnibox/jni_headers/GeolocationHeader_jni.h"
 #include "url/android/gurl_android.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/android/omnibox/omnibox_prerender.cc b/chrome/browser/android/omnibox/omnibox_prerender.cc
index 5b88a40..b47978e 100644
--- a/chrome/browser/android/omnibox/omnibox_prerender.cc
+++ b/chrome/browser/android/omnibox/omnibox_prerender.cc
@@ -7,7 +7,6 @@
 #include "base/android/jni_string.h"
 #include "base/check.h"
 #include "base/notreached.h"
-#include "chrome/android/chrome_jni_headers/OmniboxPrerender_jni.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
@@ -15,6 +14,7 @@
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
+#include "chrome/browser/ui/android/omnibox/jni_headers/OmniboxPrerender_jni.h"
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_result.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc
index 9ece50f..0040fd7 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -1334,6 +1334,25 @@
     const std::map<SquareSizePx, SkBitmap>& icon_bitmaps,
     IconEffects icon_effects,
     int size_hint_in_dip) {
+  auto image_skia =
+      ConvertIconBitmapsToImageSkia(icon_bitmaps, size_hint_in_dip);
+
+  if (image_skia.isNull()) {
+    return gfx::ImageSkia{};
+  }
+
+  if ((icon_effects & IconEffects::kCrOsStandardMask) &&
+      (icon_effects & IconEffects::kCrOsStandardBackground)) {
+    image_skia = apps::ApplyBackgroundAndMask(image_skia);
+  }
+  return image_skia;
+}
+
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+gfx::ImageSkia ConvertIconBitmapsToImageSkia(
+    const std::map<SquareSizePx, SkBitmap>& icon_bitmaps,
+    int size_hint_in_dip) {
   if (icon_bitmaps.empty()) {
     return gfx::ImageSkia{};
   }
@@ -1376,15 +1395,10 @@
   }
 
   image_skia.EnsureRepsForSupportedScales();
-  if ((icon_effects & IconEffects::kCrOsStandardMask) &&
-      (icon_effects & IconEffects::kCrOsStandardBackground)) {
-    image_skia = apps::ApplyBackgroundAndMask(image_skia);
-  }
+
   return image_skia;
 }
 
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
 void ApplyIconEffects(IconEffects icon_effects,
                       int size_hint_in_dip,
                       apps::mojom::IconValuePtr iv,
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h
index 8e6c385..43b70b54 100644
--- a/chrome/browser/apps/app_service/app_icon_factory.h
+++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -119,6 +119,10 @@
     int size_hint_in_dip);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+gfx::ImageSkia ConvertIconBitmapsToImageSkia(
+    const std::map<SquareSizePx, SkBitmap>& icon_bitmaps,
+    int size_hint_in_dip);
+
 // Modifies |iv| to apply icon post-processing effects like badging and
 // desaturation to gray.
 void ApplyIconEffects(IconEffects icon_effects,
diff --git a/chrome/browser/apps/app_service/fake_lacros_web_apps_host.cc b/chrome/browser/apps/app_service/fake_lacros_web_apps_host.cc
index 1b7279f..6966499 100644
--- a/chrome/browser/apps/app_service/fake_lacros_web_apps_host.cc
+++ b/chrome/browser/apps/app_service/fake_lacros_web_apps_host.cc
@@ -102,4 +102,9 @@
   NOTIMPLEMENTED();
 }
 
+void FakeLacrosWebAppsHost::GetMenuModel(const std::string& app_id,
+                                         GetMenuModelCallback callback) {
+  NOTIMPLEMENTED();
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/fake_lacros_web_apps_host.h b/chrome/browser/apps/app_service/fake_lacros_web_apps_host.h
index 7b30c38..c38d863 100644
--- a/chrome/browser/apps/app_service/fake_lacros_web_apps_host.h
+++ b/chrome/browser/apps/app_service/fake_lacros_web_apps_host.h
@@ -35,6 +35,8 @@
                  bool report_abuse) override;
   void PauseApp(const std::string& app_id) override;
   void UnpauseApp(const std::string& app_id) override;
+  void GetMenuModel(const std::string& app_id,
+                    GetMenuModelCallback callback) override;
 
   mojo::Receiver<crosapi::mojom::AppController> receiver_{this};
 };
diff --git a/chrome/browser/apps/app_service/menu_item_constants.h b/chrome/browser/apps/app_service/menu_item_constants.h
new file mode 100644
index 0000000..7619ddbe
--- /dev/null
+++ b/chrome/browser/apps/app_service/menu_item_constants.h
@@ -0,0 +1,13 @@
+// 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 CHROME_BROWSER_APPS_APP_SERVICE_MENU_ITEM_CONSTANTS_H_
+#define CHROME_BROWSER_APPS_APP_SERVICE_MENU_ITEM_CONSTANTS_H_
+
+namespace apps {
+// A size of square shortcut menu item icons in the context menu.
+constexpr size_t kAppShortcutIconSizeDip = 32;
+}  // namespace apps
+
+#endif  // CHROME_BROWSER_APPS_APP_SERVICE_MENU_ITEM_CONSTANTS_H_
diff --git a/chrome/browser/apps/app_service/menu_util.h b/chrome/browser/apps/app_service/menu_util.h
index 43d9486..5456970 100644
--- a/chrome/browser/apps/app_service/menu_util.h
+++ b/chrome/browser/apps/app_service/menu_util.h
@@ -97,10 +97,6 @@
 // Returns the browser menu items for the given |menu_type|.
 mojom::MenuItemsPtr CreateBrowserMenuItems(mojom::MenuType menu_type,
                                            const Profile* profile);
-
-// A size of square shortcut menu item icons in the context menu.
-constexpr int kAppShortcutIconSizeDip = 32;
-
 }  // namespace apps
 
 #endif  // CHROME_BROWSER_APPS_APP_SERVICE_MENU_UTIL_H_
diff --git a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc
index 69cf4b13..1ec1bc2a 100644
--- a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc
+++ b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/services/app_service/public/cpp/instance_registry.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "extensions/common/constants.h"
 
@@ -43,7 +44,7 @@
 
 namespace apps {
 
-WebAppsCrosapi::WebAppsCrosapi(Profile* profile) {
+WebAppsCrosapi::WebAppsCrosapi(Profile* profile) : profile_(profile) {
   // This object may be created when the flag is on or off, but only register
   // the publisher if the flag is on.
   if (base::FeatureList::IsEnabled(features::kWebAppsCrosapi)) {
@@ -111,14 +112,95 @@
                                   apps::mojom::MenuType menu_type,
                                   int64_t display_id,
                                   GetMenuModelCallback callback) {
-  // TODO(crbug.com/1194709): Check if the app is installed.
+  bool is_system_web_app = false;
+  bool can_use_uninstall = true;
+  apps::mojom::WindowMode display_mode;
+  auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_);
 
-  // TODO(crbug.com/1194709): Add menu items, based on
-  // WebAppsChromeOs::GetMenuModel().
+  proxy->AppRegistryCache().ForOneApp(
+      app_id, [&is_system_web_app, &can_use_uninstall,
+               &display_mode](const apps::AppUpdate& update) {
+        if (update.InstallSource() == apps::mojom::InstallSource::kSystem) {
+          is_system_web_app = true;
+          can_use_uninstall = false;
+        } else if (update.InstallSource() ==
+                   apps::mojom::InstallSource::kPolicy) {
+          can_use_uninstall = false;
+        }
+        display_mode = update.WindowMode();
+      });
+
   apps::mojom::MenuItemsPtr menu_items = apps::mojom::MenuItems::New();
 
-  // TODO(crbug.com/1194709): Check if the user can uninstall the web app.
-  AddCommandItem(ash::UNINSTALL, IDS_APP_LIST_UNINSTALL_ITEM, &menu_items);
+  if (!is_system_web_app) {
+    apps::CreateOpenNewSubmenu(menu_type,
+                               display_mode == apps::mojom::WindowMode::kBrowser
+                                   ? IDS_APP_LIST_CONTEXT_MENU_NEW_TAB
+                                   : IDS_APP_LIST_CONTEXT_MENU_NEW_WINDOW,
+                               &menu_items);
+  }
+
+  if (menu_type == apps::mojom::MenuType::kShelf &&
+      !proxy->InstanceRegistry().GetWindows(app_id).empty()) {
+    apps::AddCommandItem(ash::MENU_CLOSE, IDS_SHELF_CONTEXT_MENU_CLOSE,
+                         &menu_items);
+  }
+
+  if (can_use_uninstall) {
+    apps::AddCommandItem(ash::UNINSTALL, IDS_APP_LIST_UNINSTALL_ITEM,
+                         &menu_items);
+  }
+
+  if (!is_system_web_app) {
+    apps::AddCommandItem(ash::SHOW_APP_INFO, IDS_APP_CONTEXT_MENU_SHOW_INFO,
+                         &menu_items);
+  }
+  if (base::FeatureList::IsEnabled(
+          features::kDesktopPWAsAppIconShortcutsMenuUI)) {
+    controller_->GetMenuModel(
+        app_id, base::BindOnce(&WebAppsCrosapi::OnGetMenuModelFromCrosapi,
+                               weak_factory_.GetWeakPtr(), app_id, menu_type,
+                               std::move(menu_items), std::move(callback)));
+  } else {
+    std::move(callback).Run(std::move(menu_items));
+  }
+}
+
+void WebAppsCrosapi::OnGetMenuModelFromCrosapi(
+    const std::string& app_id,
+    apps::mojom::MenuType menu_type,
+    apps::mojom::MenuItemsPtr menu_items,
+    GetMenuModelCallback callback,
+    crosapi::mojom::MenuItemsPtr crosapi_menu_items) {
+  if (crosapi_menu_items->items.empty()) {
+    std::move(callback).Run(std::move(menu_items));
+    return;
+  }
+
+  auto separator_type = ui::DOUBLE_SEPARATOR;
+
+  for (int item_index = 0; item_index < crosapi_menu_items->items.size();
+       item_index++) {
+    const auto& crosapi_menu_item = crosapi_menu_items->items[item_index];
+    apps::AddSeparator(std::exchange(separator_type, ui::PADDED_SEPARATOR),
+                       &menu_items);
+
+    // Uses integer |command_id| to store menu item index.
+    const int command_id = ash::LAUNCH_APP_SHORTCUT_FIRST + item_index;
+    // Passes menu_type argument as shortcut_id to use it in
+    // ExecuteContextMenuCommand().
+    std::string shortcut_id{apps::MenuTypeToString(menu_type)};
+
+    auto& icon_image = crosapi_menu_item->image;
+
+    if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
+      icon_image = apps::ApplyBackgroundAndMask(icon_image);
+    }
+
+    apps::AddShortcutCommandItem(command_id, shortcut_id,
+                                 crosapi_menu_item->label, icon_image,
+                                 &menu_items);
+  }
 
   std::move(callback).Run(std::move(menu_items));
 }
diff --git a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.h b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.h
index 560fdea..3bba1e7 100644
--- a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.h
+++ b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.h
@@ -78,9 +78,17 @@
   void OnCrosapiDisconnected();
   void OnControllerDisconnected();
 
+  void OnGetMenuModelFromCrosapi(
+      const std::string& app_id,
+      apps::mojom::MenuType menu_type,
+      apps::mojom::MenuItemsPtr menu_items,
+      GetMenuModelCallback callback,
+      crosapi::mojom::MenuItemsPtr crosapi_menu_items);
+
   mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
   mojo::Receiver<crosapi::mojom::AppPublisher> receiver_{this};
   mojo::Remote<crosapi::mojom::AppController> controller_;
+  Profile* const profile_;
   base::WeakPtrFactory<WebAppsCrosapi> weak_factory_{this};
 };
 
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
index 0defa70b..9e3b6ed 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_queue.cc
@@ -19,6 +19,7 @@
 
 namespace apps {
 
+// Queue of WebApks to be installed or updated.
 WebApkInstallQueue::WebApkInstallQueue(Profile* profile)
     : profile_(profile), connection_ready_(false) {
   arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
index 2ca40aa..64f8f42 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
@@ -96,10 +96,96 @@
   return GURL(server_url);
 }
 
+bool DoesShareTargetDiffer(webapk::WebAppManifest manifest,
+                           arc::mojom::WebShareTargetInfoPtr share_info) {
+  if (!share_info) {
+    // There's no |share_info| in the current WebAPK, which means that a share
+    // target was added.
+    return true;
+  }
+
+  // There is only one share target added.
+  auto share_target = manifest.share_targets(0);
+  DCHECK_EQ(manifest.share_targets_size(), 1);
+
+  if (share_target.action() != share_info->action ||
+      share_target.method() != share_info->method ||
+      share_target.enctype() != share_info->enctype) {
+    return true;
+  }
+
+  auto share_param = share_target.params();
+  if (share_param.title() != share_info->param_title ||
+      share_param.text() != share_info->param_text ||
+      share_param.url() != share_info->param_url) {
+    return true;
+  }
+
+  // Compare share files.
+  if (share_param.files_size() != share_info->file_names.size()) {
+    return true;
+  }
+
+  for (int i = 0; i < share_param.files_size(); i++) {
+    if (share_param.files(i).name() != share_info->file_names[i]) {
+      return true;
+    }
+
+    if (share_param.files(i).accept_size() !=
+        share_info->file_accepts[i].size()) {
+      return true;
+    }
+
+    for (int j = 0; j < share_param.files(i).accept_size(); j++) {
+      if (share_param.files(i).accept(j) != share_info->file_accepts[i][j]) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+void AddUpdateParams(webapk::WebApk* webapk,
+                     arc::mojom::WebApkInfoPtr web_apk_info) {
+  webapk->set_version(web_apk_info->apk_version);
+  // The |manifest_url| is used as a key on Android, so the |manifest_url| sent
+  // to the server to query a particular app should always be the same.
+  webapk->set_manifest_url(web_apk_info->manifest_url);
+
+  auto manifest = webapk->manifest();
+  if (manifest.short_name() != web_apk_info->name) {
+    webapk->add_update_reasons(webapk::WebApk::SHORT_NAME_DIFFERS);
+  }
+
+  if (manifest.start_url() != web_apk_info->start_url) {
+    webapk->add_update_reasons(webapk::WebApk::START_URL_DIFFERS);
+  }
+
+  // There is only one scope added to the scopes list.
+  DCHECK_EQ(manifest.scopes_size(), 1);
+  if (manifest.scopes(0) != web_apk_info->scope) {
+    webapk->add_update_reasons(webapk::WebApk::SCOPE_DIFFERS);
+  }
+
+  // There is only one icon added to the icon list.
+  DCHECK_EQ(manifest.icons_size(), 1);
+  if (manifest.icons(0).hash() != web_apk_info->icon_hash) {
+    webapk->add_update_reasons(webapk::WebApk::PRIMARY_ICON_HASH_DIFFERS);
+  }
+
+  // Check differences in share target
+  if (DoesShareTargetDiffer(manifest, std::move(web_apk_info->share_info))) {
+    webapk->add_update_reasons(webapk::WebApk::WEB_SHARE_TARGET_DIFFERS);
+  }
+}
+
 // Attaches icon PNG data and hash to an existing icon entry, and then
 // serializes and returns the entire proto. Should be called on a worker thread.
-std::string AddIconDataAndSerializeProto(std::unique_ptr<webapk::WebApk> webapk,
-                                         std::vector<uint8_t> icon_data) {
+absl::optional<std::string> AddIconDataAndSerializeProto(
+    std::unique_ptr<webapk::WebApk> webapk,
+    std::vector<uint8_t> icon_data,
+    arc::mojom::WebApkInfoPtr web_apk_info) {
   base::AssertLongCPUWorkAllowed();
   DCHECK_EQ(webapk->manifest().icons_size(), 1);
 
@@ -110,6 +196,15 @@
       MurmurHash64A(icon_data.data(), icon_data.size(), kMurmur2HashSeed);
   icon->set_hash(base::NumberToString(icon_hash));
 
+  if (web_apk_info) {
+    AddUpdateParams(webapk.get(), std::move(web_apk_info));
+    // If we don't have an update reason here, return before we query the server
+    // as there is no reason to update.
+    if (webapk->update_reasons_size() == 0) {
+      return absl::nullopt;
+    }
+  }
+
   std::string serialized_proto;
   webapk->SerializeToString(&serialized_proto);
 
@@ -131,6 +226,7 @@
 
 namespace apps {
 
+// Installs or updates a WebAPK.
 WebApkInstallTask::WebApkInstallTask(Profile* profile,
                                      const std::string& app_id)
     : profile_(profile),
@@ -158,7 +254,59 @@
   webapk->set_manifest_url(registrar.GetAppManifestUrl(app_id_).spec());
   webapk->set_requester_application_package(kRequesterPackageName);
   webapk->set_requester_application_version(version_info::GetVersionNumber());
-  webapk->add_update_reasons(webapk::WebApk::NONE);
+
+  LoadWebApkInfo(std::move(webapk), std::move(callback));
+}
+
+void WebApkInstallTask::LoadWebApkInfo(std::unique_ptr<webapk::WebApk> webapk,
+                                       ResultCallback callback) {
+  // If a package_name exists in webapk_prefs, this WebAPK is already installed,
+  // so we need to perform an update.
+  absl::optional<std::string> package_name =
+      webapk_prefs::GetWebApkPackageName(profile_, app_id_);
+
+  if (!package_name && !package_name.has_value()) {
+    // This is a new install, continue with the installation process.
+    webapk->add_update_reasons(webapk::WebApk::NONE);
+    arc::ArcFeaturesParser::GetArcFeatures(base::BindOnce(
+        &WebApkInstallTask::OnArcFeaturesLoaded, weak_ptr_factory_.GetWeakPtr(),
+        std::move(webapk), std::move(callback)));
+    return;
+  }
+
+  webapk->set_package_name(package_name.value());
+
+  // This is an update request, so get details of the existing WebAPK from
+  // ARC++.
+  auto* arc_service_manager = arc::ArcServiceManager::Get();
+  DCHECK(arc_service_manager);
+  auto* instance = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_service_manager->arc_bridge_service()->webapk(), GetWebApkInfo);
+
+  if (!instance) {
+    LOG(ERROR) << "WebApkInstance is not ready";
+    std::move(callback).Run(false);
+    return;
+  }
+
+  instance->GetWebApkInfo(
+      package_name.value(),
+      base::BindOnce(&WebApkInstallTask::OnWebApkInfoLoaded,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(webapk),
+                     std::move(callback)));
+}
+
+void WebApkInstallTask::OnWebApkInfoLoaded(
+    std::unique_ptr<webapk::WebApk> webapk,
+    ResultCallback callback,
+    arc::mojom::WebApkInfoPtr result) {
+  if (!result) {
+    LOG(ERROR) << "Could not load WebApkInfo";
+    std::move(callback).Run(false);
+    return;
+  }
+
+  web_apk_info_ = std::move(result);
 
   arc::ArcFeaturesParser::GetArcFeatures(base::BindOnce(
       &WebApkInstallTask::OnArcFeaturesLoaded, weak_ptr_factory_.GetWeakPtr(),
@@ -261,13 +409,17 @@
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE, {base::TaskPriority::BEST_EFFORT},
       base::BindOnce(AddIconDataAndSerializeProto, std::move(webapk),
-                     std::move(data)),
+                     std::move(data), std::move(web_apk_info_)),
       base::BindOnce(&WebApkInstallTask::OnProtoSerialized,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void WebApkInstallTask::OnProtoSerialized(ResultCallback callback,
-                                          std::string serialized_proto) {
+void WebApkInstallTask::OnProtoSerialized(
+    ResultCallback callback,
+    absl::optional<std::string> serialized_proto) {
+  if (!serialized_proto && !serialized_proto.has_value()) {
+    std::move(callback).Run(false);
+  }
   GURL server_url = GetServerUrl();
 
   // TODO(crbug.com/1198433): Add timeout.
@@ -282,7 +434,7 @@
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(request),
                                                  kWebApksTrafficAnnotation);
-  url_loader_->AttachStringForUpload(std::move(serialized_proto),
+  url_loader_->AttachStringForUpload(std::move(serialized_proto.value()),
                                      kProtoMimeType);
   url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
       url_loader_factory,
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task.h b/chrome/browser/apps/app_service/webapk/webapk_install_task.h
index 256b5d02..4452190 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task.h
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/web_applications/components/web_application_info.h"
 #include "components/arc/arc_features_parser.h"
-#include "components/arc/mojom/webapk.mojom-forward.h"
+#include "components/arc/mojom/webapk.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -47,6 +47,11 @@
   const std::string& app_id() { return app_id_; }
 
  private:
+  void LoadWebApkInfo(std::unique_ptr<webapk::WebApk> webapk,
+                      ResultCallback callback);
+  void OnWebApkInfoLoaded(std::unique_ptr<webapk::WebApk> webapk,
+                          ResultCallback callback,
+                          arc::mojom::WebApkInfoPtr result);
   void OnArcFeaturesLoaded(std::unique_ptr<webapk::WebApk> webapk,
                            ResultCallback callback,
                            absl::optional<arc::ArcFeatures> arc_features);
@@ -54,7 +59,8 @@
                     ResultCallback callback,
                     IconPurpose purpose,
                     std::vector<uint8_t> data);
-  void OnProtoSerialized(ResultCallback callback, std::string serialized_proto);
+  void OnProtoSerialized(ResultCallback callback,
+                         absl::optional<std::string> serialized_proto);
   void OnUrlLoaderComplete(ResultCallback callback,
                            std::unique_ptr<std::string> response_body);
   void OnInstallComplete(const std::string& package_name,
@@ -64,6 +70,7 @@
   Profile* const profile_;
   web_app::WebAppProviderBase* web_app_provider_;
 
+  arc::mojom::WebApkInfoPtr web_apk_info_;
   const std::string app_id_;
   std::unique_ptr<network::SimpleURLLoader> url_loader_;
 
diff --git a/chrome/browser/apps/app_service/webapk/webapk_manager.cc b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
index 2c87b04..363891b 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_manager.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_manager.cc
@@ -45,27 +45,31 @@
 WebApkManager::~WebApkManager() = default;
 
 void WebApkManager::OnAppUpdate(const AppUpdate& update) {
-  // TODO(crbug.com/119433): Install WebAPKs for existing apps which become
-  // eligible, and update existing WebAPKs when app metadata changes.
   if (!initialized_) {
     return;
   }
 
-  // Install new WebAPKs when an eligible app is installed. Note that it
-  // generally shouldn't be possible to have an existing WebAPK installed when
-  // the app is newly Ready, but we include the check for completeness' sake.
-  if (update.ReadinessChanged() &&
-      update.Readiness() == apps::mojom::Readiness::kReady &&
-      IsAppEligibleForWebApk(update) &&
-      !webapk_prefs::GetWebApkPackageName(profile_, update.AppId())) {
-    QueueInstall(update.AppId());
-  }
-
-  // Uninstall WebAPKs when the app becomes no longer eligible (which includes
-  // when the app is uninstalled).
-  if (webapk_prefs::GetWebApkPackageName(profile_, update.AppId()) &&
-      !IsAppEligibleForWebApk(update)) {
-    QueueUninstall(update.AppId());
+  if (IsAppEligibleForWebApk(update)) {
+    if (webapk_prefs::GetWebApkPackageName(profile_, update.AppId())) {
+      // Existing WebAPK.
+      // Update if there are app metadata changes.
+      if (update.ShortNameChanged() || update.NameChanged() ||
+          update.IconKeyChanged() || update.IntentFiltersChanged()) {
+        QueueInstall(update.AppId());
+      }
+    } else {  // New WebAPK.
+      // Install if it is eligible for installation.
+      if (update.ReadinessChanged() &&
+          update.Readiness() == apps::mojom::Readiness::kReady) {
+        QueueInstall(update.AppId());
+      }
+    }
+  } else {  // !IsAppEligibleForWebApk(update)
+    // Uninstall WebAPKs when the app becomes no longer eligible (which includes
+    // when the app is uninstalled).
+    if (webapk_prefs::GetWebApkPackageName(profile_, update.AppId())) {
+      QueueUninstall(update.AppId());
+    }
   }
 }
 
@@ -163,6 +167,8 @@
   return true;
 }
 
+// Queues |app_id| for install or update. |install_queue_| installs new WebAPKs
+// and updates existing ones.
 void WebApkManager::QueueInstall(const std::string& app_id) {
   install_queue_->Install(app_id);
 }
diff --git a/chrome/browser/ash/accessibility/accessibility_manager.cc b/chrome/browser/ash/accessibility/accessibility_manager.cc
index 6e8499e..7dfcc889 100644
--- a/chrome/browser/ash/accessibility/accessibility_manager.cc
+++ b/chrome/browser/ash/accessibility/accessibility_manager.cc
@@ -37,7 +37,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
-#include "chrome/browser/accessibility/accessibility_extension_api.h"
+#include "chrome/browser/accessibility/accessibility_extension_api_chromeos.h"
 #include "chrome/browser/ash/accessibility/accessibility_extension_loader.h"
 #include "chrome/browser/ash/accessibility/dictation.h"
 #include "chrome/browser/ash/accessibility/magnification_manager.h"
diff --git a/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc b/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
index ca8f984..0b877fd 100644
--- a/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
+++ b/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include <string>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/shell.h"
 #include "base/command_line.h"
 #include "base/macros.h"
@@ -42,8 +42,8 @@
   return Shell::GetPrimaryRootWindow();
 }
 
-FullScreenMagnifierController* GetFullScreenMagnifierController() {
-  return Shell::Get()->full_screen_magnifier_controller();
+FullscreenMagnifierController* GetFullscreenMagnifierController() {
+  return Shell::Get()->fullscreen_magnifier_controller();
 }
 
 bool IsMagnifierEnabled() {
@@ -55,16 +55,16 @@
 }
 
 void MoveMagnifierWindow(int x, int y) {
-  GetFullScreenMagnifierController()->MoveWindow(x, y, false);
+  GetFullscreenMagnifierController()->MoveWindow(x, y, false);
 }
 
 gfx::Rect GetViewPort() {
-  return GetFullScreenMagnifierController()->GetViewportRect();
+  return GetFullscreenMagnifierController()->GetViewportRect();
 }
 
 class MagnifierAnimationWaiter {
  public:
-  explicit MagnifierAnimationWaiter(FullScreenMagnifierController* controller)
+  explicit MagnifierAnimationWaiter(FullscreenMagnifierController* controller)
       : controller_(controller) {}
 
   void Wait() {
@@ -83,17 +83,17 @@
     }
   }
 
-  FullScreenMagnifierController* controller_;  // not owned
+  FullscreenMagnifierController* controller_;  // not owned
   scoped_refptr<content::MessageLoopRunner> runner_;
   DISALLOW_COPY_AND_ASSIGN(MagnifierAnimationWaiter);
 };
 
 }  // namespace
 
-class FullScreenMagnifierControllerTest : public InProcessBrowserTest {
+class FullscreenMagnifierControllerTest : public InProcessBrowserTest {
  protected:
-  FullScreenMagnifierControllerTest() {}
-  ~FullScreenMagnifierControllerTest() override {}
+  FullscreenMagnifierControllerTest() {}
+  ~FullscreenMagnifierControllerTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     // Make screens sufficiently wide to host 2 browsers side by side.
@@ -105,13 +105,13 @@
 
     // Confirms that magnifier is enabled.
     EXPECT_TRUE(IsMagnifierEnabled());
-    EXPECT_EQ(2.0f, GetFullScreenMagnifierController()->GetScale());
+    EXPECT_EQ(2.0f, GetFullscreenMagnifierController()->GetScale());
 
-    // FullScreenMagnifierController moves the magnifier window with animation
+    // FullscreenMagnifierController moves the magnifier window with animation
     // when the magnifier is set to be enabled. It will move the mouse cursor
     // when the animation completes. Wait until the animation completes, so that
     // the mouse movement won't affect the position of magnifier window later.
-    MagnifierAnimationWaiter waiter(GetFullScreenMagnifierController());
+    MagnifierAnimationWaiter waiter(GetFullscreenMagnifierController());
     waiter.Wait();
     base::RunLoop().RunUntilIdle();
   }
@@ -157,7 +157,7 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(FullScreenMagnifierControllerTest);
+  DISALLOW_COPY_AND_ASSIGN(FullscreenMagnifierControllerTest);
 };
 
 // Test is flaky on ChromeOS: crbug.com/1150753
@@ -167,7 +167,7 @@
 #else
 #define MAYBE_FollowFocusOnWebButtonContained FollowFocusOnWebButtonContained
 #endif
-IN_PROC_BROWSER_TEST_F(FullScreenMagnifierControllerTest,
+IN_PROC_BROWSER_TEST_F(FullscreenMagnifierControllerTest,
                        MAYBE_FollowFocusOnWebButtonContained) {
   DCHECK(IsMagnifierEnabled());
   ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/ash/accessibility/magnification_manager.cc b/chrome/browser/ash/accessibility/magnification_manager.cc
index af1c7f4..aca1890e 100644
--- a/chrome/browser/ash/accessibility/magnification_manager.cc
+++ b/chrome/browser/ash/accessibility/magnification_manager.cc
@@ -7,9 +7,9 @@
 #include <limits>
 #include <memory>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/public/cpp/ash_pref_names.h"
-#include "ash/public/cpp/docked_magnifier_controller.h"
 #include "ash/shell.h"
 #include "base/bind.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
@@ -105,12 +105,12 @@
     const gfx::Rect& rect) {
   // Fullscreen magnifier and docked magnifier are mutually exclusive.
   if (fullscreen_magnifier_enabled_) {
-    Shell::Get()->full_screen_magnifier_controller()->HandleMoveMagnifierToRect(
+    Shell::Get()->fullscreen_magnifier_controller()->HandleMoveMagnifierToRect(
         rect);
     return;
   }
   if (IsDockedMagnifierEnabled()) {
-    DockedMagnifierController::Get()->MoveMagnifierToRect(rect);
+    Shell::Get()->docked_magnifier_controller()->MoveMagnifierToRect(rect);
   }
 }
 
@@ -231,7 +231,7 @@
 
   fullscreen_magnifier_enabled_ = enabled;
 
-  Shell::Get()->full_screen_magnifier_controller()->SetEnabled(enabled);
+  Shell::Get()->fullscreen_magnifier_controller()->SetEnabled(enabled);
 }
 
 void MagnificationManager::SetMagnifierKeepFocusCenteredInternal(
@@ -241,7 +241,7 @@
 
   keep_focus_centered_ = keep_focus_centered;
 
-  Shell::Get()->full_screen_magnifier_controller()->SetKeepFocusCentered(
+  Shell::Get()->fullscreen_magnifier_controller()->SetKeepFocusCentered(
       keep_focus_centered_);
 }
 
@@ -251,13 +251,13 @@
 
   scale_ = scale;
 
-  Shell::Get()->full_screen_magnifier_controller()->SetScale(
+  Shell::Get()->fullscreen_magnifier_controller()->SetScale(
       scale_, false /* animate */);
 }
 
 void MagnificationManager::SetMagnifierMouseFollowingModeInternal(
     MagnifierMouseFollowingMode mouse_following_mode) {
-  Shell::Get()->full_screen_magnifier_controller()->set_mouse_following_mode(
+  Shell::Get()->fullscreen_magnifier_controller()->set_mouse_following_mode(
       mouse_following_mode);
 }
 
diff --git a/chrome/browser/ash/accessibility/magnification_manager_browsertest.cc b/chrome/browser/ash/accessibility/magnification_manager_browsertest.cc
index 68ed41d97..feb5838 100644
--- a/chrome/browser/ash/accessibility/magnification_manager_browsertest.cc
+++ b/chrome/browser/ash/accessibility/magnification_manager_browsertest.cc
@@ -4,7 +4,7 @@
 
 #include <string>
 
-#include "ash/accessibility/magnifier/full_screen_magnifier_controller.h"
+#include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/shell.h"
@@ -41,11 +41,11 @@
 }
 
 void SetFullScreenMagnifierScale(double scale) {
-  Shell::Get()->full_screen_magnifier_controller()->SetScale(scale, false);
+  Shell::Get()->fullscreen_magnifier_controller()->SetScale(scale, false);
 }
 
 double GetFullScreenMagnifierScale() {
-  return Shell::Get()->full_screen_magnifier_controller()->GetScale();
+  return Shell::Get()->fullscreen_magnifier_controller()->GetScale();
 }
 
 void SetSavedFullScreenMagnifierScale(double scale) {
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
index 36702901..7e6c41a 100644
--- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
+++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -628,9 +628,7 @@
     return arc::mojom::AccessibilityFilterType::ALL;
   }
 
-  if (magnification_manager->IsMagnifierEnabled() ||
-      magnification_manager->IsDockedMagnifierEnabled() ||
-      accessibility_manager->IsFocusHighlightEnabled()) {
+  if (accessibility_manager->IsFocusHighlightEnabled()) {
     return arc::mojom::AccessibilityFilterType::FOCUS;
   }
 
@@ -735,10 +733,7 @@
 
   const AccessibilityManager* accessibility_manager =
       AccessibilityManager::Get();
-  const MagnificationManager* magnification_manager =
-      MagnificationManager::Get();
-
-  if (!accessibility_manager || !magnification_manager)
+  if (!accessibility_manager)
     return;
 
   is_focus_event_enabled_ = accessibility_manager->IsFocusHighlightEnabled();
diff --git a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
index 82e3f51f..8e6decc 100644
--- a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
+++ b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
+#include "chrome/browser/apps/app_service/menu_item_constants.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
 #include "chrome/browser/ash/arc/icon_decode_request.h"
 #include "chrome/common/chrome_features.h"
diff --git a/chrome/browser/ash/camera_mic/vm_camera_mic_manager.cc b/chrome/browser/ash/camera_mic/vm_camera_mic_manager.cc
index 056310a3..7a7a19f 100644
--- a/chrome/browser/ash/camera_mic/vm_camera_mic_manager.cc
+++ b/chrome/browser/ash/camera_mic/vm_camera_mic_manager.cc
@@ -233,10 +233,6 @@
 
   void OpenNotification(NotificationType type) const {
     DCHECK_NE(type, kNoNotification);
-    if (!base::FeatureList::IsEnabled(
-            features::kVmCameraMicIndicatorsAndNotifications)) {
-      return;
-    }
 
     const gfx::VectorIcon* source_icon = nullptr;
     int message_id;
@@ -286,10 +282,7 @@
 
   void CloseNotification(NotificationType type) const {
     DCHECK_NE(type, kNoNotification);
-    if (!base::FeatureList::IsEnabled(
-            features::kVmCameraMicIndicatorsAndNotifications)) {
-      return;
-    }
+
     NotificationDisplayService::GetForProfile(profile_)->Close(
         NotificationHandler::Type::TRANSIENT,
         GetNotificationId(vm_type_, type));
diff --git a/chrome/browser/ash/camera_mic/vm_camera_mic_manager_unittest.cc b/chrome/browser/ash/camera_mic/vm_camera_mic_manager_unittest.cc
index 7ac1d369..2eef6f1 100644
--- a/chrome/browser/ash/camera_mic/vm_camera_mic_manager_unittest.cc
+++ b/chrome/browser/ash/camera_mic/vm_camera_mic_manager_unittest.cc
@@ -8,11 +8,9 @@
 #include <memory>
 #include <utility>
 
-#include "ash/constants/ash_features.h"
 #include "ash/public/cpp/vm_camera_mic_constants.h"
 #include "base/bind.h"
 #include "base/containers/flat_map.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/notifications/notification_display_service.h"
@@ -127,8 +125,6 @@
         testing_profile_.GetProfileUserName(), "id"));
     scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
         std::move(mock_user_manager));
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kVmCameraMicIndicatorsAndNotifications);
 
     // Inject a fake notification display service.
     fake_display_service_ = static_cast<FakeNotificationDisplayService*>(
@@ -189,7 +185,6 @@
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   TestingProfile testing_profile_;
   std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
-  base::test::ScopedFeatureList scoped_feature_list_;
 
   FakeNotificationDisplayService* fake_display_service_;
   std::unique_ptr<VmCameraMicManager> vm_camera_mic_manager_;
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index 13e9779..ae52d99 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -53,6 +53,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/anomaly_detector_client.h"
+#include "chromeos/dbus/cicerone/cicerone_service.pb.h"
 #include "chromeos/dbus/concierge/concierge_client.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -2843,16 +2844,51 @@
     return;
   }
 
-  if (response->status() !=
-          vm_tools::cicerone::SetUpLxdContainerUserResponse::SUCCESS &&
-      response->status() !=
-          vm_tools::cicerone::SetUpLxdContainerUserResponse::EXISTS) {
-    LOG(ERROR) << "Failed to set up container user: "
-               << response->failure_reason();
-    std::move(callback).Run(/*success=*/false);
-    return;
+  switch (response->status()) {
+    case vm_tools::cicerone::SetUpLxdContainerUserResponse::UNKNOWN:
+      // If we hit this then we don't know if users are set up or not; a
+      // possible cause is we weren't able to read the /etc/passwd file.
+      // We're in one of the following cases:
+      // - Users are already set up but hit a transient error reading the file
+      //   e.g. crbug/1216305. This would be a no-op so safe to continue.
+      // - The container is in a bad state e.g. file is missing entirely.
+      //   Once we start the container (next step) the system will try to repair
+      //   this. It won't recover enough for restart to succeed, but it will
+      //   give us a valid passwd file so that next launch we'll set up users
+      //   and all will be good again. If we errored out here then we'd never
+      //   repair the file and the container is borked for good.
+      // - Lastly and least likely, it could be a transient issue but users
+      //   aren't set up correctly. The container will either fail to start,
+      //   or start but won't completely work (e.g. maybe adb sideloading will
+      //   fail). Either way, restarting the container should get them back into
+      //   a good state.
+      // Note that if the user's account is missing then garcon won't start,
+      // which combined with crbug/1197416 means launch will hang forever (well,
+      // it's a 5 day timeout so not forever but may as well be). They would
+      // have to be incredibly unlucky and restarting will fix things so that's
+      // acceptable.
+      base::UmaHistogramBoolean("Crostini.SetUpLxdContainerUser.UnknownResult",
+                                true);
+      LOG(ERROR) << "Failed to set up container user: "
+                 << response->failure_reason();
+      std::move(callback).Run(/*success=*/true);
+      break;
+    case vm_tools::cicerone::SetUpLxdContainerUserResponse::SUCCESS:
+    case vm_tools::cicerone::SetUpLxdContainerUserResponse::EXISTS:
+      base::UmaHistogramBoolean("Crostini.SetUpLxdContainerUser.UnknownResult",
+                                false);
+      std::move(callback).Run(/*success=*/true);
+      break;
+    case vm_tools::cicerone::SetUpLxdContainerUserResponse::FAILED:
+      LOG(ERROR) << "Failed to set up container user: "
+                 << response->failure_reason();
+      base::UmaHistogramBoolean("Crostini.SetUpLxdContainerUser.UnknownResult",
+                                false);
+      std::move(callback).Run(/*success=*/false);
+      break;
+    default:
+      NOTREACHED();
   }
-  std::move(callback).Run(/*success=*/true);
 }
 
 void CrostiniManager::OnLxdContainerCreated(
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
index 5df85dc..d7e1df7 100644
--- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -808,6 +808,8 @@
   ExpectRestarterUmaCount(1);
   histogram_tester_.ExpectTotalCount(
       "Crostini.RestarterTimeInState.StartTerminaVm", 1);
+  histogram_tester_.ExpectBucketCount(
+      "Crostini.SetUpLxdContainerUser.UnknownResult", false, 1);
 }
 
 TEST_F(CrostiniManagerRestartTest, UncleanRestartReportsMetricToUncleanBucket) {
diff --git a/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc b/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc
index 3a4f1323..427b8f4 100644
--- a/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc
+++ b/chrome/browser/ash/dbus/vm/vm_permission_service_provider.cc
@@ -333,16 +333,12 @@
   }
 
   const PrefService* prefs = profile->GetPrefs();
-  if (base::FeatureList::IsEnabled(
-          chromeos::features::kPluginVmShowCameraPermissions) &&
-      prefs->GetBoolean(prefs::kVideoCaptureAllowed)) {
+  if (prefs->GetBoolean(prefs::kVideoCaptureAllowed)) {
     vm->permission_to_enabled_map[VmInfo::PermissionCamera] =
         prefs->GetBoolean(plugin_vm::prefs::kPluginVmCameraAllowed);
   }
 
-  if (base::FeatureList::IsEnabled(
-          chromeos::features::kPluginVmShowMicrophonePermissions) &&
-      prefs->GetBoolean(prefs::kAudioCaptureAllowed)) {
+  if (prefs->GetBoolean(prefs::kAudioCaptureAllowed)) {
     vm->permission_to_enabled_map[VmInfo::PermissionMicrophone] =
         prefs->GetBoolean(plugin_vm::prefs::kPluginVmMicAllowed);
   }
diff --git a/chrome/browser/ash/login/accessibility_browsertest.cc b/chrome/browser/ash/login/accessibility_browsertest.cc
index 19c9d2e4..b3149e7 100644
--- a/chrome/browser/ash/login/accessibility_browsertest.cc
+++ b/chrome/browser/ash/login/accessibility_browsertest.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/public/cpp/docked_magnifier_controller.h"
+#include "ash/accessibility/magnifier/docked_magnifier_controller.h"
 #include "ash/public/cpp/keyboard/keyboard_controller.h"
+#include "ash/shell.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/accessibility/magnification_manager.h"
 #include "chrome/browser/ash/login/test/oobe_base_test.h"
@@ -52,7 +53,7 @@
   }
 
   int GetMagnifierHeight() {
-    return ash::DockedMagnifierController::Get()
+    return ash::Shell::Get()->docked_magnifier_controller()
         ->GetMagnifierHeightForTesting();
   }
 
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc
index 397eaf1a..97cdcae1 100644
--- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc
+++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc
@@ -137,14 +137,6 @@
   request.set_owner_id(owner_id_);
   request.set_vm_name_uuid(kPluginVmName);
 
-  // We need to reset these permissions unless we have permission
-  // indicators/notifications enabled.
-  if (!base::FeatureList::IsEnabled(
-          chromeos::features::kVmCameraMicIndicatorsAndNotifications)) {
-    profile_->GetPrefs()->SetBoolean(prefs::kPluginVmCameraAllowed, false);
-    profile_->GetPrefs()->SetBoolean(prefs::kPluginVmMicAllowed, false);
-  }
-
   // Probe the dispatcher.
   chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->ListVms(
       std::move(request),
diff --git a/chrome/browser/ash/web_applications/camera_system_web_app_info.cc b/chrome/browser/ash/web_applications/camera_system_web_app_info.cc
index 0da4a93..f4416b8 100644
--- a/chrome/browser/ash/web_applications/camera_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/camera_system_web_app_info.cc
@@ -55,10 +55,13 @@
 }
 
 CameraSystemAppDelegate::CameraSystemAppDelegate(Profile* profile)
-    : web_app::SystemWebAppDelegate(web_app::SystemAppType::CAMERA,
-                                    "Camera",
-                                    GURL("chrome://camera-app/views/main.html"),
-                                    profile) {}
+    : web_app::SystemWebAppDelegate(
+          web_app::SystemAppType::CAMERA,
+          "Camera",
+          GURL("chrome://camera-app/views/main.html"),
+          profile,
+          web_app::OriginTrialsMap({{web_app::GetOrigin("chrome://camera-app"),
+                                     {"FileHandling", "IdleDetection"}}})) {}
 
 std::unique_ptr<WebApplicationInfo> CameraSystemAppDelegate::GetWebAppInfo()
     const {
@@ -78,12 +81,6 @@
   return true;
 }
 
-web_app::OriginTrialsMap CameraSystemAppDelegate::GetEnabledOriginTrials()
-    const {
-  return web_app::OriginTrialsMap({{web_app::GetOrigin("chrome://camera-app"),
-                                    {"FileHandling", "IdleDetection"}}});
-}
-
 gfx::Size CameraSystemAppDelegate::GetMinimumWindowSize() const {
   return {kChromeCameraAppMinimumWidth, kChromeCameraAppMinimumHeight + 32};
 }
diff --git a/chrome/browser/ash/web_applications/camera_system_web_app_info.h b/chrome/browser/ash/web_applications/camera_system_web_app_info.h
index 2ab203ea..6a29d73 100644
--- a/chrome/browser/ash/web_applications/camera_system_web_app_info.h
+++ b/chrome/browser/ash/web_applications/camera_system_web_app_info.h
@@ -21,7 +21,6 @@
   // web_app::SystemWebAppDelegate overrides
   std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
   std::vector<web_app::AppId> GetAppIdsToUninstallAndReplace() const override;
-  web_app::OriginTrialsMap GetEnabledOriginTrials() const override;
   bool ShouldCaptureNavigations() const override;
   gfx::Size GetMinimumWindowSize() const override;
   gfx::Rect GetDefaultBounds(Browser* browser) const override;
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 adb1db0..23f13e5 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
@@ -77,10 +77,14 @@
 }  // namespace
 
 MediaSystemAppDelegate::MediaSystemAppDelegate(Profile* profile)
-    : web_app::SystemWebAppDelegate(web_app::SystemAppType::MEDIA,
-                                    "Media",
-                                    GURL("chrome://media-app/pwa.html"),
-                                    profile) {}
+    : web_app::SystemWebAppDelegate(
+          web_app::SystemAppType::MEDIA,
+          "Media",
+          GURL("chrome://media-app/pwa.html"),
+          profile,
+          web_app::OriginTrialsMap(
+              {{web_app::GetOrigin("chrome://media-app"), {"FileHandling"}}})) {
+}
 
 std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForMediaWebApp() {
   std::unique_ptr<WebApplicationInfo> info =
@@ -131,9 +135,3 @@
 bool MediaSystemAppDelegate::ShouldShowInSearch() const {
   return false;
 }
-
-web_app::OriginTrialsMap MediaSystemAppDelegate::GetEnabledOriginTrials()
-    const {
-  return web_app::OriginTrialsMap(
-      {{web_app::GetOrigin("chrome://media-app"), {"FileHandling"}}});
-}
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 5dc4d95..cbcebe78 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
@@ -19,7 +19,6 @@
   bool ShouldIncludeLaunchDirectory() const override;
   bool ShouldShowInLauncher() const override;
   bool ShouldShowInSearch() const override;
-  web_app::OriginTrialsMap GetEnabledOriginTrials() const override;
 };
 
 // Return a WebApplicationInfo used to install the app.
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 d151c59..a4d72fe 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
@@ -40,21 +40,18 @@
           web_app::SystemAppType::SAMPLE,
           "Sample",
           GURL("chrome://sample-system-web-app/pwa.html"),
-          profile) {}
+          profile,
+          web_app::OriginTrialsMap(
+              {{web_app::GetOrigin("chrome://sample-system-web-app"),
+                {"Frobulate"}},
+               {web_app::GetOrigin("chrome-untrusted://sample-system-web-app"),
+                {"Frobulate"}}})) {}
 
 std::unique_ptr<WebApplicationInfo> SampleSystemAppDelegate::GetWebAppInfo()
     const {
   return CreateWebAppInfoForSampleSystemWebApp();
 }
 
-web_app::OriginTrialsMap SampleSystemAppDelegate::GetEnabledOriginTrials()
-    const {
-  return web_app::OriginTrialsMap(
-      {{web_app::GetOrigin("chrome://sample-system-web-app"), {"Frobulate"}},
-       {web_app::GetOrigin("chrome-untrusted://sample-system-web-app"),
-        {"Frobulate"}}});
-}
-
 bool SampleSystemAppDelegate::ShouldCaptureNavigations() const {
   return true;
 }
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 6e2e54d..c5ebf46 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
@@ -21,7 +21,6 @@
 
   // web_app::SystemWebAppDelegate overrides:
   std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
-  web_app::OriginTrialsMap GetEnabledOriginTrials() const override;
   bool ShouldCaptureNavigations() const override;
   absl::optional<web_app::SystemAppBackgroundTaskInfo> GetTimerInfo()
       const override;
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index aa20c56..90c0492 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -62,10 +62,10 @@
 #endif
 
 #if defined(OS_ANDROID)
-#include "chrome/android/chrome_jni_headers/ChromeAutocompleteProviderClient_jni.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/android/tab_android_user_data.h"
 #include "chrome/browser/flags/android/chrome_session_state.h"
+#include "chrome/browser/ui/android/omnibox/jni_headers/ChromeAutocompleteProviderClient_jni.h"
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_jni_bridge.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc
index dfe41d8c..9be6f55 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.cc
@@ -6,9 +6,6 @@
 
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
-#if defined(OS_ANDROID)
-#include "chrome/android/chrome_jni_headers/ChromeAutocompleteSchemeClassifier_jni.h"
-#endif
 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
@@ -16,6 +13,9 @@
 #include "chrome/browser/profiles/profile_android.h"
 #endif
 #include "chrome/browser/profiles/profile_io_data.h"
+#if defined(OS_ANDROID)
+#include "chrome/browser/ui/android/omnibox/jni_headers/ChromeAutocompleteSchemeClassifier_jni.h"
+#endif
 #include "content/public/common/url_constants.h"
 #include "url/url_util.h"
 
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 7a1e638..76df200 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -92,36 +92,43 @@
 
 namespace {
 
-static const char kTestShippingFormString[] =
-    "An example of a shipping address form."
-    "<form action=\"https://www.example.com/\" method=\"POST\">"
-    "<label for=\"firstname\">First name:</label>"
-    " <input type=\"text\" id=\"firstname\"><br>"
-    "<label for=\"lastname\">Last name:</label>"
-    " <input type=\"text\" id=\"lastname\"><br>"
-    "<label for=\"address1\">Address line 1:</label>"
-    " <input type=\"text\" id=\"address1\"><br>"
-    "<label for=\"address2\">Address line 2:</label>"
-    " <input type=\"text\" id=\"address2\"><br>"
-    "<label for=\"city\">City:</label>"
-    " <input type=\"text\" id=\"city\"><br>"
-    "<label for=\"state\">State:</label>"
-    " <select id=\"state\">"
-    " <option value=\"\" selected=\"yes\">--</option>"
-    " <option value=\"CA\">California</option>"
-    " <option value=\"TX\">Texas</option>"
-    " </select><br>"
-    "<label for=\"zip\">ZIP code:</label>"
-    " <input type=\"text\" id=\"zip\"><br>"
-    "<label for=\"country\">Country:</label>"
-    " <select id=\"country\">"
-    " <option value=\"\" selected=\"yes\">--</option>"
-    " <option value=\"CA\">Canada</option>"
-    " <option value=\"US\">United States</option>"
-    " </select><br>"
-    "<label for=\"phone\">Phone number:</label>"
-    " <input type=\"text\" id=\"phone\"><br>"
-    "</form>";
+static const char kTestShippingFormString[] = R"(
+  <html>
+  <head>
+    <!-- Disable extra network request for /favicon.ico -->
+    <link rel="icon" href="data:,">
+  </head>
+  <body>
+    An example of a shipping address form.
+    <form action="https://www.example.com/" method="POST">
+    <label for="firstname">First name:</label>
+     <input type="text" id="firstname"><br>
+    <label for="lastname">Last name:</label>
+     <input type="text" id="lastname"><br>
+    <label for="address1">Address line 1:</label>
+     <input type="text" id="address1"><br>
+    <label for="address2">Address line 2:</label>
+     <input type="text" id="address2"><br>
+    <label for="city">City:</label>
+     <input type="text" id="city"><br>
+    <label for="state">State:</label>
+     <select id="state">
+     <option value="" selected="yes">--</option>
+     <option value="CA">California</option>
+     <option value="TX">Texas</option>
+     </select><br>
+    <label for="zip">ZIP code:</label>
+     <input type="text" id="zip"><br>
+    <label for="country">Country:</label>
+     <select id="country">
+     <option value="" selected="yes">--</option>
+     <option value="CA">Canada</option>
+     <option value="US">United States</option>
+     </select><br>
+    <label for="phone">Phone number:</label>
+     <input type="text" id="phone"><br>
+    </form>
+    )";
 
 static const char kTestBillingFormString[] =
     "An example of a billing address form."
@@ -496,9 +503,9 @@
         "        },"
         "        translatePage : function(sourceLang, targetLang,"
         "                                 onTranslateProgress) {"
-        "          document.getElementsByTagName(\"body\")[0].innerHTML = '" +
+        "          document.getElementsByTagName(\"body\")[0].innerHTML = `" +
         std::string(kTestShippingFormString) +
-        "              ';"
+        "              `;"
         "          onTranslateProgress(100, true, false);"
         "        }"
         "      };"
@@ -827,6 +834,12 @@
     AutofillInteractiveTest::TearDownOnMainThread();
   }
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    AutofillInteractiveTest::SetUpCommandLine(command_line);
+    // Prevents proxy.pac requests.
+    command_line->AppendSwitch(switches::kNoProxyServer);
+  }
+
   base::HistogramTester& histogram_tester() { return histogram_tester_; }
 
  private:
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 9844c95..83f3797a 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5746,12 +5746,12 @@
 #if !defined(OS_ANDROID)
 base::OnceClosure ChromeContentBrowserClient::FetchRemoteSms(
     content::WebContents* web_contents,
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                             absl::optional<std::string>,
                             absl::optional<content::SmsFetchFailureType>)>
         callback) {
-  return ::FetchRemoteSms(web_contents, origin, std::move(callback));
+  return ::FetchRemoteSms(web_contents, origin_list, std::move(callback));
 }
 #endif
 
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index c5b0f7c..567af73 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -672,7 +672,7 @@
 #if !defined(OS_ANDROID)
   base::OnceClosure FetchRemoteSms(
       content::WebContents* web_contents,
-      const url::Origin& origin,
+      const std::vector<url::Origin>& origin_list,
       base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                               absl::optional<std::string>,
                               absl::optional<content::SmsFetchFailureType>)>
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc
index 0278cd4..086e4e6 100644
--- a/chrome/browser/chrome_service_worker_browsertest.cc
+++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -39,6 +39,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/page.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/storage_partition.h"
@@ -515,8 +516,13 @@
 
   std::string GetManifestAndIssuedRequests() {
     base::RunLoop run_loop;
-    browser()->tab_strip_model()->GetActiveWebContents()->GetManifest(
-        base::BindOnce(&ManifestCallbackAndRun, run_loop.QuitClosure()));
+    browser()
+        ->tab_strip_model()
+        ->GetActiveWebContents()
+        ->GetMainFrame()
+        ->GetPage()
+        .GetManifest(
+            base::BindOnce(&ManifestCallbackAndRun, run_loop.QuitClosure()));
     run_loop.Run();
     return ExecuteScriptAndExtractString(
         "if (issuedRequests.length != 0) reportRequests();"
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index ba03ea49..48ca100 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -1863,9 +1863,9 @@
   for (const auto& type_and_info :
        provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) {
     api::autotest_private::SystemApp system_app;
-    web_app::SystemAppInfo info = type_and_info.second;
-    system_app.internal_name = info.internal_name;
-    system_app.url = info.install_url.GetOrigin().spec();
+    web_app::SystemWebAppDelegate* delegate = type_and_info.second.get();
+    system_app.internal_name = delegate->GetInternalName();
+    system_app.url = delegate->GetInstallUrl().GetOrigin().spec();
     result.push_back(std::move(system_app));
   }
 
@@ -1976,7 +1976,7 @@
   absl::optional<web_app::SystemAppType> app_type;
   for (const auto& type_and_info :
        provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) {
-    if (type_and_info.second.internal_name == params->app_name) {
+    if (type_and_info.second->GetInternalName() == params->app_name) {
       app_type = type_and_info.first;
       break;
     }
diff --git a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinator.java b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinator.java
index 2752838c..c8b7858e 100644
--- a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinator.java
+++ b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinator.java
@@ -11,12 +11,10 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.merchant_viewer.MerchantTrustMetrics.MessageClearReason;
 import org.chromium.chrome.browser.merchant_viewer.proto.MerchantTrustSignalsOuterClass.MerchantTrustSignals;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.messages.DismissReason;
@@ -35,9 +33,6 @@
     private final MerchantTrustMessageScheduler mMessageScheduler;
     private final MerchantTrustBottomSheetCoordinator mDetailsTabCoordinator;
     private final Context mContext;
-    private final WindowAndroid mWindowAndroid;
-    private final BottomSheetController mBottomSheetController;
-    private final View mLayoutView;
     private final MerchantTrustMetrics mMetrics;
     private final MerchantTrustSignalsDataProvider mDataProvider;
     private final MerchantTrustSignalsStorageFactory mStorageFactory;
@@ -45,34 +40,26 @@
     /** Creates a new instance. */
     public MerchantTrustSignalsCoordinator(Context context, WindowAndroid windowAndroid,
             BottomSheetController bottomSheetController, View layoutView,
-            TabModelSelector tabModelSelector, MessageDispatcher messageDispatcher,
-            Supplier<Tab> tabSupplier, ObservableSupplier<Profile> profileSupplier,
-            MerchantTrustMetrics metrics) {
-        this(context, windowAndroid, bottomSheetController, layoutView, tabModelSelector,
-                new MerchantTrustMessageScheduler(messageDispatcher, metrics), tabSupplier,
+            MessageDispatcher messageDispatcher, ObservableSupplier<Tab> tabSupplier,
+            ObservableSupplier<Profile> profileSupplier, MerchantTrustMetrics metrics) {
+        this(context, new MerchantTrustMessageScheduler(messageDispatcher, metrics), tabSupplier,
                 new MerchantTrustSignalsDataProvider(), metrics,
                 new MerchantTrustBottomSheetCoordinator(context, windowAndroid,
                         bottomSheetController, tabSupplier, layoutView, metrics),
-                profileSupplier, new MerchantTrustSignalsStorageFactory(profileSupplier));
+                new MerchantTrustSignalsStorageFactory(profileSupplier));
     }
 
     @VisibleForTesting
-    MerchantTrustSignalsCoordinator(Context context, WindowAndroid windowAndroid,
-            BottomSheetController bottomSheetController, View layoutView,
-            TabModelSelector tabModelSelector, MerchantTrustMessageScheduler messageScheduler,
-            Supplier<Tab> tabSupplier, MerchantTrustSignalsDataProvider dataProvider,
+    MerchantTrustSignalsCoordinator(Context context, MerchantTrustMessageScheduler messageScheduler,
+            ObservableSupplier<Tab> tabSupplier, MerchantTrustSignalsDataProvider dataProvider,
             MerchantTrustMetrics metrics, MerchantTrustBottomSheetCoordinator detailsTabCoordinator,
-            ObservableSupplier<Profile> profileSupplier,
             MerchantTrustSignalsStorageFactory storageFactory) {
         mContext = context;
-        mWindowAndroid = windowAndroid;
-        mBottomSheetController = bottomSheetController;
-        mLayoutView = layoutView;
         mDataProvider = dataProvider;
         mMetrics = metrics;
         mStorageFactory = storageFactory;
 
-        mMediator = new MerchantTrustSignalsMediator(tabModelSelector, this::maybeDisplayMessage);
+        mMediator = new MerchantTrustSignalsMediator(tabSupplier, this::maybeDisplayMessage);
         mMessageScheduler = messageScheduler;
         mDetailsTabCoordinator = detailsTabCoordinator;
     }
diff --git a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediator.java b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediator.java
index efd7a39..29f962a 100644
--- a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediator.java
+++ b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediator.java
@@ -6,13 +6,11 @@
 
 import android.text.TextUtils;
 
+import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.chrome.browser.tab.CurrentTabObserver;
+import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.content_public.browser.NavigationHandle;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsObserver;
 
 /** Responsible for detecting candidate events for publishing the merchant trust message. */
 class MerchantTrustSignalsMediator {
@@ -25,62 +23,27 @@
         void maybeDisplayMessage(MerchantTrustMessageContext item);
     }
 
-    private final MerchantTrustSignalsCallback mDelegate;
-    private final TabModelSelector mTabModelSelector;
-    private final TabModelObserver mTabModelObserver;
-    private WebContents mCurrentWebContents;
-    private Tab mTab;
-
-    private final WebContentsObserver mWebContentsObserver = new WebContentsObserver() {
-        @Override
-        public void didFinishNavigation(NavigationHandle navigation) {
-            if (!navigation.hasCommitted() || !navigation.isInMainFrame()
-                    || navigation.isSameDocument()) {
-                return;
-            }
-
-            if (navigation.getUrl() == null || TextUtils.isEmpty(navigation.getUrl().getHost())) {
-                return;
-            }
-
-            mDelegate.maybeDisplayMessage(
-                    new MerchantTrustMessageContext(navigation, mCurrentWebContents));
-        }
-    };
+    private final CurrentTabObserver mCurrentTabObserver;
 
     MerchantTrustSignalsMediator(
-            TabModelSelector tabModelSelector, MerchantTrustSignalsCallback delegate) {
-        mTabModelSelector = tabModelSelector;
-        mDelegate = delegate;
-
-        mTabModelObserver = new TabModelObserver() {
+            ObservableSupplier<Tab> tabSupplier, MerchantTrustSignalsCallback delegate) {
+        mCurrentTabObserver = new CurrentTabObserver(tabSupplier, new EmptyTabObserver() {
             @Override
-            public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
-                if (mTab != null && mTab.getWebContents() != null) {
-                    mTab.getWebContents().removeObserver(mWebContentsObserver);
+            public void onDidFinishNavigation(Tab tab, NavigationHandle navigation) {
+                if ((tab.isIncognito()) || (!navigation.hasCommitted())
+                        || (!navigation.isInMainFrame()) || (navigation.isSameDocument())
+                        || (navigation.getUrl() == null)
+                        || (TextUtils.isEmpty(navigation.getUrl().getHost()))) {
+                    return;
                 }
 
-                // Capture the current Tab and WebContents instances.
-                mCurrentWebContents = tab.getWebContents();
-                mTab = tab;
-                mCurrentWebContents.addObserver(mWebContentsObserver);
+                delegate.maybeDisplayMessage(
+                        new MerchantTrustMessageContext(navigation, tab.getWebContents()));
             }
-        };
-
-        mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver);
-
-        // Listen on the initial tab's changes.
-        mTab = tabModelSelector.getCurrentTab();
-        if (mTab != null) {
-            mCurrentWebContents = mTab.getWebContents();
-            mCurrentWebContents.addObserver(mWebContentsObserver);
-        }
+        });
     }
 
     void destroy() {
-        if (mTabModelSelector != null) {
-            mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
-                    mTabModelObserver);
-        }
+        mCurrentTabObserver.destroy();
     }
 }
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinatorTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinatorTest.java
index 0d9febc..70196ff 100644
--- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinatorTest.java
+++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsCoordinatorTest.java
@@ -18,7 +18,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Build;
-import android.view.View;
 
 import androidx.test.filters.SmallTest;
 
@@ -36,7 +35,6 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
@@ -44,13 +42,11 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.merchant_viewer.MerchantTrustMetrics.MessageClearReason;
 import org.chromium.chrome.browser.merchant_viewer.proto.MerchantTrustSignalsOuterClass.MerchantTrustSignals;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
-import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.messages.DismissReason;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
@@ -96,13 +92,7 @@
     private Context mMockContext;
 
     @Mock
-    private BottomSheetController mMockBottomSheetController;
-
-    @Mock
-    private View mMockDecorView;
-
-    @Mock
-    private Supplier<Tab> mMockTabProvider;
+    private ObservableSupplier<Tab> mMockTabProvider;
 
     @Mock
     private WindowAndroid mMockWindowAndroid;
@@ -141,9 +131,6 @@
     private ArgumentCaptor<Callback> mOnMessageEnqueuedCallbackCaptor;
 
     @Mock
-    private ObservableSupplier<Profile> mMockProfileSupplier;
-
-    @Mock
     private NavigationHandle mNavigationHandle;
 
     private MerchantTrustSignals mDummyMerchantTrustSignals =
@@ -420,10 +407,8 @@
     }
 
     private MerchantTrustSignalsCoordinator getCoordinatorUnderTest() {
-        return new MerchantTrustSignalsCoordinator(mMockContext, mMockWindowAndroid,
-                mMockBottomSheetController, mMockDecorView, mMockTabModelSelector,
-                mMockMerchantMessageScheduler, mMockTabProvider, mMockMerchantTrustDataProvider,
-                mMockMetrics, mMockDetailsTabCoordinator, mMockProfileSupplier,
-                mMockMerchantTrustStorageFactory);
+        return new MerchantTrustSignalsCoordinator(mMockContext, mMockMerchantMessageScheduler,
+                mMockTabProvider, mMockMerchantTrustDataProvider, mMockMetrics,
+                mMockDetailsTabCoordinator, mMockMerchantTrustStorageFactory);
     }
 }
\ No newline at end of file
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediatorTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediatorTest.java
index cf9716bc..7e3a8e5f 100644
--- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediatorTest.java
+++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsMediatorTest.java
@@ -5,13 +5,12 @@
 package org.chromium.chrome.browser.merchant_viewer;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -23,18 +22,16 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
+import org.chromium.base.Callback;
+import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabImpl;
-import org.chromium.chrome.browser.tab.TabSelectionType;
-import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsObserver;
 import org.chromium.url.GURL;
-import org.chromium.url.JUnitTestGURLs;
 
 /**
  * Tests for {@link MerchantTrustSignalsMediator}.
@@ -49,19 +46,10 @@
     private MerchantTrustSignalsMediator.MerchantTrustSignalsCallback mMockDelegate;
 
     @Mock
-    private TabModelSelector mMockTabModelSelector;
+    private TabImpl mMockTab;
 
     @Mock
-    private TabModelObserver mMockTabModelObserver;
-
-    @Mock
-    private TabModelFilterProvider mTabModelFilterProvider;
-
-    @Mock
-    private TabImpl mMockPrimaryTab;
-
-    @Mock
-    private TabImpl mMockSecondaryTab;
+    private ObservableSupplier<Tab> mMockTabProvider;
 
     @Mock
     private WebContents mMockWebContents;
@@ -69,162 +57,92 @@
     @Mock
     private NavigationHandle mMockNavigationHandle;
 
-    @Captor
-    private ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
+    @Mock
+    private GURL mMockUrl;
 
     @Captor
-    private ArgumentCaptor<WebContentsObserver> mWebContentsObserver;
+    private ArgumentCaptor<Callback<Tab>> mTabSupplierCallbackCaptor;
+
+    @Captor
+    private ArgumentCaptor<TabObserver> mTabObserverCaptor;
+
+    private MerchantTrustSignalsMediator mMediator;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        doReturn(mTabModelFilterProvider).when(mMockTabModelSelector).getTabModelFilterProvider();
-        doReturn(100).when(mMockPrimaryTab).getId();
-        doReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1)).when(mMockPrimaryTab).getUrl();
-        doReturn(mMockWebContents).when(mMockPrimaryTab).getWebContents();
-
-        doReturn(200).when(mMockSecondaryTab).getId();
-        doReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2)).when(mMockSecondaryTab).getUrl();
-        doReturn(mMockWebContents).when(mMockSecondaryTab).getWebContents();
-    }
-
-    @Test
-    public void testObserversSetup() {
-        getMediatorUnderTest(mMockPrimaryTab);
-    }
-
-    @Test
-    public void testWebContentsUpdated() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-
-        // Select another tab.
-        mTabModelObserverCaptor.getValue().didSelectTab(
-                mMockSecondaryTab, TabSelectionType.FROM_USER, 100);
-
-        verify(mMockWebContents, times(1)).removeObserver(eq(mWebContentsObserver.getValue()));
-        verify(mMockWebContents, times(2)).addObserver(mWebContentsObserver.capture());
-    }
-
-    @Test
-    public void testDestroyCleanup() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-
-        mediator.destroy();
-        verify(mTabModelFilterProvider, times(1))
-                .removeTabModelFilterObserver(eq(mTabModelObserverCaptor.getValue()));
-    }
-
-    @Test
-    public void testWebContentsNavigation() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-        GURL gurl = mock(GURL.class);
-
+        doReturn(mMockWebContents).when(mMockTab).getWebContents();
+        doReturn(false).when(mMockTab).isIncognito();
         doReturn(true).when(mMockNavigationHandle).hasCommitted();
         doReturn(true).when(mMockNavigationHandle).isInMainFrame();
         doReturn(false).when(mMockNavigationHandle).isSameDocument();
+        doReturn(mMockUrl).when(mMockNavigationHandle).getUrl();
+        doReturn("fake_host").when(mMockUrl).getHost();
 
-        doReturn("fake_host").when(gurl).getHost();
-        doReturn(gurl).when(mMockNavigationHandle).getUrl();
+        createMediatorAndVerify();
+    }
 
-        mWebContentsObserver.getValue().didFinishNavigation(mMockNavigationHandle);
+    @After
+    public void tearDown() {
+        destroyAndVerify();
+    }
 
+    private void createMediatorAndVerify() {
+        mMediator = new MerchantTrustSignalsMediator(mMockTabProvider, mMockDelegate);
+        verify(mMockTabProvider, times(1)).addObserver(mTabSupplierCallbackCaptor.capture());
+        mTabSupplierCallbackCaptor.getValue().onResult(mMockTab);
+        verify(mMockTab, times(1)).addObserver(mTabObserverCaptor.capture());
+    }
+
+    private void destroyAndVerify() {
+        mMediator.destroy();
+        verify(mMockTab, times(1)).removeObserver(mTabObserverCaptor.getValue());
+        verify(mMockTabProvider, times(1)).removeObserver(mTabSupplierCallbackCaptor.getValue());
+    }
+
+    @Test
+    public void testTabObserverOnDidFinishNavigation() {
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
         verify(mMockDelegate, times(1)).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
     }
 
     @Test
-    public void testWebContentsNavigationNonCommit() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-        GURL gurl = mock(GURL.class);
+    public void testTabObserverOnDidFinishNavigation_IncognitoTab() {
+        doReturn(true).when(mMockTab).isIncognito();
 
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
+        verify(mMockDelegate, never()).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
+    }
+
+    @Test
+    public void testTabObserverOnDidFinishNavigation_NavigationNonCommit() {
         doReturn(false).when(mMockNavigationHandle).hasCommitted();
-        doReturn(true).when(mMockNavigationHandle).isInMainFrame();
-        doReturn(false).when(mMockNavigationHandle).isSameDocument();
 
-        doReturn("fake_host").when(gurl).getHost();
-        doReturn(gurl).when(mMockNavigationHandle).getUrl();
-
-        mWebContentsObserver.getValue().didFinishNavigation(mMockNavigationHandle);
-
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
         verify(mMockDelegate, never()).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
     }
 
     @Test
-    public void testWebContentsNavigationNonMainFrame() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-        GURL gurl = mock(GURL.class);
-
-        doReturn(true).when(mMockNavigationHandle).hasCommitted();
+    public void testTabObserverOnDidFinishNavigation_NonMainFrame() {
         doReturn(false).when(mMockNavigationHandle).isInMainFrame();
-        doReturn(false).when(mMockNavigationHandle).isSameDocument();
 
-        doReturn("fake_host").when(gurl).getHost();
-        doReturn(gurl).when(mMockNavigationHandle).getUrl();
-
-        mWebContentsObserver.getValue().didFinishNavigation(mMockNavigationHandle);
-
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
         verify(mMockDelegate, never()).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
     }
 
     @Test
-    public void testWebContentsNavigationSameDoc() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-        GURL gurl = mock(GURL.class);
-
-        doReturn(true).when(mMockNavigationHandle).hasCommitted();
-        doReturn(true).when(mMockNavigationHandle).isInMainFrame();
+    public void testTabObserverOnDidFinishNavigation_SameDoc() {
         doReturn(true).when(mMockNavigationHandle).isSameDocument();
 
-        doReturn("fake_host").when(gurl).getHost();
-        doReturn(gurl).when(mMockNavigationHandle).getUrl();
-
-        mWebContentsObserver.getValue().didFinishNavigation(mMockNavigationHandle);
-
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
         verify(mMockDelegate, never()).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
     }
 
     @Test
-    public void testWebContentsNavigationMissingHost() {
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(mMockPrimaryTab);
-        GURL gurl = mock(GURL.class);
+    public void testTabObserverOnDidFinishNavigation_MissingHost() {
+        doReturn(null).when(mMockUrl).getHost();
 
-        doReturn(true).when(mMockNavigationHandle).hasCommitted();
-        doReturn(true).when(mMockNavigationHandle).isInMainFrame();
-        doReturn(false).when(mMockNavigationHandle).isSameDocument();
-
-        doReturn(null).when(gurl).getHost();
-        doReturn(gurl).when(mMockNavigationHandle).getUrl();
-
-        mWebContentsObserver.getValue().didFinishNavigation(mMockNavigationHandle);
-
+        mTabObserverCaptor.getValue().onDidFinishNavigation(mMockTab, mMockNavigationHandle);
         verify(mMockDelegate, never()).maybeDisplayMessage(any(MerchantTrustMessageContext.class));
     }
-
-    @Test
-    public void testInitialTabSelection() {
-        doReturn(mMockPrimaryTab).when(mMockTabModelSelector).getCurrentTab();
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(null);
-        verify(mMockWebContents, times(1)).addObserver(mWebContentsObserver.capture());
-    }
-
-    @Test
-    public void testInitialTabEmpty() {
-        doReturn(null).when(mMockTabModelSelector).getCurrentTab();
-        MerchantTrustSignalsMediator mediator = getMediatorUnderTest(null);
-        verify(mMockWebContents, never()).addObserver(mWebContentsObserver.capture());
-    }
-
-    private MerchantTrustSignalsMediator getMediatorUnderTest(TabImpl tabToSelect) {
-        MerchantTrustSignalsMediator mediator =
-                new MerchantTrustSignalsMediator(mMockTabModelSelector, mMockDelegate);
-        verify(mTabModelFilterProvider, times(1))
-                .addTabModelFilterObserver(mTabModelObserverCaptor.capture());
-
-        if (tabToSelect != null) {
-            mTabModelObserverCaptor.getValue().didSelectTab(
-                    mMockPrimaryTab, TabSelectionType.FROM_USER, 0);
-            verify(mMockWebContents, times(1)).addObserver(mWebContentsObserver.capture());
-        }
-
-        return mediator;
-    }
 }
diff --git a/chrome/browser/content_creation/notes/internal/BUILD.gn b/chrome/browser/content_creation/notes/internal/BUILD.gn
deleted file mode 100644
index 9881f5e0..0000000
--- a/chrome/browser/content_creation/notes/internal/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-source_set("internal") {
-  sources = [
-    "note_service_factory.cc",
-    "note_service_factory.h",
-  ]
-  deps = [
-    "//base",
-    "//components/content_creation/notes/core",
-    "//components/content_creation/notes/core/templates",
-    "//components/keyed_service/core",
-  ]
-
-  if (is_android) {
-    deps += [
-      "//chrome/browser/content_creation/notes/internal/android:jni_headers",
-    ]
-  }
-}
diff --git a/chrome/browser/content_creation/notes/internal/android/note_service_bridge_factory.cc b/chrome/browser/content_creation/notes/internal/android/note_service_bridge_factory.cc
index a64d210..d924830 100644
--- a/chrome/browser/content_creation/notes/internal/android/note_service_bridge_factory.cc
+++ b/chrome/browser/content_creation/notes/internal/android/note_service_bridge_factory.cc
@@ -16,15 +16,14 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& j_profile) {
   Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile);
-  ProfileKey* profile_key = profile->GetProfileKey();
 
   // Return null if there is no reasonable context for the provided Java
   // profile.
-  if (profile_key == nullptr)
+  if (profile == nullptr)
     return base::android::ScopedJavaLocalRef<jobject>();
 
   content_creation::NoteService* note_service =
-      NoteServiceFactory::GetInstance()->GetServiceInstance(profile_key);
+      content_creation::NoteServiceFactory::GetForProfile(profile);
   return content_creation::NoteServiceBridge::GetBridgeForNoteService(
       note_service);
 }
diff --git a/chrome/browser/content_creation/notes/internal/note_service_factory.cc b/chrome/browser/content_creation/notes/internal/note_service_factory.cc
index b93da7e..0914c1d4 100644
--- a/chrome/browser/content_creation/notes/internal/note_service_factory.cc
+++ b/chrome/browser/content_creation/notes/internal/note_service_factory.cc
@@ -5,13 +5,17 @@
 #include "chrome/browser/content_creation/notes/internal/note_service_factory.h"
 
 #include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/content_creation/notes/core/note_service.h"
+#include "components/content_creation/notes/core/server/notes_repository.h"
 #include "components/content_creation/notes/core/templates/template_store.h"
-#include "components/keyed_service/core/simple_dependency_manager.h"
-#include "components/keyed_service/core/simple_factory_key.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
 
-using content_creation::NoteService;
-using content_creation::TemplateStore;
+namespace content_creation {
 
 // static
 NoteServiceFactory* NoteServiceFactory::GetInstance() {
@@ -19,21 +23,29 @@
 }
 
 // static
-NoteService* NoteServiceFactory::GetServiceInstance(SimpleFactoryKey* key) {
-  return static_cast<NoteService*>(GetInstance()->GetServiceForKey(key, true));
+NoteService* NoteServiceFactory::GetForProfile(Profile* profile) {
+  return static_cast<NoteService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, /*create=*/true));
 }
 
 NoteServiceFactory::NoteServiceFactory()
-    : SimpleKeyedServiceFactory("NoteService",
-                                SimpleDependencyManager::GetInstance()) {}
+    : BrowserContextKeyedServiceFactory(
+          "NoteService",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(IdentityManagerFactory::GetInstance());
+}
 
 NoteServiceFactory::~NoteServiceFactory() = default;
 
-std::unique_ptr<KeyedService> NoteServiceFactory::BuildServiceInstanceFor(
-    SimpleFactoryKey* key) const {
-  return std::make_unique<NoteService>(std::make_unique<TemplateStore>());
+KeyedService* NoteServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+
+  return new NoteService(std::make_unique<TemplateStore>(),
+                         std::make_unique<NotesRepository>(
+                             IdentityManagerFactory::GetForProfile(profile),
+                             context->GetDefaultStoragePartition()
+                                 ->GetURLLoaderFactoryForBrowserProcess()));
 }
 
-SimpleFactoryKey* NoteServiceFactory::GetKeyToUse(SimpleFactoryKey* key) const {
-  return key;
-}
+}  // namespace content_creation
diff --git a/chrome/browser/content_creation/notes/internal/note_service_factory.h b/chrome/browser/content_creation/notes/internal/note_service_factory.h
index c052f0e8..80e2236 100644
--- a/chrome/browser/content_creation/notes/internal/note_service_factory.h
+++ b/chrome/browser/content_creation/notes/internal/note_service_factory.h
@@ -7,22 +7,20 @@
 
 #include "base/macros.h"
 #include "base/memory/singleton.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/keyed_service/core/simple_keyed_service_factory.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class KeyedService;
+class Profile;
 
 namespace content_creation {
-class NoteService;
-}  // namespace content_creation
 
-class SimpleFactoryKey;
+class NoteService;
 
 // Factory to create and retrieve a NoteService per profile.
-class NoteServiceFactory : public SimpleKeyedServiceFactory {
+class NoteServiceFactory : public BrowserContextKeyedServiceFactory {
  public:
   static NoteServiceFactory* GetInstance();
-
-  static content_creation::NoteService* GetServiceInstance(
-      SimpleFactoryKey* key);
+  static content_creation::NoteService* GetForProfile(Profile* profile);
 
  private:
   friend struct base::DefaultSingletonTraits<NoteServiceFactory>;
@@ -30,12 +28,11 @@
   NoteServiceFactory();
   ~NoteServiceFactory() override;
 
-  // SimpleKeyedServiceFactory implementation:
-  std::unique_ptr<KeyedService> BuildServiceInstanceFor(
-      SimpleFactoryKey* key) const override;
-  SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(NoteServiceFactory);
+  // BrowserContextKeyedServiceFactory implementation:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
 };
 
+}  // namespace content_creation
+
 #endif  // CHROME_BROWSER_CONTENT_CREATION_NOTES_INTERNAL_NOTE_SERVICE_FACTORY_H_
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
index 32caa55..5a2b3a8 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.cc
@@ -143,6 +143,18 @@
   return block_until_verdict_ == BlockUntilVerdict::BLOCK;
 }
 
+absl::optional<std::u16string> AnalysisServiceSettings::GetCustomMessage() {
+  if (!IsValid() || custom_message_text_.empty())
+    return absl::nullopt;
+  return custom_message_text_;
+}
+
+absl::optional<GURL> AnalysisServiceSettings::GetLearnMoreUrl() {
+  if (!IsValid() || custom_message_learn_more_url_.is_empty())
+    return absl::nullopt;
+  return custom_message_learn_more_url_;
+}
+
 void AnalysisServiceSettings::AddUrlPatternSettings(
     const base::Value& url_settings_value,
     bool enabled,
diff --git a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
index f38911ff..b251e6b 100644
--- a/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
+++ b/chrome/browser/enterprise/connectors/analysis/analysis_service_settings.h
@@ -32,6 +32,11 @@
   // Get the block_until_verdict setting if the settings are valid.
   bool ShouldBlockUntilVerdict() const;
 
+  // Get the custom message/learn more URL. Returns absl::nullopt if the
+  // settings are invalid or if the message/URL are empty.
+  absl::optional<std::u16string> GetCustomMessage();
+  absl::optional<GURL> GetLearnMoreUrl();
+
   std::string service_provider_name() const { return service_provider_name_; }
 
  private:
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
index 7b0230a..82b6550 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -220,7 +220,8 @@
 absl::optional<std::u16string> ContentAnalysisDelegate::GetCustomMessage()
     const {
   if (!data_.settings.custom_message_text.empty()) {
-    return data_.settings.custom_message_text;
+    return l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE,
+                                      data_.settings.custom_message_text);
   }
 
   return absl::nullopt;
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
index 4da6e54..9518591 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
@@ -127,7 +127,7 @@
 
 const std::set<std::string>* DocMimeTypes() {
   static std::set<std::string> set = {
-      "application/msword",
+      "application/msword", "text/plain",
       // The 50 MB file can result in no mimetype being found.
       ""};
   return &set;
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
index 22cd7c9..154440f 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog.cc
@@ -704,8 +704,7 @@
 std::u16string ContentAnalysisDialog::GetCustomMessage() const {
   DCHECK(is_warning() || is_failure());
   DCHECK(has_custom_message());
-  return l10n_util::GetStringFUTF16(IDS_DEEP_SCANNING_DIALOG_CUSTOM_MESSAGE,
-                                    *(delegate_->GetCustomMessage()));
+  return *(delegate_->GetCustomMessage());
 }
 
 const gfx::ImageSkia* ContentAnalysisDialog::GetTopImage() const {
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc
index 7287e9e..56b6218 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_dialog_browsertest.cc
@@ -824,8 +824,7 @@
       std::move(delegate), ContentAnalysisDelegateBase::FinalResult::SUCCESS);
   dialog->ShowResult(ContentAnalysisDelegateBase::FinalResult::WARNING);
 
-  EXPECT_EQ(dialog->GetMessageForTesting()->GetText(),
-            u"Your administrator says \"Test\".");
+  EXPECT_EQ(dialog->GetMessageForTesting()->GetText(), u"Test");
 }
 
 IN_PROC_BROWSER_TEST_F(ContentAnalysisDialogPlainTests,
@@ -883,6 +882,7 @@
                        TestWithDownloadsDelegateBypassWarning) {
   ContentAnalysisDialog* dialog = CreateContentAnalysisDialog(
       std::make_unique<ContentAnalysisDownloadsDelegate>(
+          u"", u"", GURL(),
           base::BindOnce(&ContentAnalysisDialogPlainTests::OpenCallback,
                          base::Unretained(this)),
           base::BindOnce(&ContentAnalysisDialogPlainTests::DiscardCallback,
@@ -901,6 +901,7 @@
                        TestWithDownloadsDelegateDiscardWarning) {
   ContentAnalysisDialog* dialog = CreateContentAnalysisDialog(
       std::make_unique<ContentAnalysisDownloadsDelegate>(
+          u"", u"", GURL(),
           base::BindOnce(&ContentAnalysisDialogPlainTests::OpenCallback,
                          base::Unretained(this)),
           base::BindOnce(&ContentAnalysisDialogPlainTests::DiscardCallback,
@@ -919,6 +920,7 @@
                        TestWithDownloadsDelegateDiscardBlock) {
   ContentAnalysisDialog* dialog = CreateContentAnalysisDialog(
       std::make_unique<ContentAnalysisDownloadsDelegate>(
+          u"", u"", GURL(),
           base::BindOnce(&ContentAnalysisDialogPlainTests::OpenCallback,
                          base::Unretained(this)),
           base::BindOnce(&ContentAnalysisDialogPlainTests::DiscardCallback,
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.cc
index 120bc57..0b6fcedb 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.cc
@@ -4,12 +4,23 @@
 
 #include "chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h"
 
+#include "chrome/browser/enterprise/connectors/connectors_service.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/enterprise/common/proto/connectors.pb.h"
+#include "ui/base/l10n/l10n_util.h"
+
 namespace enterprise_connectors {
 
 ContentAnalysisDownloadsDelegate::ContentAnalysisDownloadsDelegate(
+    const std::u16string& filename,
+    const std::u16string& custom_message,
+    GURL custom_learn_more_url,
     base::OnceCallback<void()> open_file_callback,
     base::OnceCallback<void()> discard_file_callback)
-    : open_file_callback_(std::move(open_file_callback)),
+    : filename_(filename),
+      custom_message_(custom_message),
+      custom_learn_more_url_(custom_learn_more_url),
+      open_file_callback_(std::move(open_file_callback)),
       discard_file_callback_(std::move(discard_file_callback)) {}
 
 ContentAnalysisDownloadsDelegate::~ContentAnalysisDownloadsDelegate() = default;
@@ -33,12 +44,18 @@
 
 absl::optional<std::u16string>
 ContentAnalysisDownloadsDelegate::GetCustomMessage() const {
-  return absl::nullopt;
+  if (custom_message_.empty())
+    return absl::nullopt;
+  return l10n_util::GetStringFUTF16(
+      IDS_DEEP_SCANNING_DIALOG_DOWNLOADS_CUSTOM_MESSAGE, filename_,
+      custom_message_);
 }
 
 absl::optional<GURL> ContentAnalysisDownloadsDelegate::GetCustomLearnMoreUrl()
     const {
-  return absl::nullopt;
+  if (custom_learn_more_url_.is_empty())
+    return absl::nullopt;
+  return custom_learn_more_url_;
 }
 
 }  // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h
index 6d10806..2e97723 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h
@@ -16,6 +16,9 @@
 class ContentAnalysisDownloadsDelegate : public ContentAnalysisDelegateBase {
  public:
   ContentAnalysisDownloadsDelegate(
+      const std::u16string& filename,
+      const std::u16string& custom_message,
+      GURL custom_learn_more_url,
       base::OnceCallback<void()> open_file_callback,
       base::OnceCallback<void()> discard_file_callback);
   ~ContentAnalysisDownloadsDelegate() override;
@@ -38,6 +41,9 @@
   // (which may be undefined).
   void ResetCallbacks();
 
+  std::u16string filename_;
+  std::u16string custom_message_;
+  GURL custom_learn_more_url_;
   base::OnceCallback<void()> open_file_callback_;
   base::OnceCallback<void()> discard_file_callback_;
 };
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate_unittest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate_unittest.cc
index 651b2eb..8994d4c 100644
--- a/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate_unittest.cc
+++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate_unittest.cc
@@ -20,6 +20,7 @@
 
 TEST_F(ContentAnalysisDownloadsDelegateTest, TestOpenFile) {
   ContentAnalysisDownloadsDelegate delegate(
+      u"", u"", GURL(),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::OpenCallback,
                      base::Unretained(this)),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::DiscardCallback,
@@ -45,6 +46,7 @@
 
 TEST_F(ContentAnalysisDownloadsDelegateTest, TestDiscardFileWarning) {
   ContentAnalysisDownloadsDelegate delegate(
+      u"", u"", GURL(),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::OpenCallback,
                      base::Unretained(this)),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::DiscardCallback,
@@ -70,6 +72,7 @@
 
 TEST_F(ContentAnalysisDownloadsDelegateTest, TestDiscardFileBlock) {
   ContentAnalysisDownloadsDelegate delegate(
+      u"", u"", GURL(),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::OpenCallback,
                      base::Unretained(this)),
       base::BindOnce(&ContentAnalysisDownloadsDelegateTest::DiscardCallback,
@@ -93,4 +96,35 @@
   EXPECT_EQ(1, times_discard_called_);
 }
 
+TEST_F(ContentAnalysisDownloadsDelegateTest, TestNoMessageOrUrlReturnsNullOpt) {
+  ContentAnalysisDownloadsDelegate delegate(
+      u"", u"", GURL(),
+      base::BindOnce(&ContentAnalysisDownloadsDelegateTest::OpenCallback,
+                     base::Unretained(this)),
+      base::BindOnce(&ContentAnalysisDownloadsDelegateTest::DiscardCallback,
+                     base::Unretained(this)));
+
+  EXPECT_FALSE(delegate.GetCustomMessage());
+  EXPECT_FALSE(delegate.GetCustomLearnMoreUrl());
+}
+
+TEST_F(ContentAnalysisDownloadsDelegateTest, TestGetMessageAndUrl) {
+  ContentAnalysisDownloadsDelegate delegate(
+      u"foo.txt", u"Message", GURL("http://www.example.com"),
+      base::BindOnce(&ContentAnalysisDownloadsDelegateTest::OpenCallback,
+                     base::Unretained(this)),
+      base::BindOnce(&ContentAnalysisDownloadsDelegateTest::DiscardCallback,
+                     base::Unretained(this)));
+
+  EXPECT_TRUE(delegate.GetCustomMessage());
+  EXPECT_TRUE(delegate.GetCustomLearnMoreUrl());
+
+  EXPECT_EQ(
+      u"foo.txt has sensitive or dangerous data. Your administrator says "
+      u"\"Message\".",
+      *(delegate.GetCustomMessage()));
+  EXPECT_EQ(GURL("http://www.example.com"),
+            *(delegate.GetCustomLearnMoreUrl()));
+}
+
 }  // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/connectors_manager.cc b/chrome/browser/enterprise/connectors/connectors_manager.cc
index 420e555a..c3ce91f 100644
--- a/chrome/browser/enterprise/connectors/connectors_manager.cc
+++ b/chrome/browser/enterprise/connectors/connectors_manager.cc
@@ -193,6 +193,36 @@
   return false;
 }
 
+absl::optional<std::u16string> ConnectorsManager::GetCustomMessage(
+    AnalysisConnector connector) {
+  if (IsConnectorEnabled(connector)) {
+    if (analysis_connector_settings_.count(connector) == 0)
+      CacheAnalysisConnectorPolicy(connector);
+
+    if (analysis_connector_settings_.count(connector) &&
+        !analysis_connector_settings_.at(connector).empty()) {
+      return analysis_connector_settings_.at(connector)
+          .at(0)
+          .GetCustomMessage();
+    }
+  }
+  return absl::nullopt;
+}
+
+absl::optional<GURL> ConnectorsManager::GetLearnMoreUrl(
+    AnalysisConnector connector) {
+  if (IsConnectorEnabled(connector)) {
+    if (analysis_connector_settings_.count(connector) == 0)
+      CacheAnalysisConnectorPolicy(connector);
+
+    if (analysis_connector_settings_.count(connector) &&
+        !analysis_connector_settings_.at(connector).empty()) {
+      return analysis_connector_settings_.at(connector).at(0).GetLearnMoreUrl();
+    }
+  }
+  return absl::nullopt;
+}
+
 std::vector<std::string> ConnectorsManager::GetAnalysisServiceProviderNames(
     AnalysisConnector connector) {
   if (IsConnectorEnabled(connector)) {
diff --git a/chrome/browser/enterprise/connectors/connectors_manager.h b/chrome/browser/enterprise/connectors/connectors_manager.h
index ae25ee03..4892da62 100644
--- a/chrome/browser/enterprise/connectors/connectors_manager.h
+++ b/chrome/browser/enterprise/connectors/connectors_manager.h
@@ -61,6 +61,8 @@
   bool IsConnectorEnabled(FileSystemConnector connector) const;
 
   bool DelayUntilVerdict(AnalysisConnector connector);
+  absl::optional<std::u16string> GetCustomMessage(AnalysisConnector connector);
+  absl::optional<GURL> GetLearnMoreUrl(AnalysisConnector connector);
 
   std::vector<std::string> GetAnalysisServiceProviderNames(
       AnalysisConnector connector);
diff --git a/chrome/browser/enterprise/connectors/connectors_service.cc b/chrome/browser/enterprise/connectors/connectors_service.cc
index 21753af..dcb932a 100644
--- a/chrome/browser/enterprise/connectors/connectors_service.cc
+++ b/chrome/browser/enterprise/connectors/connectors_service.cc
@@ -332,6 +332,26 @@
   return connectors_manager_->DelayUntilVerdict(connector);
 }
 
+absl::optional<std::u16string> ConnectorsService::GetCustomMessage(
+    AnalysisConnector connector) {
+  if (!ConnectorsEnabled())
+    return absl::nullopt;
+
+  return connectors_manager_->GetCustomMessage(connector);
+}
+
+absl::optional<GURL> ConnectorsService::GetLearnMoreUrl(
+    AnalysisConnector connector) {
+  if (!ConnectorsEnabled())
+    return absl::nullopt;
+
+  return connectors_manager_->GetLearnMoreUrl(connector);
+}
+
+bool ConnectorsService::HasCustomInfoToDisplay(AnalysisConnector connector) {
+  return GetCustomMessage(connector) || GetLearnMoreUrl(connector);
+}
+
 std::vector<std::string> ConnectorsService::GetAnalysisServiceProviderNames(
     AnalysisConnector connector) {
   if (!ConnectorsEnabled())
diff --git a/chrome/browser/enterprise/connectors/connectors_service.h b/chrome/browser/enterprise/connectors/connectors_service.h
index afa0482..ff5ac26 100644
--- a/chrome/browser/enterprise/connectors/connectors_service.h
+++ b/chrome/browser/enterprise/connectors/connectors_service.h
@@ -63,6 +63,9 @@
   bool IsConnectorEnabled(FileSystemConnector connector) const;
 
   bool DelayUntilVerdict(AnalysisConnector connector);
+  absl::optional<std::u16string> GetCustomMessage(AnalysisConnector connector);
+  absl::optional<GURL> GetLearnMoreUrl(AnalysisConnector connector);
+  bool HasCustomInfoToDisplay(AnalysisConnector connector);
 
   std::vector<std::string> GetAnalysisServiceProviderNames(
       AnalysisConnector connector);
diff --git a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
index 39f2d0a..6ea5f9b 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
@@ -8,9 +8,6 @@
 #include "base/callback_helpers.h"
 #include "build/branding_buildflags.h"
 #include "build/chromeos_buildflags.h"
-#include "chrome/browser/media/router/media_router_feature.h"       // nogncheck
-#include "chrome/browser/media/router/mojo/media_router_desktop.h"  // nogncheck
-#include "components/media_router/common/mojom/media_router.mojom.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -103,14 +100,6 @@
     content::RenderFrameHost* render_frame_host,
     const Extension* extension) {
   DCHECK(extension);
-  auto* context = render_frame_host->GetProcess()->GetBrowserContext();
-  if (media_router::MediaRouterEnabled(context) &&
-      extension->permissions_data()->HasAPIPermission(
-          mojom::APIPermissionID::kMediaRouterPrivate)) {
-    binder_map->Add<media_router::mojom::MediaRouter>(
-        base::BindRepeating(&media_router::MediaRouterDesktop::BindToReceiver,
-                            base::RetainedRef(extension), context));
-  }
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 
diff --git a/chrome/browser/feed/android/BUILD.gn b/chrome/browser/feed/android/BUILD.gn
index 637d6135..8a2123de 100644
--- a/chrome/browser/feed/android/BUILD.gn
+++ b/chrome/browser/feed/android/BUILD.gn
@@ -186,6 +186,7 @@
     "//ui/android:ui_java_test_support",
     "//ui/android:ui_java_test_support",
     "//ui/android:ui_no_recycler_view_java",
+    "//ui/android:ui_recycler_view_java",
     "//url:gurl_java",
     "//url:gurl_junit_test_support",
   ]
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index fdca391..a8cd898 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -242,6 +242,11 @@
     "expiry_milestone": 95
   },
   {
+    "name": "ash-bento-bar",
+    "owners": [ "minch", "janetmac" ],
+    "expiry_milestone": 100
+  },
+  {
     "name": "ash-debug-shortcuts",
     "owners": [ "//ash/OWNERS" ],
     // Used by developers for debugging and to dump extra information to logs
@@ -4287,16 +4292,6 @@
     "expiry_milestone": 96
   },
   {
-    "name": "pluginvm-show-camera-permissions",
-    "owners": [ "danielng@google.com", "lxj@google.com" ],
-    "expiry_milestone": 93
-  },
-  {
-    "name": "pluginvm-show-microphone-permissions",
-    "owners": [ "dtor", "lxj@google.com" ],
-    "expiry_milestone": 93
-  },
-  {
     "name": "post-quantum-cecpq2",
     "owners": [ "agl" ],
     "expiry_milestone": 100
@@ -5328,11 +5323,6 @@
     "expiry_milestone": 93
   },
   {
-    "name": "vm-camera-mic-indicators-and-notifications",
-    "owners": [ "lxj", "joelhockey", "timloh" ],
-    "expiry_milestone": 93
-  },
-  {
     "name": "vm-status-page",
     "owners": [ "lxj", "joelhockey", "timloh" ],
     "expiry_milestone": 94
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 104cd244b..f3b9f89e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -363,6 +363,11 @@
     "To enable caching pages on same-site navigations too, choose 'enabled "
     "same-site support'.";
 
+const char kBentoBarName[] = "Persistent desks bar";
+const char kBentoBarDescription[] =
+    "Showing a persistent desks bar at the top of the screen in clamshell mode "
+    "when there are more than one desk.";
+
 const char kBiometricReauthForPasswordFillingName[] =
     "Biometric reauth for password filling";
 const char kBiometricReauthForPasswordFillingDescription[] =
@@ -4881,16 +4886,6 @@
 const char kPluginVmFullscreenDescription[] =
     "Hides shelf in immersive mode and allows esc hold to exit.";
 
-const char kPluginVmShowCameraPermissionsName[] =
-    "Show Plugin VM camera permissions";
-const char kPluginVmShowCameraPermissionsDescription[] =
-    "Displays camera permissions for Plugin VM in the app settings.";
-
-const char kPluginVmShowMicrophonePermissionsName[] =
-    "Show Plugin VM microphone permissions";
-const char kPluginVmShowMicrophonePermissionsDescription[] =
-    "Displays microphone permissions for Plugin VM in the app settings.";
-
 const char kTetherName[] = "Instant Tethering";
 const char kTetherDescription[] =
     "Enables Instant Tethering. Instant Tethering allows your nearby Google "
@@ -4945,11 +4940,6 @@
 const char kVirtualKeyboardMultipasteDescription[] =
     "Show virtual keyboard with multipaste UI";
 
-const char kVmCameraMicIndicatorsAndNotificationsName[] =
-    "VM camera/mic indicators/notifications";
-const char kVmCameraMicIndicatorsAndNotificationsDescription[] =
-    "Show VM camera/mic indicators/notifications";
-
 const char kVmStatusPageName[] = "VM status page";
 const char kVmStatusPageDescription[] = "Enable VM status page";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b6c2c69..747f435 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -217,6 +217,9 @@
 extern const char kBackForwardCacheName[];
 extern const char kBackForwardCacheDescription[];
 
+extern const char kBentoBarName[];
+extern const char kBentoBarDescription[];
+
 extern const char kBiometricReauthForPasswordFillingName[];
 extern const char kBiometricReauthForPasswordFillingDescription[];
 
@@ -2539,12 +2542,6 @@
 extern const char kPluginVmFullscreenName[];
 extern const char kPluginVmFullscreenDescription[];
 
-extern const char kPluginVmShowCameraPermissionsName[];
-extern const char kPluginVmShowCameraPermissionsDescription[];
-
-extern const char kPluginVmShowMicrophonePermissionsName[];
-extern const char kPluginVmShowMicrophonePermissionsDescription[];
-
 extern const char kTrimOnFreezeName[];
 extern const char kTrimOnFreezeDescription[];
 
@@ -2862,9 +2859,6 @@
 extern const char kVirtualKeyboardMultipasteName[];
 extern const char kVirtualKeyboardMultipasteDescription[];
 
-extern const char kVmCameraMicIndicatorsAndNotificationsName[];
-extern const char kVmCameraMicIndicatorsAndNotificationsDescription[];
-
 extern const char kVmStatusPageName[];
 extern const char kVmStatusPageDescription[];
 
diff --git a/chrome/browser/language/android/java/res/layout/app_language_prompt_row.xml b/chrome/browser/language/android/java/res/layout/app_language_prompt_row.xml
index e8f36eb..f87a208 100644
--- a/chrome/browser/language/android/java/res/layout/app_language_prompt_row.xml
+++ b/chrome/browser/language/android/java/res/layout/app_language_prompt_row.xml
@@ -27,7 +27,7 @@
         android:gravity="center">
 
       <TextView
-          android:id="@+id/native_language_name"
+          android:id="@+id/primary_language_name"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:textAppearance="@style/TextAppearance.TextLarge.Primary"
@@ -35,7 +35,7 @@
           android:singleLine="true" />
 
       <TextView
-          android:id="@+id/display_language_name"
+          android:id="@+id/secondary_language_name"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java
index 0554a74c..31ee8382 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java
@@ -187,14 +187,15 @@
      */
     private class AppLanguagePromptRowViewHolder
             extends RecyclerView.ViewHolder implements View.OnClickListener {
-        private TextView mDisplayNameTextView;
-        private TextView mNativeNameTextView;
+        private TextView mPrimaryNameTextView;
+        private TextView mSecondaryNameTextView;
         private RadioButton mRadioButton;
 
         AppLanguagePromptRowViewHolder(View view) {
             super(view);
-            mDisplayNameTextView = ((TextView) itemView.findViewById(R.id.display_language_name));
-            mNativeNameTextView = ((TextView) itemView.findViewById(R.id.native_language_name));
+            mPrimaryNameTextView = ((TextView) itemView.findViewById(R.id.primary_language_name));
+            mSecondaryNameTextView =
+                    ((TextView) itemView.findViewById(R.id.secondary_language_name));
             mRadioButton =
                     ((RadioButton) itemView.findViewById(R.id.app_language_prompt_radiobutton));
 
@@ -210,8 +211,14 @@
 
         public void bindViewHolder(LanguageItem languageItem, boolean checked) {
             mRadioButton.setChecked(checked);
-            mDisplayNameTextView.setText(languageItem.getDisplayName());
-            mNativeNameTextView.setText(languageItem.getNativeDisplayName());
+            if (languageItem.isSystemDefault()) {
+                // For the system default locale the display name should be the primary TextView.
+                mPrimaryNameTextView.setText(languageItem.getDisplayName());
+                mSecondaryNameTextView.setText(languageItem.getNativeDisplayName());
+            } else {
+                mPrimaryNameTextView.setText(languageItem.getNativeDisplayName());
+                mSecondaryNameTextView.setText(languageItem.getDisplayName());
+            }
         }
     }
 
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 366289b..d87de8e 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -266,7 +266,6 @@
       "discovery/media_sink_discovery_metrics_unittest.cc",
       "media_router_feature_unittest.cc",
       "mojo/media_router_mojo_impl_unittest.cc",
-      "mojo/media_router_mojo_metrics_unittest.cc",
       "mojo/media_sink_service_status_unittest.cc",
       "providers/cast/app_activity_unittest.cc",
       "providers/cast/cast_activity_manager_unittest.cc",
diff --git a/chrome/browser/media/router/mojo/media_router_desktop.cc b/chrome/browser/media/router/mojo/media_router_desktop.cc
index 8680735..180b1cce 100644
--- a/chrome/browser/media/router/mojo/media_router_desktop.cc
+++ b/chrome/browser/media/router/mojo/media_router_desktop.cc
@@ -20,7 +20,6 @@
 #include "components/media_router/common/media_source.h"
 #include "components/openscreen_platform/network_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "extensions/common/extension.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #if defined(OS_WIN)
@@ -35,19 +34,6 @@
 
 MediaRouterDesktop::~MediaRouterDesktop() = default;
 
-// static
-void MediaRouterDesktop::BindToReceiver(
-    const extensions::Extension* extension,
-    content::BrowserContext* context,
-    content::RenderFrameHost* render_frame_host,
-    mojo::PendingReceiver<mojom::MediaRouter> receiver) {
-  MediaRouterDesktop* impl = static_cast<MediaRouterDesktop*>(
-      MediaRouterFactory::GetApiForBrowserContext(context));
-  DCHECK(impl);
-
-  impl->BindToMojoReceiver(std::move(receiver), *extension);
-}
-
 void MediaRouterDesktop::OnUserGesture() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   MediaRouterMojoImpl::OnUserGesture();
@@ -166,17 +152,6 @@
   std::move(callback).Run(media_sink_service_status_.GetStatusAsJSONString());
 }
 
-void MediaRouterDesktop::BindToMojoReceiver(
-    mojo::PendingReceiver<mojom::MediaRouter> receiver,
-    const extensions::Extension& extension) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  MediaRouterMojoImpl::BindToMojoReceiver(std::move(receiver));
-  if (!provider_version_was_recorded_) {
-    MediaRouterMojoMetrics::RecordMediaRouteProviderVersion(extension);
-    provider_version_was_recorded_ = true;
-  }
-}
-
 void MediaRouterDesktop::InitializeMediaRouteProviders() {
   if (!openscreen_platform::HasNetworkContextGetter()) {
     openscreen_platform::SetNetworkContextGetter(base::BindRepeating([] {
@@ -256,9 +231,6 @@
 #if defined(OS_WIN)
 void MediaRouterDesktop::EnsureMdnsDiscoveryEnabled() {
   media_sink_service_->StartMdnsDiscovery();
-  // Record that we enabled mDNS discovery, so that we will know to enable again
-  // when we reconnect to the component extension.
-  should_enable_mdns_discovery_ = true;
 }
 
 void MediaRouterDesktop::OnFirewallCheckComplete(
diff --git a/chrome/browser/media/router/mojo/media_router_desktop.h b/chrome/browser/media/router/mojo/media_router_desktop.h
index 472f1a7..e8cf68b 100644
--- a/chrome/browser/media/router/mojo/media_router_desktop.h
+++ b/chrome/browser/media/router/mojo/media_router_desktop.h
@@ -14,21 +14,12 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
-namespace content {
-class RenderFrameHost;
-}
-
-namespace extensions {
-class Extension;
-}
-
 namespace media_router {
 class CastMediaRouteProvider;
 class DualMediaSinkService;
 class WiredDisplayMediaRouteProvider;
 
-// MediaRouter implementation that uses the MediaRouteProvider implemented in
-// the component extension.
+// MediaRouter implementation that uses the desktop MediaRouteProviders.
 class MediaRouterDesktop : public MediaRouterMojoImpl {
  public:
   // This constructor performs a firewall check on Windows and is not suitable
@@ -36,26 +27,6 @@
   explicit MediaRouterDesktop(content::BrowserContext* context);
   ~MediaRouterDesktop() override;
 
-  // Max number of Mojo connection error counts on a MediaRouteProvider message
-  // pipe before MediaRouterDesktop treats it as a permanent error. Used for
-  // ExtensionMediaRouteProviderProxy only.
-  static constexpr int kMaxMediaRouteProviderErrorCount = 10;
-
-  // Sets up the MediaRouter instance owned by |context| to handle
-  // MediaRouterObserver requests from the component extension given by
-  // |extension|. Creates the MediaRouterMojoImpl instance if it does not
-  // exist.
-  // Called by the Mojo module registry.
-  // |extension|: The component extension, used for querying
-  //     suspension state.
-  // |context|: The BrowserContext which owns the extension process.
-  // |receiver|: The Mojo pending receiver used for binding.
-  static void BindToReceiver(
-      const extensions::Extension* extension,
-      content::BrowserContext* context,
-      content::RenderFrameHost* render_frame_host,
-      mojo::PendingReceiver<mojom::MediaRouter> receiver);
-
   // MediaRouter implementation.
   void OnUserGesture() override;
   base::Value GetState() const override;
@@ -70,8 +41,6 @@
 
  private:
   friend class MediaRouterDesktopTest;
-  FRIEND_TEST_ALL_PREFIXES(MediaRouterDesktopTest,
-                           ExtensionMrpRecoversFromConnectionError);
 
   // Used by tests only. This constructor skips the firewall check so unit tests
   // do not have to depend on the system's firewall configuration.
@@ -91,12 +60,6 @@
   void GetMediaSinkServiceStatus(
       mojom::MediaRouter::GetMediaSinkServiceStatusCallback callback) override;
 
-  // Binds |this| to a Mojo pending receiver, so that clients can acquire a
-  // handle to a MediaRouter instance via the Mojo service connector.
-  // Passes the extension's ID to the event page request manager.
-  void BindToMojoReceiver(mojo::PendingReceiver<mojom::MediaRouter> receiver,
-                          const extensions::Extension& extension);
-
   // Initializes MRPs and adds them to |media_route_providers_|.
   void InitializeMediaRouteProviders();
 
@@ -106,7 +69,7 @@
   void InitializeDialMediaRouteProvider();
 
 #if defined(OS_WIN)
-  // Ensures that mDNS discovery is enabled in the MRPM extension. This can be
+  // Ensures that mDNS discovery is enabled in the Cast MRP. This can be
   // called many times but the MRPM will only be called once per registration
   // period.
   void EnsureMdnsDiscoveryEnabled();
@@ -134,22 +97,10 @@
   DualMediaSinkService* media_sink_service_;
   base::CallbackListSubscription media_sink_service_subscription_;
 
-  // A flag to ensure that we record the provider version once, during the
-  // initial event page wakeup attempt.
-  bool provider_version_was_recorded_ = false;
-
   // A status object that keeps track of sinks discovered by media sink
   // services.
   MediaSinkServiceStatus media_sink_service_status_;
 
-#if defined(OS_WIN)
-  // A flag to ensure that mDNS discovery is only enabled on Windows when there
-  // will be appropriate context for the user to associate a firewall prompt
-  // with Media Router. |should_enable_mdns_discovery_| can only go from
-  // |false| to |true|.
-  bool should_enable_mdns_discovery_ = false;
-#endif
-
   base::WeakPtrFactory<MediaRouterDesktop> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(MediaRouterDesktop);
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_metrics.cc b/chrome/browser/media/router/mojo/media_router_mojo_metrics.cc
index 00c2a63..d40988de 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_metrics.cc
+++ b/chrome/browser/media/router/mojo/media_router_mojo_metrics.cc
@@ -7,11 +7,8 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/version.h"
 #include "components/media_router/common/providers/cast/cast_media_source.h"
 #include "components/ukm/content/source_url_recorder.h"
-#include "components/version_info/version_info.h"
-#include "extensions/common/extension.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
 
@@ -21,45 +18,10 @@
 
 constexpr char kHistogramProviderRouteControllerCreationOutcome[] =
     "MediaRouter.Provider.RouteControllerCreationOutcome";
-constexpr char kHistogramProviderVersion[] = "MediaRouter.Provider.Version";
-constexpr char kHistogramProviderWakeReason[] =
-    "MediaRouter.Provider.WakeReason";
-constexpr char kHistogramProviderWakeup[] = "MediaRouter.Provider.Wakeup";
 
 }  // namespace
 
 // static
-void MediaRouterMojoMetrics::RecordMediaRouteProviderWakeReason(
-    MediaRouteProviderWakeReason reason) {
-  DCHECK_LT(static_cast<int>(reason),
-            static_cast<int>(MediaRouteProviderWakeReason::TOTAL_COUNT));
-  base::UmaHistogramEnumeration(kHistogramProviderWakeReason, reason,
-                                MediaRouteProviderWakeReason::TOTAL_COUNT);
-}
-
-// static
-void MediaRouterMojoMetrics::RecordMediaRouteProviderVersion(
-    const extensions::Extension& extension) {
-  MediaRouteProviderVersion version = MediaRouteProviderVersion::UNKNOWN;
-  version = GetMediaRouteProviderVersion(extension.version(),
-                                         version_info::GetVersion());
-
-  DCHECK_LT(static_cast<int>(version),
-            static_cast<int>(MediaRouteProviderVersion::TOTAL_COUNT));
-  base::UmaHistogramEnumeration(kHistogramProviderVersion, version,
-                                MediaRouteProviderVersion::TOTAL_COUNT);
-}
-
-// static
-void MediaRouterMojoMetrics::RecordMediaRouteProviderWakeup(
-    MediaRouteProviderWakeup wakeup) {
-  DCHECK_LT(static_cast<int>(wakeup),
-            static_cast<int>(MediaRouteProviderWakeup::TOTAL_COUNT));
-  base::UmaHistogramEnumeration(kHistogramProviderWakeup, wakeup,
-                                MediaRouteProviderWakeup::TOTAL_COUNT);
-}
-
-// static
 void MediaRouterMojoMetrics::RecordMediaRouteControllerCreationResult(
     bool success) {
   base::UmaHistogramBoolean(kHistogramProviderRouteControllerCreationOutcome,
@@ -97,27 +59,4 @@
   }
 }
 
-// static
-MediaRouteProviderVersion MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-    const base::Version& extension_version,
-    const base::Version& browser_version) {
-  if (!extension_version.IsValid() || extension_version.components().empty() ||
-      !browser_version.IsValid() || browser_version.components().empty()) {
-    return MediaRouteProviderVersion::UNKNOWN;
-  }
-
-  uint32_t extension_major = extension_version.components()[0];
-  uint32_t browser_major = browser_version.components()[0];
-  // Sanity check.
-  if (extension_major == 0 || browser_major == 0) {
-    return MediaRouteProviderVersion::UNKNOWN;
-  } else if (extension_major >= browser_major) {
-    return MediaRouteProviderVersion::SAME_VERSION_AS_CHROME;
-  } else if (browser_major - extension_major == 1) {
-    return MediaRouteProviderVersion::ONE_VERSION_BEHIND_CHROME;
-  } else {
-    return MediaRouteProviderVersion::MULTIPLE_VERSIONS_BEHIND_CHROME;
-  }
-}
-
 }  // namespace media_router
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_metrics.h b/chrome/browser/media/router/mojo/media_router_mojo_metrics.h
index e282988..5b953d6c 100644
--- a/chrome/browser/media/router/mojo/media_router_mojo_metrics.h
+++ b/chrome/browser/media/router/mojo/media_router_mojo_metrics.h
@@ -11,73 +11,8 @@
 #include "components/media_router/common/route_request_result.h"
 #include "content/public/browser/web_contents.h"
 
-namespace base {
-class Version;
-}  // namespace base
-
-namespace extensions {
-class Extension;
-}  // namespace extensions
-
 namespace media_router {
 
-// NOTE: Do not renumber enums as that would confuse interpretation of
-// previously logged data. When making changes, also update the enum lists
-// in tools/metrics/histograms/enums.xml to keep it in sync.
-
-// Why the Media Route Provider process was woken up.
-enum class MediaRouteProviderWakeReason {
-  CREATE_ROUTE = 0,
-  JOIN_ROUTE = 1,
-  TERMINATE_ROUTE = 2,
-  SEND_SESSION_MESSAGE = 3,
-  SEND_SESSION_BINARY_MESSAGE = 4,
-  DETACH_ROUTE = 5,
-  START_OBSERVING_MEDIA_SINKS = 6,
-  STOP_OBSERVING_MEDIA_SINKS = 7,
-  START_OBSERVING_MEDIA_ROUTES = 8,
-  STOP_OBSERVING_MEDIA_ROUTES = 9,
-  START_LISTENING_FOR_ROUTE_MESSAGES = 10,
-  STOP_LISTENING_FOR_ROUTE_MESSAGES = 11,
-  CONNECTION_ERROR = 12,
-  REGISTER_MEDIA_ROUTE_PROVIDER = 13,
-  CONNECT_ROUTE_BY_ROUTE_ID = 14,
-  ENABLE_MDNS_DISCOVERY = 15,
-  UPDATE_MEDIA_SINKS = 16,
-  SEARCH_SINKS = 17,  // Obsolete
-  PROVIDE_SINKS = 18,
-  CREATE_MEDIA_ROUTE_CONTROLLER = 19,
-  ROUTE_CONTROLLER_COMMAND = 20,
-
-  // NOTE: Add entries only immediately above this line.
-  TOTAL_COUNT = 21
-};
-
-// The install status of the Media Router component extension.
-enum class MediaRouteProviderVersion {
-  // Installed but version is invalid or cannot be determined.
-  UNKNOWN = 0,
-  // Installed and the extension version matches the browser version.
-  SAME_VERSION_AS_CHROME = 1,
-  // Installed and the extension version is one version behind the browser
-  // version.
-  ONE_VERSION_BEHIND_CHROME = 2,
-  // Installed and the extension version is more than one version behind the
-  // browser version.
-  MULTIPLE_VERSIONS_BEHIND_CHROME = 3,
-  // Note: Add entries only immediately above this line.
-  TOTAL_COUNT = 4
-};
-
-// The outcome of an attempt to wake the Media Router component event page.
-enum class MediaRouteProviderWakeup {
-  SUCCESS = 0,
-  ERROR_UNKNOWN = 1,
-  ERROR_TOO_MANY_RETRIES = 2,
-  // Note: Add entries only immediately above this line.
-  TOTAL_COUNT = 3
-};
-
 // Whether audio has been played since the last navigation. Do not modify
 // existing values, since they are used for metrics reporting. Add new values
 // only at the bottom, and also update tools/metrics/histograms/enums.xml.
@@ -89,18 +24,6 @@
 
 class MediaRouterMojoMetrics {
  public:
-  // Records the installed version of the Media Router component extension.
-  static void RecordMediaRouteProviderVersion(
-      const extensions::Extension& extension);
-
-  // Records why the media route provider extension was woken up.
-  static void RecordMediaRouteProviderWakeReason(
-      MediaRouteProviderWakeReason reason);
-
-  // Records the outcome of an attempt to wake the Media Router component event
-  // page.
-  static void RecordMediaRouteProviderWakeup(MediaRouteProviderWakeup wakeup);
-
   // Records whether the Media Route Provider succeeded or failed to create a
   // controller for a media route.
   static void RecordMediaRouteControllerCreationResult(bool success);
@@ -113,15 +36,6 @@
   static void RecordSiteInitiatedMirroringStarted(
       content::WebContents* web_contents,
       const MediaSource& media_source);
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(MediaRouterMojoMetricsTest,
-                           TestGetMediaRouteProviderVersion);
-
-  // Returns the version status of the Media Router component extension.
-  static MediaRouteProviderVersion GetMediaRouteProviderVersion(
-      const base::Version& extension_version,
-      const base::Version& browser_version);
 };
 
 }  // namespace media_router
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc
deleted file mode 100644
index bdec15d..0000000
--- a/chrome/browser/media/router/mojo/media_router_mojo_metrics_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media/router/mojo/media_router_mojo_metrics.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/version.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Bucket;
-using testing::ElementsAre;
-
-namespace media_router {
-
-TEST(MediaRouterMojoMetricsTest, TestGetMediaRouteProviderVersion) {
-  const base::Version kBrowserVersion("50.0.2396.71");
-  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("50.0.2396.71"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("50.0.2100.0"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::SAME_VERSION_AS_CHROME,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("51.0.2117.0"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::ONE_VERSION_BEHIND_CHROME,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("49.0.2138.0"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::MULTIPLE_VERSIONS_BEHIND_CHROME,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("47.0.1134.0"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("blargh"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version(""), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("-1.0.0.0"), kBrowserVersion));
-  EXPECT_EQ(MediaRouteProviderVersion::UNKNOWN,
-            MediaRouterMojoMetrics::GetMediaRouteProviderVersion(
-                base::Version("0"), kBrowserVersion));
-}
-
-}  // namespace media_router
diff --git a/chrome/browser/metrics/plugin_metrics_provider.cc b/chrome/browser/metrics/plugin_metrics_provider.cc
index 42af3d5..7141411 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider.cc
@@ -338,7 +338,7 @@
   return child_process_stats_buffer_[child_name];
 }
 
-void PluginMetricsProvider::BrowserChildProcessHostConnected(
+void PluginMetricsProvider::BrowserChildProcessLaunchedAndConnected(
     const content::ChildProcessData& data) {
   GetChildProcessStats(data).process_launches++;
   RecordCurrentStateWithDelay();
diff --git a/chrome/browser/metrics/plugin_metrics_provider.h b/chrome/browser/metrics/plugin_metrics_provider.h
index 182991f..de977a83 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.h
+++ b/chrome/browser/metrics/plugin_metrics_provider.h
@@ -78,7 +78,7 @@
   void RecordCurrentState();
 
   // content::BrowserChildProcessObserver:
-  void BrowserChildProcessHostConnected(
+  void BrowserChildProcessLaunchedAndConnected(
       const content::ChildProcessData& data) override;
   void BrowserChildProcessCrashed(
       const content::ChildProcessData& data,
diff --git a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
index 07c84957..d68727d 100644
--- a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
@@ -173,23 +173,23 @@
   content::ChildProcessData child_process_data1(
       content::PROCESS_TYPE_PPAPI_PLUGIN);
   child_process_data1.name = u"p1";
-  provider.BrowserChildProcessHostConnected(child_process_data1);
+  provider.BrowserChildProcessLaunchedAndConnected(child_process_data1);
   provider.BrowserChildProcessCrashed(child_process_data1,
                                       abnormal_termination_info);
 
   // A disconnect should not generate a crash event.
-  provider.BrowserChildProcessHostConnected(child_process_data1);
+  provider.BrowserChildProcessLaunchedAndConnected(child_process_data1);
   provider.BrowserChildProcessHostDisconnected(child_process_data1);
 
   content::ChildProcessData child_process_data2(
       content::PROCESS_TYPE_PPAPI_PLUGIN);
   child_process_data2.name = u"p2";
-  provider.BrowserChildProcessHostConnected(child_process_data2);
+  provider.BrowserChildProcessLaunchedAndConnected(child_process_data2);
   provider.BrowserChildProcessCrashed(child_process_data2,
                                       abnormal_termination_info);
 
   // A kill should generate a crash event
-  provider.BrowserChildProcessHostConnected(child_process_data2);
+  provider.BrowserChildProcessLaunchedAndConnected(child_process_data2);
   provider.BrowserChildProcessKilled(child_process_data2,
                                      abnormal_termination_info);
 
diff --git a/chrome/browser/payments/BUILD.gn b/chrome/browser/payments/BUILD.gn
index 4fff86fe..7d4ce8b3 100644
--- a/chrome/browser/payments/BUILD.gn
+++ b/chrome/browser/payments/BUILD.gn
@@ -22,6 +22,7 @@
     "payment_handler_enable_delegations_browsertest.cc",
     "payment_handler_enforce_full_delegation_browsertest.cc",
     "payment_handler_exploit_browsertest.cc",
+    "payment_handler_install_failed_browsertest.cc",
     "payment_handler_jit_install_with_registered_sw_browsertest.cc",
     "payment_handler_just_in_time_installation_browsertest.cc",
     "payment_handler_ui_browsertest.cc",
diff --git a/chrome/browser/payments/payment_handler_install_failed_browsertest.cc b/chrome/browser/payments/payment_handler_install_failed_browsertest.cc
new file mode 100644
index 0000000..12596bd
--- /dev/null
+++ b/chrome/browser/payments/payment_handler_install_failed_browsertest.cc
@@ -0,0 +1,66 @@
+// 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 <string>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "chrome/test/payments/payment_request_platform_browsertest_base.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace payments {
+namespace {
+
+class PaymentHandlerInstallFailedTest
+    : public PaymentRequestPlatformBrowserTestBase {
+ private:
+  void OnErrorDisplayed() override {
+    PaymentRequestPlatformBrowserTestBase::OnErrorDisplayed();
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(&PaymentHandlerInstallFailedTest::CloseDialog,
+                                  base::Unretained(this)));
+  }
+
+  void CloseDialog() { ASSERT_TRUE(test_controller()->CloseDialog()); }
+};
+
+// When the service worker file is missing, the error message should mention
+// that the payment handler install failed. The metrics should record a failed
+// installation.
+IN_PROC_BROWSER_TEST_F(PaymentHandlerInstallFailedTest, Test) {
+  base::HistogramTester histogram_tester;
+  histogram_tester.ExpectTotalCount(
+      "PaymentRequest.PaymentHandlerInstallSuccess", 0);
+
+  std::string method_name =
+      https_server()->GetURL("a.com", "/paulpay.com/pay").spec();
+  ASSERT_NE('/', method_name[method_name.length() - 1]);
+  NavigateTo("b.com", "/can_make_payment_checker.html");
+  EXPECT_EQ("true", content::EvalJs(
+                        GetActiveWebContents(),
+                        content::JsReplace("canMakePayment($1)", method_name)));
+
+  histogram_tester.ExpectTotalCount(
+      "PaymentRequest.PaymentHandlerInstallSuccess", 0);
+
+  NavigateTo("b.com", "/payment_handler_status.html");
+  EXPECT_EQ("Failed to install the payment handler.",
+            content::EvalJs(GetActiveWebContents(),
+                            content::JsReplace("getStatus($1)", method_name)));
+
+  histogram_tester.ExpectTotalCount(
+      "PaymentRequest.PaymentHandlerInstallSuccess", 1);
+  histogram_tester.ExpectBucketCount(
+      "PaymentRequest.PaymentHandlerInstallSuccess", true, 0);
+  histogram_tester.ExpectBucketCount(
+      "PaymentRequest.PaymentHandlerInstallSuccess", false, 1);
+}
+
+}  // namespace
+}  // namespace payments
diff --git a/chrome/browser/payments/payment_request_security_policy_browsertest.cc b/chrome/browser/payments/payment_request_security_policy_browsertest.cc
index ffce6e2..039c0ea 100644
--- a/chrome/browser/payments/payment_request_security_policy_browsertest.cc
+++ b/chrome/browser/payments/payment_request_security_policy_browsertest.cc
@@ -15,16 +15,33 @@
 
 class PaymentRequestSecurityPolicyBrowsertest
     : public PaymentRequestPlatformBrowserTestBase {
- public:
+ protected:
   void ExpectPaymentRequestCSPViolationRecorded(bool expected) {
     // Navigate away in order to flush use counters.
-    NavigateTo("b.com", "/payment_request_csp_violation.html");
+    ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(),
+                                       GURL(url::kAboutBlankURL)));
     histogram_tester_.ExpectBucketCount(
         "Blink.UseCounter.Features",
         blink::mojom::WebFeature::kPaymentRequestCSPViolation,
         expected ? 1 : 0);
   }
 
+  void BuildPaymentRequest() {
+    ResetEventWaiterForEventSequence(
+        {TestEvent::kCanMakePaymentCalled, TestEvent::kCanMakePaymentReturned});
+
+    // The CSP check happens in buildPaymentRequest. We only call canMakePayment
+    // to ensure the promise resolves before metrics are checked.
+    EXPECT_EQ(false,
+              content::EvalJs(
+                  GetActiveWebContents(),
+                  content::JsReplace(
+                      "buildPaymentRequest($1).canMakePayment()",
+                      https_server()->GetURL("bobpay.com", "/csp-test"))));
+
+    WaitForObservedEvent();
+  }
+
  private:
   base::HistogramTester histogram_tester_;
 };
@@ -33,13 +50,7 @@
 IN_PROC_BROWSER_TEST_F(PaymentRequestSecurityPolicyBrowsertest, CSPViolation) {
   NavigateTo("a.com", "/payment_request_csp_violation.html");
 
-  // The CSP check happens in buildPaymentRequest. We only call canMakePayment
-  // to ensure the promise resolves before metrics are checked.
-  EXPECT_EQ(false, content::EvalJs(
-                       GetActiveWebContents(),
-                       content::JsReplace(
-                           "buildPaymentRequest($1).canMakePayment()",
-                           https_server()->GetURL("bobpay.com", "/csp-test"))));
+  BuildPaymentRequest();
 
   ExpectPaymentRequestCSPViolationRecorded(true);
 }
@@ -48,13 +59,7 @@
 IN_PROC_BROWSER_TEST_F(PaymentRequestSecurityPolicyBrowsertest, CSPAllowAll) {
   NavigateTo("a.com", "/payment_request_csp_allow_all.html");
 
-  // The CSP check happens in buildPaymentRequest. We only call canMakePayment
-  // to ensure the promise resolves before metrics are checked.
-  EXPECT_EQ(false, content::EvalJs(
-                       GetActiveWebContents(),
-                       content::JsReplace(
-                           "buildPaymentRequest($1).canMakePayment()",
-                           https_server()->GetURL("bobpay.com", "/csp-test"))));
+  BuildPaymentRequest();
 
   ExpectPaymentRequestCSPViolationRecorded(false);
 }
@@ -64,13 +69,7 @@
                        CSPAllowSpecific) {
   NavigateTo("a.com", "/payment_request_csp_allow_specific.html");
 
-  // The CSP check happens in buildPaymentRequest. We only call canMakePayment
-  // to ensure the promise resolves before metrics are checked.
-  EXPECT_EQ(false, content::EvalJs(
-                       GetActiveWebContents(),
-                       content::JsReplace(
-                           "buildPaymentRequest($1).canMakePayment()",
-                           https_server()->GetURL("bobpay.com", "/csp-test"))));
+  BuildPaymentRequest();
 
   ExpectPaymentRequestCSPViolationRecorded(false);
 }
diff --git a/chrome/browser/privacy/BUILD.gn b/chrome/browser/privacy/BUILD.gn
index 04f62218..6f3e7ec 100644
--- a/chrome/browser/privacy/BUILD.gn
+++ b/chrome/browser/privacy/BUILD.gn
@@ -11,6 +11,8 @@
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_junit_tests__java_binary",
     "//chrome/android:chrome_test_java",
+    "//chrome/browser/ui/android/omnibox:java",
+    "//chrome/browser/ui/android/omnibox:junit",
   ]
   sources = [
     "java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsBridge.java",
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 e79cb22..bbebee5 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
@@ -1578,9 +1578,8 @@
   ASSERT_TRUE(response_received);
 }
 
-// TODO(http://crbug.com/1177587): Resolve flake and re-enable test.
 IN_PROC_BROWSER_TEST_F(SearchByImageBrowserTest,
-                       DISABLED_LensImageSearchWithValidImage) {
+                       LensImageSearchWithValidImage) {
   static const char kValidImage[] = "/image_search/valid.png";
   SetupAndLoadImagePage(kValidImage);
 
diff --git a/chrome/browser/resources/chromeos/login/oobe.css b/chrome/browser/resources/chromeos/login/oobe.css
index aa278b51..4e44a07 100644
--- a/chrome/browser/resources/chromeos/login/oobe.css
+++ b/chrome/browser/resources/chromeos/login/oobe.css
@@ -62,8 +62,8 @@
 
   /* This size fits 675px screen with docked magnifier and shelf. Basically this
    * is calc(675px * (1 - 1 / 3) - 10px - var(--shelf-area-height-base)) where
-   * 3 is DockedMagnifierControllerImpl::kScreenHeightDivisor
-   * 10 is DockedMagnifierControllerImpl::kSeparatorHeight */
+   * 3 is DockedMagnifierController::kScreenHeightDivisor
+   * 10 is DockedMagnifierController::kSeparatorHeight */
   --oobe-dialog-min-height: 384px;
 
   --oobe-dialog-side-margin: 48px;
diff --git a/chrome/browser/resources/memories/BUILD.gn b/chrome/browser/resources/memories/BUILD.gn
index 3ee6d28..c35346f 100644
--- a/chrome/browser/resources/memories/BUILD.gn
+++ b/chrome/browser/resources/memories/BUILD.gn
@@ -48,7 +48,6 @@
 js_library("cluster") {
   deps = [
     ":page_favicon",
-    ":search_query",
     ":top_visit",
     ":utils",
     "//components/history_clusters/core:mojo_bindings_webui_js",
@@ -80,6 +79,7 @@
 
 js_library("top_visit") {
   deps = [
+    ":search_query",
     ":visit_row",
     "//components/history_clusters/core:mojo_bindings_webui_js",
     "//third_party/polymer/v3_0/components-chromium/iron-collapse:iron-collapse",
diff --git a/chrome/browser/resources/memories/cluster.html b/chrome/browser/resources/memories/cluster.html
index 41a76056..2858cdb 100644
--- a/chrome/browser/resources/memories/cluster.html
+++ b/chrome/browser/resources/memories/cluster.html
@@ -17,28 +17,7 @@
     font-size: 0.875rem;  /* 14px */
     line-height: 20px;
   }
-
-  #queries {
-    display: flex;
-    flex-wrap: wrap;
-  }
-
-  search-query {
-    margin-top: 10px;
-  }
-
-  search-query:not(:last-of-type) {
-    margin-inline-end: 10px;
-  }
 </style>
-<div class="section" hidden="[[!cluster.relatedSearches.length]]">
-  <div class="header">$i18n{relatedSearchesSectionHeader}</div>
-  <div id="queries">
-    <template is="dom-repeat" items="[[cluster.relatedSearches]]">
-      <search-query search-query="[[item]]"></search-query>
-    </template>
-  </div>
-</div>
 <div class="section" hidden="[[!cluster.visits.length]]">
   <div class="header">$i18n{visitsSectionHeader}</div>
   <div id="top-visits">
diff --git a/chrome/browser/resources/memories/cluster.js b/chrome/browser/resources/memories/cluster.js
index b6eb318..0246117 100644
--- a/chrome/browser/resources/memories/cluster.js
+++ b/chrome/browser/resources/memories/cluster.js
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import './page_favicon.js';
-import './search_query.js';
 import './shared_vars.js';
 import './top_visit.js';
 import 'chrome://resources/cr_elements/shared_style_css.m.js';
diff --git a/chrome/browser/resources/memories/top_visit.html b/chrome/browser/resources/memories/top_visit.html
index 0884a03..a57cd50 100644
--- a/chrome/browser/resources/memories/top_visit.html
+++ b/chrome/browser/resources/memories/top_visit.html
@@ -1,5 +1,7 @@
 <style>
   :host {
+    --indentation: 52px;
+    --search-query-margin: 10px;
     display: block;
     padding: 10px 0;
     position: relative;
@@ -28,13 +30,44 @@
     --cr-section-vertical-padding: 0;
   }
 
+  #related-visits,
+  #related-searches {
+    margin-inline-start: var(--indentation);
+  }
+
   #related-visits {
-    margin-inline-start: 52px;
+    margin-bottom: var(--search-query-margin);
   }
 
   #related-visits visit-row {
     padding: 4px 0;
   }
+
+  #related-searches {
+    align-items: center;
+    display: flex;
+    flex-direction: row;
+    margin-top: calc(-1 * var(--search-query-margin));
+  }
+
+  #related-searches-label {
+    color: var(--cr-secondary-text-color);
+    margin-inline-end: 16px;
+    margin-top: var(--search-query-margin);
+  }
+
+  #search-queries {
+    display: flex;
+    flex-wrap: wrap;
+  }
+
+  search-query {
+    margin-top: var(--search-query-margin);
+  }
+
+  search-query:not(:last-of-type) {
+    margin-inline-end: var(--search-query-margin);
+  }
 </style>
 <div id="vertical-line"></div>
 <template is="dom-if" if="[[visit.relatedVisits.length]]">
@@ -48,6 +81,14 @@
         <visit-row visit="[[item]]"></visit-row>
       </template>
     </div>
+    <div id="related-searches" hidden="[[!visit.relatedSearches.length]]">
+      <div id="related-searches-label">$i18n{relatedSearchesLabel}</div>
+      <div id="search-queries">
+        <template is="dom-repeat" items="[[visit.relatedSearches]]">
+          <search-query search-query="[[item]]"></search-query>
+        </template>
+      </div>
+    </div>
   </iron-collapse>
 </template>
 <template is="dom-if" if="[[!visit.relatedVisits.length]]">
diff --git a/chrome/browser/resources/memories/top_visit.js b/chrome/browser/resources/memories/top_visit.js
index bd68d77a..9eefb56 100644
--- a/chrome/browser/resources/memories/top_visit.js
+++ b/chrome/browser/resources/memories/top_visit.js
@@ -6,6 +6,7 @@
 import './visit_row.js';
 import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.m.js';
 import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+import './search_query.js';
 
 import {URLVisit} from '/components/history_clusters/core/history_clusters.mojom-webui.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
index 6cfbf54f..9c6f1d0 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
@@ -32,26 +32,22 @@
           <div class="header-text">$i18n{appManagementPermissionsLabel}</div>
         </div>
         <div class="permission-list indented-permission-block">
-          <template is="dom-if" if="[[showCameraPermissions_]]">
-            <app-management-permission-item
-                id="camera-permission"
-                class="subpermission-row" icon="app-management:camera"
-                sync-permission-manually
-                permission-label="$i18n{appManagementCameraPermissionLabel}"
-                permission-type="CAMERA"
-                on-change="onPermissionChanged_">
-            </app-management-permission-item>
-          </template>
-          <template is="dom-if" if="[[showMicrophonePermissions_]]">
-            <app-management-permission-item
-                id="microphone-permission"
-                class="subpermission-row" icon="app-management:microphone"
-                sync-permission-manually
-                permission-label="$i18n{appManagementMicrophonePermissionLabel}"
-                permission-type="MICROPHONE"
-                on-change="onPermissionChanged_">
-            </app-management-permission-item>
-          </template>
+          <app-management-permission-item
+              id="camera-permission"
+              class="subpermission-row" icon="app-management:camera"
+              sync-permission-manually
+              permission-label="$i18n{appManagementCameraPermissionLabel}"
+              permission-type="CAMERA"
+              on-change="onPermissionChanged_">
+          </app-management-permission-item>
+          <app-management-permission-item
+              id="microphone-permission"
+              class="subpermission-row" icon="app-management:microphone"
+              sync-permission-manually
+              permission-label="$i18n{appManagementMicrophonePermissionLabel}"
+              permission-type="MICROPHONE"
+              on-change="onPermissionChanged_">
+          </app-management-permission-item>
           <app-management-permission-item
               class="subpermission-row" icon="cr:print"
               permission-label="$i18n{appManagementPrintingPermissionLabel}"
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
index efea89b..2eb9bca4c 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
@@ -16,28 +16,6 @@
      */
     app_: Object,
 
-    /**
-     * Whether the camera permissions should be shown.
-     * @private {boolean}
-     */
-    showCameraPermissions_: {
-      type: Boolean,
-      value() {
-        return loadTimeData.getBoolean('showPluginVmCameraPermissions');
-      },
-    },
-
-    /**
-     * Whether the microphone permissions should be shown.
-     * @private {boolean}
-     */
-    showMicrophonePermissions_: {
-      type: Boolean,
-      value() {
-        return loadTimeData.getBoolean('showPluginVmMicrophonePermissions');
-      },
-    },
-
     /** @private {boolean} */
     showDialog_: {
       type: Boolean,
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
index 3454aed..2056139 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
@@ -87,7 +87,8 @@
   getMenuItems(name, value) {
     return settings.input_method_util.getOptionMenuItems(name).map(menuItem => {
       menuItem['selected'] = menuItem['value'] === value;
-      menuItem['label'] = this.i18n(menuItem['name']);
+      menuItem['label'] =
+          menuItem['name'] ? this.i18n(menuItem['name']) : menuItem['value'];
       return menuItem;
     });
   },
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
index 985bcd4..8a080d3 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
@@ -344,6 +344,12 @@
         return 'inputMethodOptionsXkbLayout';
       case OptionType.EDIT_USER_DICT:
         return 'inputMethodOptionsEditUserDict';
+      case OptionType.ZHUYIN_KEYBOARD_LAYOUT:
+        return 'inputMethodOptionsZhuyinKeyboardLayout';
+      case OptionType.ZHUYIN_SELECT_KEYS:
+        return 'inputMethodOptionsZhuyinSelectKeys';
+      case OptionType.ZHUYIN_PAGE_SIZE:
+        return 'inputMethodOptionsZhuyinPageSize';
       default:
         assertNotReached();
     }
@@ -369,6 +375,29 @@
           {value: 'Dvorak', name: 'inputMethodOptionsDvorakKeyboard'},
           {value: 'Colemak', name: 'inputMethodOptionsColemakKeyboard'}
         ];
+      case OptionType.ZHUYIN_KEYBOARD_LAYOUT:
+        return [
+          {value: 'Default', name: 'inputMethodOptionsZhuyinLayoutDefault'},
+          {value: 'IBM', name: 'inputMethodOptionsZhuyinLayoutIBM'},
+          {value: 'Eten', name: 'inputMethodOptionsZhuyinLayoutEten'},
+        ];
+      case OptionType.ZHUYIN_SELECT_KEYS:
+        // Zhuyin select keys correspond to physical keys so are not
+        // translated.
+        return [
+          {value: '1234567890'},
+          {value: 'asdfghjkl;'},
+          {value: 'asdfzxcv89'},
+          {value: 'asdfjkl789'},
+          {value: '1234qweras'},
+        ];
+      case OptionType.ZHUYIN_PAGE_SIZE:
+        // Zhuyin page size is just a number, so is not translated.
+        return [
+          {value: '10'},
+          {value: '9;'},
+          {value: '8'},
+        ];
       default:
         return [];
     }
diff --git a/chrome/browser/resources/tab_search/app.js b/chrome/browser/resources/tab_search/app.js
index 3360330d..9246127 100644
--- a/chrome/browser/resources/tab_search/app.js
+++ b/chrome/browser/resources/tab_search/app.js
@@ -21,7 +21,7 @@
 import {fuzzySearch} from './fuzzy_search.js';
 import {InfiniteList, NO_SELECTION, selectorNavigationKeys} from './infinite_list.js';
 import {ariaLabel, TabData, TabItemType, tokenToString} from './tab_data.js';
-import {Tab, TabGroup, Window} from './tab_search.mojom-webui.js';
+import {RecentlyClosedTab, Tab, TabGroup, Window} from './tab_search.mojom-webui.js';
 import {TabSearchApiProxy, TabSearchApiProxyImpl} from './tab_search_api_proxy.js';
 import {TitleItem} from './title_item.js';
 
@@ -375,7 +375,7 @@
     if (type === TabItemType.OPEN) {
       this.apiProxy_.switchToTab({tabId}, !!this.searchText_, tabIndex);
     } else {
-      this.apiProxy_.openRecentlyClosedTab(tabId);
+      this.apiProxy_.openRecentlyClosedEntry(tabId);
     }
   }
 
@@ -414,7 +414,7 @@
 
   /**
    * @param {!Array<!Window>} newOpenWindows
-   * @param {!Array<!Tab>} recentlyClosedTabs
+   * @param {!Array<!RecentlyClosedTab>} recentlyClosedTabs
    * @param {!Array<!TabGroup>} tabGroups
    * @private
    */
@@ -567,7 +567,7 @@
   }
 
   /**
-   * @param {!Tab} tab
+   * @param {!Tab|!RecentlyClosedTab} tab
    * @param {boolean} inActiveWindow
    * @param {!TabItemType} type
    * @param {!Map<string, !TabGroup>} tabGroupsMap
@@ -631,11 +631,6 @@
     this.searchResultText_ = this.getA11ySearchResultText_();
   }
 
-  /** @return {!Tab} */
-  getSelectedTab_() {
-    return this.filteredOpenTabs_[this.getSelectedIndex()].tab;
-  }
-
   /** @return {string} */
   getSearchTextForTesting() {
     return this.searchText_;
diff --git a/chrome/browser/resources/tab_search/tab_data.js b/chrome/browser/resources/tab_search/tab_data.js
index 256c8dc..b4a7c1ca 100644
--- a/chrome/browser/resources/tab_search/tab_data.js
+++ b/chrome/browser/resources/tab_search/tab_data.js
@@ -4,7 +4,7 @@
 
 import {Token} from 'chrome://resources/mojo/mojo/public/mojom/base/token.mojom-webui.js';
 
-import {Tab, TabGroup} from './tab_search.mojom-webui.js';
+import {RecentlyClosedTab, Tab, TabGroup} from './tab_search.mojom-webui.js';
 
 /** @enum {number} */
 export const TabItemType = {
@@ -19,7 +19,7 @@
  */
 export class TabData {
   constructor() {
-    /** @type {!Tab} */
+    /** @type {!Tab|!RecentlyClosedTab} */
     this.tab;
 
     /** @type {string} */
diff --git a/chrome/browser/resources/tab_search/tab_search_api_proxy.js b/chrome/browser/resources/tab_search/tab_search_api_proxy.js
index 7fdf7c4..53b1e71 100644
--- a/chrome/browser/resources/tab_search/tab_search_api_proxy.js
+++ b/chrome/browser/resources/tab_search/tab_search_api_proxy.js
@@ -28,8 +28,8 @@
   /** @return {Promise<{profileData: ProfileData}>} */
   getProfileData() {}
 
-  /** @param {number} tabId */
-  openRecentlyClosedTab(tabId) {}
+  /** @param {number} id */
+  openRecentlyClosedEntry(id) {}
 
   /**
    * @param {!SwitchToTabInfo} info
@@ -76,8 +76,8 @@
   }
 
   /** @override */
-  openRecentlyClosedTab(tabId) {
-    this.handler.openRecentlyClosedTab(tabId);
+  openRecentlyClosedEntry(tabId) {
+    this.handler.openRecentlyClosedEntry(tabId);
   }
 
   /** @override */
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 441f6cd..8df0394 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -259,12 +259,28 @@
  public:
   typedef security_interstitials::UnsafeResource UnsafeResource;
 
+  class WebContentsObserver : public content::WebContentsObserver {
+   public:
+    WebContentsObserver(ClientSideDetectionHostTestBase* harness,
+                        content::WebContents* contents)
+        : content::WebContentsObserver(contents), harness_(harness) {}
+
+    void RenderFrameCreated(
+        content::RenderFrameHost* render_frame_host) override {
+      harness_->InitTestApi(render_frame_host);
+    }
+
+   private:
+    // The raw pointer is safe because `harness_` owns this.
+    ClientSideDetectionHostTestBase* harness_;
+  };
+
   explicit ClientSideDetectionHostTestBase(bool is_incognito)
       : is_incognito_(is_incognito) {}
 
-  void InitTestApi() {
+  void InitTestApi(content::RenderFrameHost* rfh) {
     service_manager::InterfaceProvider* remote_interfaces =
-        web_contents()->GetMainFrame()->GetRemoteInterfaces();
+        rfh->GetRemoteInterfaces();
 
     service_manager::InterfaceProvider::TestApi test_api(remote_interfaces);
 
@@ -277,6 +293,8 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
 
+    observer_ = std::make_unique<WebContentsObserver>(this, web_contents());
+
     if (is_incognito_) {
       auto incognito_web_contents =
           content::WebContentsTester::CreateTestWebContents(
@@ -288,7 +306,7 @@
     // Initiate the connection to a (pretend) renderer process.
     NavigateAndCommit(GURL("about:blank"));
 
-    InitTestApi();
+    InitTestApi(web_contents()->GetMainFrame());
 
     // Inject service classes.
     csd_service_ = std::make_unique<MockClientSideDetectionService>();
@@ -403,6 +421,7 @@
   const bool is_incognito_;
   signin::IdentityTestEnvironment identity_test_env_;
   base::test::ScopedFeatureList feature_list_;
+  std::unique_ptr<WebContentsObserver> observer_;
 };
 
 class ClientSideDetectionHostTest : public ClientSideDetectionHostTestBase {
@@ -935,9 +954,6 @@
   ExpectPreClassificationChecks(url2, &kFalse, &kFalse, &kFalse, &kFalse,
                                 &kFalse);
   NavigateAndKeepLoading(web_contents(), url2);
-  // Re-override the binder for PhishingDetector because navigation causes
-  // a new web InterfaceProvider to be created
-  InitTestApi();
   WaitAndCheckPreClassificationChecks();
 
   fake_phishing_detector_.CheckMessage(&url2);
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
index ecc1a0c..cc67599e 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
@@ -47,6 +47,10 @@
 
   base::RunLoop run_loop;
 
+  // Ensure that IPCs to set the model have propagated, otherwise they may
+  // interrupt classification.
+  content::RunAllTasksUntilIdle();
+
   content::RenderFrameHost* rfh =
       browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
   mojo::Remote<mojom::PhishingDetector> phishing_detector;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
index 5fce1d5..a2273e3 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/memory_mapped_file.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece_forward.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "chrome/browser/file_util_service.h"
@@ -16,25 +17,47 @@
 #include "chrome/services/file_util/public/cpp/sandboxed_zip_analyzer.h"
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
+#include "net/base/filename_util.h"
+#include "net/base/mime_sniffer.h"
 #include "net/base/mime_util.h"
 
 namespace safe_browsing {
 
 namespace {
 
-std::string GetFileMimeType(const base::FilePath& path) {
-  // TODO(crbug.com/1013252): Obtain a more accurate MimeType by parsing the
-  // file content.
+std::string GetFileMimeType(const base::FilePath& path,
+                            const base::MemoryMappedFile& file) {
+  std::string sniffed_mime_type;
+  bool sniff_found = net::SniffMimeType(
+      base::StringPiece(
+          reinterpret_cast<const char*>(file.data()),
+          std::min(file.length(), static_cast<size_t>(net::kMaxBytesToSniff))),
+      net::FilePathToFileURL(path),
+      /*type_hint*/ std::string(), net::ForceSniffFileUrlsForHtml::kDisabled,
+      &sniffed_mime_type);
+
+  if (sniff_found && !sniffed_mime_type.empty() &&
+      sniffed_mime_type != "text/*" &&
+      sniffed_mime_type != "application/octet-stream") {
+    return sniffed_mime_type;
+  }
+
+  // If the file got a trivial or empty mime type sniff, fall back to using its
+  // extension if possible.
   base::FilePath::StringType ext = path.FinalExtension();
   if (ext.empty())
-    return "";
+    return sniffed_mime_type;
 
   if (ext[0] == FILE_PATH_LITERAL('.'))
     ext = ext.substr(1);
 
-  std::string mime_type;
-  net::GetMimeTypeFromExtension(ext, &mime_type);
-  return mime_type;
+  std::string ext_mime_type;
+  bool ext_found = net::GetMimeTypeFromExtension(ext, &ext_mime_type);
+
+  if (!ext_found || ext_mime_type.empty())
+    return sniffed_mime_type;
+
+  return ext_mime_type;
 }
 
 std::pair<BinaryUploadService::Result, BinaryUploadService::Request::Data>
@@ -62,7 +85,7 @@
   file_data.size = file_size;
   file_data.path = path;
   if (detect_mime_type)
-    file_data.mime_type = GetFileMimeType(path);
+    file_data.mime_type = GetFileMimeType(path, mm_file);
 
   std::unique_ptr<crypto::SecureHash> secure_hash =
       crypto::SecureHash::Create(crypto::SecureHash::SHA256);
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
index e3398e4..7a5f1aad 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
@@ -39,7 +39,7 @@
 // one of multiple values.
 bool IsDocMimeType(const std::string& mime_type) {
   static std::set<std::string> set = {
-      "application/msword",
+      "application/msword", "text/plain",
       // Large files can result in no mimetype being found.
       ""};
   return set.count(mime_type);
@@ -199,7 +199,8 @@
   // printf "Normal file contents" | sha256sum |  tr '[:lower:]' '[:upper:]'
   EXPECT_EQ(data.hash,
             "29644C10BD036866FCFD2BDACFF340DB5DE47A90002D6AB0C42DE6A22C26158B");
-  EXPECT_TRUE(IsDocMimeType(data.mime_type));
+  EXPECT_TRUE(IsDocMimeType(data.mime_type))
+      << data.mime_type << " is not an expected mimetype";
 
   std::string long_contents =
       std::string(BinaryUploadService::kMaxUploadSizeBytes, 'a');
@@ -210,7 +211,8 @@
   // printf "Normal file contents" | sha256sum |  tr '[:lower:]' '[:upper:]'
   EXPECT_EQ(data.hash,
             "4F0E9C6A1A9A90F35B884D0F0E7343459C21060EEFEC6C0F2FA9DC1118DBE5BE");
-  EXPECT_TRUE(IsDocMimeType(data.mime_type));
+  EXPECT_TRUE(IsDocMimeType(data.mime_type))
+      << data.mime_type << " is not an expected mimetype";
 }
 
 TEST_F(FileAnalysisRequestTest, LargeFiles) {
@@ -229,7 +231,8 @@
   // '[:lower:]' '[:upper:]'
   EXPECT_EQ(data.hash,
             "9EB56DB30C49E131459FE735BA6B9D38327376224EC8D5A1233F43A5B4A25942");
-  EXPECT_TRUE(IsDocMimeType(data.mime_type));
+  EXPECT_TRUE(IsDocMimeType(data.mime_type))
+      << data.mime_type << " is not an expected mimetype";
 
   std::string very_large_file_contents(
       2 * BinaryUploadService::kMaxUploadSizeBytes, 'a');
@@ -241,7 +244,8 @@
   // '[:lower:]' '[:upper:]'
   EXPECT_EQ(data.hash,
             "CEE41E98D0A6AD65CC0EC77A2BA50BF26D64DC9007F7F1C7D7DF68B8B71291A6");
-  EXPECT_TRUE(IsDocMimeType(data.mime_type));
+  EXPECT_TRUE(IsDocMimeType(data.mime_type))
+      << data.mime_type << " is not an expected mimetype";
 }
 
 TEST_F(FileAnalysisRequestTest, PopulatesDigest) {
@@ -429,7 +433,8 @@
   EXPECT_EQ(data.hash,
             "29644C10BD036866FCFD2BDACFF340DB5DE47A90002D6AB0C42DE6A22C26158B");
   EXPECT_EQ(request->digest(), data.hash);
-  EXPECT_TRUE(data.mime_type.empty());
+  EXPECT_EQ("text/plain", data.mime_type)
+      << data.mime_type << " is not an expected mimetype";
 }
 
 TEST_F(FileAnalysisRequestTest, UnsupportedFileTypeNoBlock) {
@@ -474,7 +479,8 @@
   EXPECT_EQ(data.hash,
             "29644C10BD036866FCFD2BDACFF340DB5DE47A90002D6AB0C42DE6A22C26158B");
   EXPECT_EQ(request->digest(), data.hash);
-  EXPECT_TRUE(data.mime_type.empty());
+  EXPECT_EQ("text/plain", data.mime_type)
+      << data.mime_type << " is not an expected mimetype";
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/sharing/proto/sms_fetch_message_test_proto3_optional.proto b/chrome/browser/sharing/proto/sms_fetch_message_test_proto3_optional.proto
index 8c4ed2d..377d6d1 100644
--- a/chrome/browser/sharing/proto/sms_fetch_message_test_proto3_optional.proto
+++ b/chrome/browser/sharing/proto/sms_fetch_message_test_proto3_optional.proto
@@ -14,17 +14,19 @@
 
 // Request message to fetch a SMS from a remote device.
 message SmsFetchRequest {
-  // The origin that is requesting the SMS. Remote devices use it to match
-  // against the metadata contained in the received SMS.
+  // The list of origins that is requesting the SMS. Remote devices use it to
+  // match against the metadata contained in the received SMS. At the moment we
+  // expect at most 2 origins in the list when the request is made from a cross
+  // origin iframe. i.e. they represent the top frame and the embedded frame.
   // required
-  string origin = 1;
+  repeated string origins = 1;
 }
 
 // Response message to fetch a SMS from a remote device.
 message SmsFetchResponse {
   // The list of parsed origins of the received SMS.
   // required
-  repeated string origin = 1;
+  repeated string origins = 1;
   // The parsed one time code of the received SMS.
   // required
   string one_time_code = 2;
diff --git a/chrome/browser/sharing/sharing_message_sender_unittest.cc b/chrome/browser/sharing/sharing_message_sender_unittest.cc
index 75aa10a..2990b454 100644
--- a/chrome/browser/sharing/sharing_message_sender_unittest.cc
+++ b/chrome/browser/sharing/sharing_message_sender_unittest.cc
@@ -352,7 +352,7 @@
   std::unique_ptr<syncer::DeviceInfo> device_info = SetupDevice();
 
   chrome_browser_sharing::SharingMessage sent_message;
-  sent_message.mutable_sms_fetch_request()->set_origin("https://a.com");
+  sent_message.mutable_sms_fetch_request()->add_origins("https://a.com");
 
   chrome_browser_sharing::ResponseMessage expected_response_message;
   base::MockCallback<SharingMessageSender::ResponseCallback> mock_callback;
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler.cc b/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
index bb27567..3e1715ea 100644
--- a/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/sms_fetcher.h"
+#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
@@ -28,6 +29,22 @@
 // visible to users.
 static constexpr base::TimeDelta kNotificationDelay =
     base::TimeDelta::FromSeconds(1);
+
+bool DoesMatchOriginList(const std::vector<std::u16string>& origins,
+                         const content::OriginList& origin_list) {
+  if (origins.size() != origin_list.size())
+    return false;
+
+  for (size_t i = 0; i < origins.size(); ++i) {
+    if (origins[i] != url_formatter::FormatOriginForSecurityDisplay(
+                          origin_list[i],
+                          url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace
 
 SmsFetchRequestHandler::SmsFetchRequestHandler(
@@ -50,9 +67,17 @@
   const std::string& client_name =
       device ? device->client_name() : message.sender_device_name();
 
-  auto origin = url::Origin::Create(GURL(message.sms_fetch_request().origin()));
-  auto request = std::make_unique<Request>(this, fetcher_, origin, client_name,
-                                           std::move(done_callback));
+  const google::protobuf::RepeatedPtrField<std::string>& origin_strings =
+      message.sms_fetch_request().origins();
+  if (origin_strings.empty())
+    return;
+
+  std::vector<url::Origin> origin_list;
+  for (const std::string& origin_string : origin_strings)
+    origin_list.push_back(url::Origin::Create(GURL(origin_string)));
+
+  auto request = std::make_unique<Request>(
+      this, fetcher_, origin_list, client_name, std::move(done_callback));
   requests_.insert(std::move(request));
 }
 
@@ -65,9 +90,25 @@
     const std::string& one_time_code,
     const std::string& client_name) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
-  const std::u16string origin = url_formatter::FormatOriginForSecurityDisplay(
-      origin_list[0], url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+  DCHECK(origin_list.size() == 1 || origin_list.size() == 2);
+
+  base::android::ScopedJavaLocalRef<jstring> embedded_origin;
+  base::android::ScopedJavaLocalRef<jstring> top_origin;
+  if (origin_list.size() == 2) {
+    embedded_origin = base::android::ConvertUTF16ToJavaString(
+        env,
+        url_formatter::FormatOriginForSecurityDisplay(
+            origin_list[0], url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
+    top_origin = base::android::ConvertUTF16ToJavaString(
+        env,
+        url_formatter::FormatOriginForSecurityDisplay(
+            origin_list[1], url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
+  } else {
+    top_origin = base::android::ConvertUTF16ToJavaString(
+        env,
+        url_formatter::FormatOriginForSecurityDisplay(
+            origin_list[0], url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS));
+  }
 
   // If there is a notification from a previous request on screen this will
   // overwrite that one with the new origin. In most cases where there's only
@@ -77,25 +118,41 @@
   // handle failures when there are multiple pending origins simultaneously.
   Java_SmsFetcherMessageHandler_showNotification(
       env, base::android::ConvertUTF8ToJavaString(env, one_time_code),
-      base::android::ConvertUTF16ToJavaString(env, origin),
+      top_origin, embedded_origin,
       base::android::ConvertUTF8ToJavaString(env, client_name),
       reinterpret_cast<intptr_t>(this));
 }
 
-void SmsFetchRequestHandler::OnConfirm(JNIEnv* env, jstring j_origin) {
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
-  std::u16string origin =
-      base::android::ConvertJavaStringToUTF16(env, j_origin);
-  auto* request = GetRequest(origin);
+void SmsFetchRequestHandler::OnConfirm(JNIEnv* env,
+                                       jstring j_top_origin,
+                                       jstring j_embedded_origin) {
+  std::vector<std::u16string> origins;
+  if (j_embedded_origin) {
+    std::u16string embedded_origin =
+        base::android::ConvertJavaStringToUTF16(env, j_embedded_origin);
+    origins.push_back(embedded_origin);
+  }
+  std::u16string top_origin =
+      base::android::ConvertJavaStringToUTF16(env, j_top_origin);
+  origins.push_back(top_origin);
+  auto* request = GetRequest(origins);
   DCHECK(request);
   request->SendSuccessMessage();
 }
 
-void SmsFetchRequestHandler::OnDismiss(JNIEnv* env, jstring j_origin) {
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
-  std::u16string origin =
-      base::android::ConvertJavaStringToUTF16(env, j_origin);
-  auto* request = GetRequest(origin);
+void SmsFetchRequestHandler::OnDismiss(JNIEnv* env,
+                                       jstring j_top_origin,
+                                       jstring j_embedded_origin) {
+  std::vector<std::u16string> origins;
+  if (j_embedded_origin) {
+    std::u16string embedded_origin =
+        base::android::ConvertJavaStringToUTF16(env, j_embedded_origin);
+    origins.push_back(embedded_origin);
+  }
+  std::u16string top_origin =
+      base::android::ConvertJavaStringToUTF16(env, j_top_origin);
+  origins.push_back(top_origin);
+  auto* request = GetRequest(origins);
   DCHECK(request);
   // TODO(crbug.com/1015645): We should have a separate catergory for this type
   // of failure.
@@ -103,15 +160,12 @@
 }
 
 SmsFetchRequestHandler::Request* SmsFetchRequestHandler::GetRequest(
-    const std::u16string& origin) {
+    const std::vector<std::u16string>& origins) {
+  // If the request is made from a cross-origin iframe, the origin_list consists
+  // of the embedded frame origin and then the top frame origin.
   for (auto& request : requests_) {
-    const auto& origin_list = request->origin_list();
-    // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
-    if (origin == url_formatter::FormatOriginForSecurityDisplay(
-                      origin_list[0],
-                      url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS)) {
+    if (DoesMatchOriginList(origins, request->origin_list()))
       return request.get();
-    }
   }
   return nullptr;
 }
@@ -123,20 +177,18 @@
 SmsFetchRequestHandler::Request::Request(
     SmsFetchRequestHandler* handler,
     content::SmsFetcher* fetcher,
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     const std::string& client_name,
     SharingMessageHandler::DoneCallback respond_callback)
     : handler_(handler),
       fetcher_(fetcher),
-      origin_list_(content::OriginList{origin}),
+      origin_list_(origin_list),
       client_name_(client_name),
       respond_callback_(std::move(respond_callback)) {
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
   fetcher_->Subscribe(origin_list_, this);
 }
 
 SmsFetchRequestHandler::Request::~Request() {
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
   fetcher_->Unsubscribe(origin_list_, this);
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_SmsFetcherMessageHandler_dismissNotification(env);
@@ -146,8 +198,7 @@
     const content::OriginList& origin_list,
     const std::string& one_time_code,
     content::SmsFetcher::UserConsent consent_requirement) {
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
-  DCHECK_EQ(origin_list[0], origin_list_[0]);
+  DCHECK(origin_list_ == origin_list);
   one_time_code_ = one_time_code;
 
   // Postpones asking for user permission to make sure that the notification is
@@ -163,7 +214,7 @@
 void SmsFetchRequestHandler::Request::SendSuccessMessage() {
   auto response = std::make_unique<chrome_browser_sharing::ResponseMessage>();
   for (const auto& origin : origin_list_)
-    response->mutable_sms_fetch_response()->add_origin(origin.Serialize());
+    response->mutable_sms_fetch_response()->add_origins(origin.Serialize());
   response->mutable_sms_fetch_response()->set_one_time_code(one_time_code_);
 
   std::move(respond_callback_).Run(std::move(response));
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler.h b/chrome/browser/sharing/sms/sms_fetch_request_handler.h
index cad0db8..3a043f4 100644
--- a/chrome/browser/sharing/sms/sms_fetch_request_handler.h
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler.h
@@ -38,8 +38,8 @@
   virtual void AskUserPermission(const content::OriginList&,
                                  const std::string& one_time_code,
                                  const std::string& client_name);
-  virtual void OnConfirm(JNIEnv*, jstring origin);
-  virtual void OnDismiss(JNIEnv*, jstring origin);
+  virtual void OnConfirm(JNIEnv*, jstring top_origin, jstring embedded_origin);
+  virtual void OnDismiss(JNIEnv*, jstring top_origin, jstring embedded_origin);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(SmsFetchRequestHandlerTest, Basic);
@@ -57,7 +57,7 @@
    public:
     Request(SmsFetchRequestHandler* handler,
             content::SmsFetcher* fetcher,
-            const url::Origin& origin,
+            const std::vector<url::Origin>& origin_list,
             const std::string& client_name,
             SharingMessageHandler::DoneCallback respond_callback);
     ~Request() override;
@@ -84,7 +84,8 @@
   };
 
   void RemoveRequest(Request* Request);
-  Request* GetRequest(const std::u16string& origin);
+  Request* GetRequest(const std::vector<std::u16string>& origins);
+
   base::WeakPtr<SmsFetchRequestHandler> GetWeakPtr();
 
   // |device_source_| is owned by |SharingService| which also transitively owns
diff --git a/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc b/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc
index f751dc7b..031f2de 100644
--- a/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc
+++ b/chrome/browser/sharing/sms/sms_fetch_request_handler_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/sharing/sms/sms_fetch_request_handler.h"
+
 #include <string>
 
 #include "base/android/jni_android.h"
@@ -83,7 +84,15 @@
 
 SharingMessage CreateRequest(const std::string& origin) {
   SharingMessage message;
-  message.mutable_sms_fetch_request()->set_origin(origin);
+  message.mutable_sms_fetch_request()->add_origins(origin);
+  return message;
+}
+
+SharingMessage CreateRequestWithMultipleOrigins(
+    const std::vector<std::string>& origins) {
+  SharingMessage message;
+  for (const auto& origin : origins)
+    message.mutable_sms_fetch_request()->add_origins(origin);
   return message;
 }
 
@@ -118,7 +127,7 @@
 
   subscriber->OnReceive(content::OriginList{url::Origin::Create(GURL(origin))},
                         "123", SmsFetcher::UserConsent::kNotObtained);
-  handler.OnConfirm(env, j_origin.obj());
+  handler.OnConfirm(env, j_origin.obj(), nullptr);
   loop.Run();
 }
 
@@ -173,12 +182,12 @@
 
   request2->OnReceive(content::OriginList{url::Origin::Create(GURL(origin2))},
                       "2", SmsFetcher::UserConsent::kNotObtained);
-  handler.OnConfirm(env, j_origin2.obj());
+  handler.OnConfirm(env, j_origin2.obj(), nullptr);
   loop2.Run();
 
   request1->OnReceive(content::OriginList{url::Origin::Create(GURL(origin1))},
                       "1", SmsFetcher::UserConsent::kNotObtained);
-  handler.OnConfirm(env, j_origin1.obj());
+  handler.OnConfirm(env, j_origin1.obj(), nullptr);
   loop1.Run();
 }
 
@@ -251,7 +260,7 @@
 
   subscriber->OnReceive(content::OriginList{url::Origin::Create(GURL(origin))},
                         "123", SmsFetcher::UserConsent::kNotObtained);
-  handler.OnConfirm(env, j_origin.obj());
+  handler.OnConfirm(env, j_origin.obj(), nullptr);
   loop.Run();
 }
 
@@ -286,6 +295,101 @@
 
   subscriber->OnReceive(content::OriginList{url::Origin::Create(GURL(origin))},
                         "123", SmsFetcher::UserConsent::kNotObtained);
-  handler.OnDismiss(env, j_origin.obj());
+  handler.OnDismiss(env, j_origin.obj(), nullptr);
+  loop.Run();
+}
+
+TEST(SmsFetchRequestHandlerTest, EmbeddedFrameConfirm) {
+  StrictMock<MockSmsFetcher> fetcher;
+  MockSmsFetchRequestHandler handler(&fetcher);
+  const std::string top_origin = "https://top.com";
+  const std::string embedded_origin = "https://embedded.com";
+  std::vector<std::string> origins{embedded_origin, top_origin};
+  SharingMessage message = CreateRequestWithMultipleOrigins(origins);
+  JNIEnv* env = base::android::AttachCurrentThread();
+  const std::u16string formatted_top_origin =
+      url_formatter::FormatOriginForSecurityDisplay(
+          url::Origin::Create(GURL(top_origin)),
+          url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+  base::android::ScopedJavaLocalRef<jstring> j_top_origin =
+      base::android::ConvertUTF16ToJavaString(env, formatted_top_origin);
+
+  const std::u16string formatted_embedded_origin =
+      url_formatter::FormatOriginForSecurityDisplay(
+          url::Origin::Create(GURL(embedded_origin)),
+          url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+  base::android::ScopedJavaLocalRef<jstring> j_embedded_origin =
+      base::android::ConvertUTF16ToJavaString(env, formatted_embedded_origin);
+
+  base::RunLoop loop;
+
+  SmsFetcher::Subscriber* subscriber;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&subscriber));
+  EXPECT_CALL(fetcher, Unsubscribe(_, _));
+
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&](std::unique_ptr<ResponseMessage> response) {
+        EXPECT_TRUE(response->has_sms_fetch_response());
+        EXPECT_EQ("123", response->sms_fetch_response().one_time_code());
+        const auto& origin_strings = response->sms_fetch_response().origins();
+        EXPECT_EQ(embedded_origin, origin_strings[0]);
+        EXPECT_EQ(top_origin, origin_strings[1]);
+        loop.Quit();
+      }));
+
+  content::OriginList origin_list;
+  origin_list.push_back(url::Origin::Create(GURL(embedded_origin)));
+  origin_list.push_back(url::Origin::Create(GURL(top_origin)));
+  subscriber->OnReceive(origin_list, "123",
+                        SmsFetcher::UserConsent::kNotObtained);
+  handler.OnConfirm(env, j_top_origin.obj(), j_embedded_origin.obj());
+  loop.Run();
+}
+
+TEST(SmsFetchRequestHandlerTest, EmbeddedFrameDismiss) {
+  StrictMock<MockSmsFetcher> fetcher;
+  MockSmsFetchRequestHandler handler(&fetcher);
+  const std::string top_origin = "https://top.com";
+  const std::string embedded_origin = "https://embedded.com";
+  std::vector<std::string> origins{embedded_origin, top_origin};
+  SharingMessage message = CreateRequestWithMultipleOrigins(origins);
+  JNIEnv* env = base::android::AttachCurrentThread();
+  const std::u16string formatted_top_origin =
+      url_formatter::FormatOriginForSecurityDisplay(
+          url::Origin::Create(GURL(top_origin)),
+          url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+  base::android::ScopedJavaLocalRef<jstring> j_top_origin =
+      base::android::ConvertUTF16ToJavaString(env, formatted_top_origin);
+
+  const std::u16string formatted_embedded_origin =
+      url_formatter::FormatOriginForSecurityDisplay(
+          url::Origin::Create(GURL(embedded_origin)),
+          url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
+  base::android::ScopedJavaLocalRef<jstring> j_embedded_origin =
+      base::android::ConvertUTF16ToJavaString(env, formatted_embedded_origin);
+
+  base::RunLoop loop;
+
+  SmsFetcher::Subscriber* subscriber;
+  EXPECT_CALL(fetcher, Subscribe(_, _)).WillOnce(SaveArg<1>(&subscriber));
+  EXPECT_CALL(fetcher, Unsubscribe(_, _));
+
+  handler.OnMessage(
+      message,
+      BindLambdaForTesting([&](std::unique_ptr<ResponseMessage> response) {
+        EXPECT_TRUE(response->has_sms_fetch_response());
+        EXPECT_EQ(content::SmsFetchFailureType::kPromptCancelled,
+                  static_cast<content::SmsFetchFailureType>(
+                      response->sms_fetch_response().failure_type()));
+        loop.Quit();
+      }));
+
+  content::OriginList origin_list;
+  origin_list.push_back(url::Origin::Create(GURL(embedded_origin)));
+  origin_list.push_back(url::Origin::Create(GURL(top_origin)));
+  subscriber->OnReceive(origin_list, "123",
+                        SmsFetcher::UserConsent::kNotObtained);
+  handler.OnDismiss(env, j_top_origin.obj(), j_embedded_origin.obj());
   loop.Run();
 }
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher.cc b/chrome/browser/sharing/sms/sms_remote_fetcher.cc
index 4a11f53b..5317521 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher.cc
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher.cc
@@ -14,7 +14,7 @@
 
 base::OnceClosure FetchRemoteSms(
     content::WebContents* web_contents,
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                             absl::optional<std::string>,
                             absl::optional<content::SmsFetchFailureType>)>
@@ -35,7 +35,7 @@
 #if !defined(OS_ANDROID)
   auto* ui_controller =
       SmsRemoteFetcherUiController::GetOrCreateFromWebContents(web_contents);
-  return ui_controller->FetchRemoteSms(origin, std::move(callback));
+  return ui_controller->FetchRemoteSms(origin_list, std::move(callback));
 #else
   std::move(callback).Run(absl::nullopt, absl::nullopt, absl::nullopt);
   return base::NullCallback();
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher.h b/chrome/browser/sharing/sms/sms_remote_fetcher.h
index 53ef16ba..2cbe6ac 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher.h
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher.h
@@ -26,7 +26,7 @@
 // Returns a null callback if fetching from a remote device is disabled.
 base::OnceClosure FetchRemoteSms(
     content::WebContents* web_contents,
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                             absl::optional<std::string>,
                             absl::optional<content::SmsFetchFailureType>)>);
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.cc b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.cc
index 647b7670..0ecffe6b 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.cc
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.cc
@@ -98,7 +98,7 @@
                                 response->sms_fetch_response().failure_type()));
     return;
   }
-  auto origin_strings = response->sms_fetch_response().origin();
+  auto origin_strings = response->sms_fetch_response().origins();
   std::vector<url::Origin> origin_list;
   for (const std::string& origin_string : origin_strings)
     origin_list.push_back(url::Origin::Create(GURL(origin_string)));
@@ -109,7 +109,7 @@
 }
 
 base::OnceClosure SmsRemoteFetcherUiController::FetchRemoteSms(
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     OnRemoteCallback callback) {
   SharingService::SharingDeviceList devices = GetDevices();
 
@@ -127,7 +127,8 @@
   last_device_name_ = device->client_name();
   chrome_browser_sharing::SharingMessage request;
 
-  request.mutable_sms_fetch_request()->set_origin(origin.Serialize());
+  for (const url::Origin& origin : origin_list)
+    request.mutable_sms_fetch_request()->add_origins(origin.Serialize());
 
   return SendMessageToDevice(
       *device.get(), blink::kWebOTPRequestTimeout, std::move(request),
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h
index 974eea2..2819fca 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h
@@ -61,7 +61,7 @@
       SharingSendMessageResult result,
       std::unique_ptr<chrome_browser_sharing::ResponseMessage> response);
 
-  base::OnceClosure FetchRemoteSms(const url::Origin& origin,
+  base::OnceClosure FetchRemoteSms(const std::vector<url::Origin>& origin_list,
                                    OnRemoteCallback callback);
 
  protected:
diff --git a/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc b/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc
index fde6f0a..baadc9b 100644
--- a/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc
+++ b/chrome/browser/sharing/sms/sms_remote_fetcher_unittest.cc
@@ -56,7 +56,7 @@
   base::RunLoop loop;
 
   FetchRemoteSms(
-      web_contents.get(), GetOriginForURL("a.com"),
+      web_contents.get(), std::vector<url::Origin>{GetOriginForURL("a.com")},
       BindLambdaForTesting(
           [&loop](absl::optional<std::vector<url::Origin>>,
                   absl::optional<std::string> result,
@@ -88,7 +88,7 @@
   base::RunLoop loop;
 
   FetchRemoteSms(
-      web_contents.get(), GetOriginForURL("a.com"),
+      web_contents.get(), std::vector<url::Origin>{GetOriginForURL("a.com")},
       BindLambdaForTesting(
           [&loop](absl::optional<std::vector<url::Origin>>,
                   absl::optional<std::string> result,
@@ -134,7 +134,7 @@
       }));
 
   FetchRemoteSms(
-      web_contents.get(), GetOriginForURL("a.com"),
+      web_contents.get(), std::vector<url::Origin>{GetOriginForURL("a.com")},
       BindLambdaForTesting(
           [&loop](absl::optional<std::vector<url::Origin>>,
                   absl::optional<std::string> result,
@@ -179,7 +179,7 @@
       }));
 
   FetchRemoteSms(
-      web_contents.get(), GetOriginForURL("a.com"),
+      web_contents.get(), std::vector<url::Origin>{GetOriginForURL("a.com")},
       BindLambdaForTesting(
           [&loop](absl::optional<std::vector<url::Origin>>,
                   absl::optional<std::string> result,
@@ -224,7 +224,7 @@
       }));
 
   base::OnceClosure cancel_callback = FetchRemoteSms(
-      web_contents.get(), GetOriginForURL("a.com"),
+      web_contents.get(), std::vector<url::Origin>{GetOriginForURL("a.com")},
       BindLambdaForTesting(
           [&loop](absl::optional<std::vector<url::Origin>>,
                   absl::optional<std::string> one_time_code,
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
index 78bd5da..5b08ad40 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
@@ -127,7 +127,7 @@
      */
     @VisibleForTesting
     protected CriticalPersistedTabData(
-            Tab tab, byte[] data, PersistedTabDataStorage storage, String persistedTabDataId) {
+            Tab tab, ByteBuffer data, PersistedTabDataStorage storage, String persistedTabDataId) {
         super(tab, storage, persistedTabDataId);
         deserializeAndLog(data);
     }
@@ -167,7 +167,7 @@
      * @return serialized {@link CriticalPersistedTabData}
      * TODO(crbug.com/1119452) rethink CriticalPersistedTabData contract
      */
-    public static byte[] restore(int tabId, boolean isIncognito) {
+    public static ByteBuffer restore(int tabId, boolean isIncognito) {
         PersistedTabDataConfiguration config =
                 PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, isIncognito);
         return config.getStorage().restore(tabId, config.getId());
@@ -179,7 +179,7 @@
      * @param isIncognito true if the {@link Tab} is incognito
      * @param callback the serialized {@link CriticalPersistedTabData} is passed back in
      */
-    public static void restore(int tabId, boolean isIncognito, Callback<byte[]> callback) {
+    public static void restore(int tabId, boolean isIncognito, Callback<ByteBuffer> callback) {
         PersistedTabDataConfiguration config =
                 PersistedTabDataConfiguration.get(CriticalPersistedTabData.class, isIncognito);
         config.getStorage().restore(tabId, config.getId(), callback);
@@ -191,7 +191,7 @@
      * @param isCriticalPersistedTabDataEnabled true if CriticalPersistedData is enabled
      * as the storage/retrieval method
      */
-    public static void build(Tab tab, byte[] serialized, boolean isStorageRetrievalEnabled) {
+    public static void build(Tab tab, ByteBuffer serialized, boolean isStorageRetrievalEnabled) {
         CriticalPersistedTabData res = PersistedTabData.build(tab, (data, storage, id) -> {
             return new CriticalPersistedTabData(tab, data, storage, id);
         }, serialized, CriticalPersistedTabData.class);
@@ -208,7 +208,7 @@
     }
 
     @Override
-    boolean deserialize(@Nullable byte[] bytes) {
+    boolean deserialize(@Nullable ByteBuffer bytes) {
         try (TraceEvent e = TraceEvent.scoped("CriticalPersistedTabData.Deserialize")) {
             CriticalPersistedTabDataProto criticalPersistedTabDataProto =
                     CriticalPersistedTabDataProto.parseFrom(bytes);
@@ -364,6 +364,7 @@
         }
     }
 
+    // TODO(crbug.com/1220678) Change PersistedTabData saves to use ByteBuffer instead of byte[]
     @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
     @Override
     public Supplier<byte[]> getSerializeSupplier() {
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java
index c2331ee..0daf61522 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/EncryptedFilePersistedTabDataStorage.java
@@ -23,6 +23,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.Locale;
 
 import javax.crypto.Cipher;
@@ -63,13 +64,13 @@
 
     @MainThread
     @Override
-    public void restore(int tabId, String dataId, Callback<byte[]> callback) {
+    public void restore(int tabId, String dataId, Callback<ByteBuffer> callback) {
         addStorageRequestAndProcessNext(new EncryptedFileRestoreRequest(tabId, dataId, callback));
     }
 
     @MainThread
     @Override
-    public byte[] restore(int tabId, String dataId) {
+    public ByteBuffer restore(int tabId, String dataId) {
         return new EncryptedFileRestoreRequest(tabId, dataId, null).executeSyncTask();
     }
 
@@ -159,12 +160,12 @@
          * @param callback - callback to return the retrieved serialized
          * {@link PersistedTabData} in
          */
-        EncryptedFileRestoreRequest(int tabId, String dataId, Callback<byte[]> callback) {
+        EncryptedFileRestoreRequest(int tabId, String dataId, Callback<ByteBuffer> callback) {
             super(tabId, dataId, callback);
         }
 
         @Override
-        public byte[] executeSyncTask() {
+        public ByteBuffer executeSyncTask() {
             Cipher cipher = CipherFactory.getInstance().getCipher(Cipher.DECRYPT_MODE);
             if (cipher == null) {
                 Log.e(TAG,
@@ -216,7 +217,7 @@
             }
             RecordHistogram.recordBooleanHistogram(
                     "Tabs.PersistedTabData.Storage.Restore." + getUmaTag(), success);
-            return res;
+            return res == null ? null : ByteBuffer.wrap(res);
         }
     }
 }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java
index cf854074..f2c8e97 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/FilePersistedTabDataStorage.java
@@ -32,6 +32,7 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.Locale;
 
@@ -97,13 +98,13 @@
 
     @MainThread
     @Override
-    public void restore(int tabId, String dataId, Callback<byte[]> callback) {
+    public void restore(int tabId, String dataId, Callback<ByteBuffer> callback) {
         addStorageRequestAndProcessNext(new FileRestoreRequest(tabId, dataId, callback));
     }
 
     @MainThread
     @Override
-    public byte[] restore(int tabId, String dataId) {
+    public ByteBuffer restore(int tabId, String dataId) {
         return new FileRestoreRequest(tabId, dataId, null).executeSyncTask();
     }
 
@@ -352,8 +353,8 @@
     /**
      * Request to restore saved serialized {@link PersistedTabData}
      */
-    protected class FileRestoreRequest extends StorageRequest<byte[]> {
-        protected Callback<byte[]> mCallback;
+    protected class FileRestoreRequest extends StorageRequest<ByteBuffer> {
+        protected Callback<ByteBuffer> mCallback;
 
         /**
          * @param tabId identifier for the {@link Tab}
@@ -361,13 +362,13 @@
          * @param callback - callback to return the retrieved serialized
          * {@link PersistedTabData} in
          */
-        FileRestoreRequest(int tabId, String dataId, Callback<byte[]> callback) {
+        FileRestoreRequest(int tabId, String dataId, Callback<ByteBuffer> callback) {
             super(tabId, dataId);
             mCallback = callback;
         }
 
         @Override
-        public byte[] executeSyncTask() {
+        public ByteBuffer executeSyncTask() {
             boolean success = false;
             byte[] res = null;
             try {
@@ -394,19 +395,19 @@
             }
             RecordHistogram.recordBooleanHistogram(
                     "Tabs.PersistedTabData.Storage.Restore." + getUmaTag(), success);
-            return res;
+            return res == null ? null : ByteBuffer.wrap(res);
         }
 
         @Override
         public AsyncTask getAsyncTask() {
-            return new AsyncTask<byte[]>() {
+            return new AsyncTask<ByteBuffer>() {
                 @Override
-                protected byte[] doInBackground() {
+                protected ByteBuffer doInBackground() {
                     return executeSyncTask();
                 }
 
                 @Override
-                protected void onPostExecute(byte[] res) {
+                protected void onPostExecute(ByteBuffer res) {
                     PostTask.runOrPostTask(
                             UiThreadTaskTraits.DEFAULT, () -> { mCallback.onResult(res); });
                     processNextItemOnQueue();
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
index 23193648..93b078f 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorage.java
@@ -11,6 +11,7 @@
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.profiles.Profile;
 
+import java.nio.ByteBuffer;
 import java.util.Locale;
 
 /**
@@ -51,8 +52,9 @@
 
     @MainThread
     @Override
-    public void restore(int tabId, String dataId, Callback<byte[]> callback) {
-        mPersistedDataStorage.load(getKey(tabId, dataId), callback);
+    public void restore(int tabId, String dataId, Callback<ByteBuffer> callback) {
+        mPersistedDataStorage.load(getKey(tabId, dataId),
+                (res) -> { callback.onResult(res == null ? null : ByteBuffer.wrap(res)); });
     }
 
     /**
@@ -62,7 +64,7 @@
     @Deprecated
     @MainThread
     @Override
-    public byte[] restore(int tabId, String dataId) {
+    public ByteBuffer restore(int tabId, String dataId) {
         assert false : "Synchronous restore is not supported for LevelDBPersistedTabDataStorage";
         return null;
     }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabData.java
index 2eec6ec..fa46db6 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabData.java
@@ -29,7 +29,8 @@
         mField = field;
     }
 
-    private MockPersistedTabData(Tab tab, byte[] data, PersistedTabDataStorage storage, String id) {
+    private MockPersistedTabData(
+            Tab tab, ByteBuffer data, PersistedTabDataStorage storage, String id) {
         super(tab, storage, id);
         deserializeAndLog(data);
     }
@@ -71,8 +72,8 @@
     }
 
     @Override
-    public boolean deserialize(byte[] data) {
-        mField = ByteBuffer.wrap(data).getInt();
+    public boolean deserialize(ByteBuffer data) {
+        mField = data.getInt();
         return true;
     }
 
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabDataStorage.java
index 9f6673c..03b1eaa 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/MockPersistedTabDataStorage.java
@@ -9,6 +9,7 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -30,9 +31,12 @@
     }
 
     @Override
-    public void restore(int tabId, String tabDataId, Callback<byte[]> callback) {
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT,
-                () -> { callback.onResult(mStorage.get(getKey(tabId))); });
+    public void restore(int tabId, String tabDataId, Callback<ByteBuffer> callback) {
+        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
+            callback.onResult(mStorage.get(getKey(tabId)) == null
+                            ? null
+                            : ByteBuffer.wrap(mStorage.get(getKey(tabId))));
+        });
         if (mSemaphore != null) {
             mSemaphore.release();
         }
@@ -40,7 +44,7 @@
 
     // Unused
     @Override
-    public byte[] restore(int tabId, String tabDataId) {
+    public ByteBuffer restore(int tabId, String tabDataId) {
         return null;
     }
 
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
index d8d1ded5b5..6e55865 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabData.java
@@ -20,6 +20,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -28,8 +29,7 @@
 
 /**
  * PersistedTabData is Tab data persisted across restarts
- * A constructor of taking a Tab and a byte[] (serialized
- * {@link PersistedTabData}, PersistedTabDataStorage and
+ * A constructor of taking a Tab, a PersistedTabDataStorage and
  * PersistedTabDataID (identifier for {@link PersistedTabData}
  * in storage) is required as reflection is used to build
  * the object after acquiring the serialized object from storage.
@@ -69,7 +69,7 @@
      * @return deserialized {@link PersistedTabData}
      */
     protected static <T extends PersistedTabData> T build(
-            Tab tab, PersistedTabDataFactory<T> factory, byte[] data, Class<T> clazz) {
+            Tab tab, PersistedTabDataFactory<T> factory, ByteBuffer data, Class<T> clazz) {
         PersistedTabDataConfiguration config =
                 PersistedTabDataConfiguration.get(clazz, tab.isIncognito());
         T persistedTabData = factory.create(data, config.getStorage(), config.getId());
@@ -268,9 +268,9 @@
      * assign to fields in {@link PersistedTabData}
      * @param bytes serialized PersistedTabData
      */
-    abstract boolean deserialize(@Nullable byte[] bytes);
+    abstract boolean deserialize(@Nullable ByteBuffer bytes);
 
-    protected void deserializeAndLog(@Nullable byte[] bytes) {
+    protected void deserializeAndLog(@Nullable ByteBuffer bytes) {
         boolean success;
         try (TraceEvent e = TraceEvent.scoped("PersistedTabData.Deserialize")) {
             success = deserialize(bytes);
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataFactory.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataFactory.java
index 260bc3da..2605fe7 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataFactory.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataFactory.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.tab.state;
 
+import java.nio.ByteBuffer;
+
 /**
  * Creates a {@link PersistedTabData}
  * @param <T> {@link PersistedTabData} being created
@@ -14,5 +16,5 @@
      * @param storage storage method {@link PersistedTabDataStorage} for {@link PersistedTabData}
      * @param id identifier for {@link PersistedTabData} in storage
      */
-    T create(byte[] data, PersistedTabDataStorage storage, String id);
+    T create(ByteBuffer data, PersistedTabDataStorage storage, String id);
 }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorage.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorage.java
index 8e3f3f0..db12bde1 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorage.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/PersistedTabDataStorage.java
@@ -7,6 +7,8 @@
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.Supplier;
 
+import java.nio.ByteBuffer;
+
 /**
  * Storage for {@link PersistedTabData}
  */
@@ -23,14 +25,14 @@
      * @param tabDataId unique identifier representing the type of {@link PersistedTabData}
      * @param callback to pass back the seraizliaed {@link PersistedTabData} in
      */
-    void restore(int tabId, String tabDataId, Callback<byte[]> callback);
+    void restore(int tabId, String tabDataId, Callback<ByteBuffer> callback);
 
     /**
      * @param tabId identifier for the {@link Tab}
      * @param tabDataId unique identifier representing the type of {@link PersistedTabData}
      * @return serialized {@link PersitsedTabData}
      */
-    byte[] restore(int tabId, String tabDataId);
+    ByteBuffer restore(int tabId, String tabDataId);
 
     /**
      * @param tabId identifier for the {@link Tab}
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
index 8dda202..f0d6f8565 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
@@ -37,6 +37,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
@@ -185,7 +186,7 @@
 
     @VisibleForTesting
     protected ShoppingPersistedTabData(
-            Tab tab, byte[] data, PersistedTabDataStorage storage, String persistedTabDataId) {
+            Tab tab, ByteBuffer data, PersistedTabDataStorage storage, String persistedTabDataId) {
         super(tab, storage, persistedTabDataId);
         deserializeAndLog(data);
         setupPersistence(tab);
@@ -617,7 +618,7 @@
     }
 
     @Override
-    public boolean deserialize(@Nullable byte[] bytes) {
+    public boolean deserialize(@Nullable ByteBuffer bytes) {
         // TODO(crbug.com/1135573) add in metrics for serialize and deserialize
         // Do not attempt to deserialize if the bytes are null
         if (bytes == null) {
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/StorePersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/StorePersistedTabData.java
index 0dcf15fb..1c36a9e 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/StorePersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/StorePersistedTabData.java
@@ -20,6 +20,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.proto.StorePersistedTabData.StorePersistedTabDataProto;
 
+import java.nio.ByteBuffer;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
@@ -82,7 +83,7 @@
      * @param persistedTabDataId id for {@link StorePersistedTabData}
      */
     protected StorePersistedTabData(
-            Tab tab, byte[] data, PersistedTabDataStorage storage, String persistedTabDataId) {
+            Tab tab, ByteBuffer data, PersistedTabDataStorage storage, String persistedTabDataId) {
         super(tab, storage, persistedTabDataId);
     }
 
@@ -244,7 +245,7 @@
     }
 
     @Override
-    boolean deserialize(@Nullable byte[] bytes) {
+    boolean deserialize(@Nullable ByteBuffer bytes) {
         if (bytes == null) {
             return false;
         }
diff --git a/chrome/browser/tab_contents/view_source_browsertest.cc b/chrome/browser/tab_contents/view_source_browsertest.cc
index db9e5699..5b70222 100644
--- a/chrome/browser/tab_contents/view_source_browsertest.cc
+++ b/chrome/browser/tab_contents/view_source_browsertest.cc
@@ -5,6 +5,7 @@
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -27,6 +28,7 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/prerender_test_util.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/public/test/url_loader_interceptor.h"
@@ -762,3 +764,59 @@
       &response));
   EXPECT_EQ("vertical-scroll", response);
 }
+
+namespace {
+
+class ViewSourcePrerenderTest : public ViewSourceTest {
+ protected:
+  content::test::PrerenderTestHelper& prerender_test_helper() {
+    return prerender_test_helper_;
+  }
+
+  content::WebContents* target() const { return target_; }
+  void set_target(content::WebContents* target) { target_ = target; }
+
+  void SetUpOnMainThread() override {
+    ViewSourceTest::SetUpOnMainThread();
+    prerender_test_helper().SetUpOnMainThread(embedded_test_server());
+  }
+
+ private:
+  content::test::PrerenderTestHelper prerender_test_helper_{
+      base::BindRepeating(&ViewSourcePrerenderTest::target,
+                          base::Unretained(this))};
+
+  // The WebContents which is expected to request prerendering.
+  content::WebContents* target_ = nullptr;
+};
+
+// A frame in a prerendered page should be able to have its source viewed, like
+// any other. There is currently no UI for this, but in principle it should
+// work.
+IN_PROC_BROWSER_TEST_F(ViewSourcePrerenderTest, ViewSourceForPrerender) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL referrer_url = embedded_test_server()->GetURL("/title1.html");
+  GURL prerender_url = embedded_test_server()->GetURL("/title2.html");
+  content::RenderFrameHost* referrer_frame =
+      ui_test_utils::NavigateToURL(browser(), referrer_url);
+  set_target(content::WebContents::FromRenderFrameHost(referrer_frame));
+
+  prerender_test_helper().AddPrerender(prerender_url);
+  int host_id = prerender_test_helper().GetHostForUrl(prerender_url);
+  content::RenderFrameHost* prerender_frame =
+      prerender_test_helper().GetPrerenderedMainFrameHost(host_id);
+  EXPECT_TRUE(prerender_frame);
+
+  content::WebContentsAddedObserver view_source_contents_observer;
+  prerender_frame->ViewSource();
+  content::WebContents* view_source_contents =
+      view_source_contents_observer.GetWebContents();
+  EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+  EXPECT_EQ(view_source_contents->GetLastCommittedURL(),
+            GURL(base::StrCat(
+                {content::kViewSourceScheme, ":", prerender_url.spec()})));
+  EXPECT_THAT(base::UTF16ToUTF8(view_source_contents->GetTitle()),
+              HasSubstr(content::kViewSourceScheme));
+}
+
+}  // namespace
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
index dcf2756..bd0bec3 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
@@ -16,6 +16,8 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /**
  * Creates Tabs.  If the TabCreator creates Tabs asynchronously, null pointers will be returned
  * everywhere instead of a Tab.
@@ -48,8 +50,8 @@
      * @param isIncognito if the {@link Tab} is incognito or not
      * @param index    The index for where to place the tab.
      */
-    public abstract Tab createFrozenTab(TabState state, byte[] serializedCriticalPersistedTabData,
-            int id, boolean isIncognito, int index);
+    public abstract Tab createFrozenTab(TabState state,
+            ByteBuffer serializedCriticalPersistedTabData, int id, boolean isIncognito, int index);
 
     /**
      * Creates a new tab and loads the specified URL in it. This is a convenience method for
diff --git a/chrome/browser/thumbnail/generator/BUILD.gn b/chrome/browser/thumbnail/generator/BUILD.gn
index 4ae1ae2..9d49d84 100644
--- a/chrome/browser/thumbnail/generator/BUILD.gn
+++ b/chrome/browser/thumbnail/generator/BUILD.gn
@@ -175,9 +175,6 @@
       "//ui/gfx",
     ]
 
-    sources = [
-      "android/thumbnail_media_parser_bridge.cc",
-      "android/thumbnail_media_parser_bridge.h",
-    ]
+    sources = [ "android/thumbnail_media_parser_bridge.cc" ]
   }
 }
diff --git a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java
index 3a1f09d..a65da75d 100644
--- a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java
+++ b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java
@@ -8,50 +8,27 @@
 import org.chromium.base.annotations.NativeMethods;
 
 /**
- * A JNI bridge that owns a native side ThumbnailMediaParser, which parses media file safely in an
+ * A JNI bridge for testing native ThumbnailMediaParser, which parses media file safely in an
  * utility process.
  */
 public class ThumbnailMediaParserBridge {
-    private long mNativeThumbnailMediaParserBridge;
+    private ThumbnailMediaParserBridge() {}
 
     /**
-     * Creates a media parser to analyze media metadata and retrieve thumbnails.
+     * Starts to parse a media file to retrieve media metadata and video thumbnail.
      * @param mimeType The mime type of the media file.
      * @param filePath The absolute path of the media file.
      * @param totalSize Total size of the media file.
      * @param callback Callback to get the result.
+     *
      */
-    public ThumbnailMediaParserBridge(
+    public static void parse(
             String mimeType, String filePath, Callback<ThumbnailMediaData> callback) {
-        mNativeThumbnailMediaParserBridge = ThumbnailMediaParserBridgeJni.get().init(
-                ThumbnailMediaParserBridge.this, mimeType, filePath, callback);
-    }
-
-    /**
-     * Destroys the native object of ThumbnailMediaParser. This will result in the utility process
-     * being destroyed.
-     */
-    public void destroy() {
-        ThumbnailMediaParserBridgeJni.get().destroy(
-                mNativeThumbnailMediaParserBridge, ThumbnailMediaParserBridge.this);
-        mNativeThumbnailMediaParserBridge = 0;
-    }
-
-    /**
-     * Starts to parse a media file to retrieve media metadata and video thumbnail.
-     */
-    public void start() {
-        if (mNativeThumbnailMediaParserBridge != 0) {
-            ThumbnailMediaParserBridgeJni.get().start(
-                    mNativeThumbnailMediaParserBridge, ThumbnailMediaParserBridge.this);
-        }
+        ThumbnailMediaParserBridgeJni.get().parse(mimeType, filePath, callback);
     }
 
     @NativeMethods
     interface Natives {
-        long init(ThumbnailMediaParserBridge caller, String mimeType, String filePath,
-                Callback<ThumbnailMediaData> callback);
-        void destroy(long nativeThumbnailMediaParserBridge, ThumbnailMediaParserBridge caller);
-        void start(long nativeThumbnailMediaParserBridge, ThumbnailMediaParserBridge caller);
+        void parse(String mimeType, String filePath, Callback<ThumbnailMediaData> callback);
     }
 }
diff --git a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java
index 3fad00eb..6a4a180 100644
--- a/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java
+++ b/chrome/browser/thumbnail/generator/android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java
@@ -63,12 +63,10 @@
 
         // The native MediaParser needs to be created on UI thread.
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            ThumbnailMediaParserBridge parser = new ThumbnailMediaParserBridge(
-                    mimeType, filePath, (ThumbnailMediaData mediaData) -> {
-                        result.mediaData = mediaData;
-                        result.done = true;
-                    });
-            parser.start();
+            ThumbnailMediaParserBridge.parse(mimeType, filePath, (ThumbnailMediaData mediaData) -> {
+                result.mediaData = mediaData;
+                result.done = true;
+            });
         });
 
         CriteriaHelper.pollUiThread(
diff --git a/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.cc b/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.cc
index 5d9d1be..db07775 100644
--- a/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.cc
+++ b/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.h"
 #include "base/android/callback_android.h"
 #include "base/android/jni_string.h"
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/task/post_task.h"
+#include "chrome/browser/thumbnail/generator/android/thumbnail_media_parser.h"
 #include "chrome/browser/thumbnail/generator/test_support_jni_headers/ThumbnailMediaData_jni.h"
 #include "chrome/browser/thumbnail/generator/test_support_jni_headers/ThumbnailMediaParserBridge_jni.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -17,7 +17,8 @@
 
 namespace {
 
-void OnMediaParsed(const base::android::ScopedJavaGlobalRef<jobject> jcallback,
+void OnMediaParsed(ThumbnailMediaParser*,
+                   const base::android::ScopedJavaGlobalRef<jobject> jcallback,
                    bool success,
                    chrome::mojom::MediaMetadataPtr metadata,
                    SkBitmap thumbnail_bitmap) {
@@ -42,9 +43,8 @@
 }  // namespace
 
 // static
-jlong JNI_ThumbnailMediaParserBridge_Init(
+void JNI_ThumbnailMediaParserBridge_Parse(
     JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& jcaller,
     const base::android::JavaParamRef<jstring>& jmime_type,
     const base::android::JavaParamRef<jstring>& jfile_path,
     const base::android::JavaParamRef<jobject>& jcallback) {
@@ -53,26 +53,10 @@
   std::string mime_type =
       base::android::ConvertJavaStringToUTF8(env, jmime_type);
 
-  auto* bridge = new ThumbnailMediaParserBridge(
-      mime_type, file_path,
-      base::BindOnce(&OnMediaParsed,
+  // Deletes self
+  ThumbnailMediaParser* parser =
+      ThumbnailMediaParser::Create(mime_type, file_path).release();
+  parser->Start(
+      base::BindOnce(&OnMediaParsed, base::Owned(parser),
                      base::android::ScopedJavaGlobalRef<jobject>(jcallback)));
-  return reinterpret_cast<intptr_t>(bridge);
-}
-
-ThumbnailMediaParserBridge::ThumbnailMediaParserBridge(
-    const std::string& mime_type,
-    const base::FilePath& file_path,
-    ThumbnailMediaParser::ParseCompleteCB parse_complete_cb)
-    : parser_(ThumbnailMediaParser::Create(mime_type, file_path)),
-      parse_complete_cb_(std::move(parse_complete_cb)) {}
-
-ThumbnailMediaParserBridge::~ThumbnailMediaParserBridge() = default;
-
-void ThumbnailMediaParserBridge::Destroy(JNIEnv* env, jobject obj) {
-  delete this;
-}
-
-void ThumbnailMediaParserBridge::Start(JNIEnv* env, jobject obj) {
-  parser_->Start(std::move(parse_complete_cb_));
 }
diff --git a/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.h b/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.h
deleted file mode 100644
index fa20270..0000000
--- a/chrome/browser/thumbnail/generator/android/thumbnail_media_parser_bridge.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_THUMBNAIL_GENERATOR_ANDROID_THUMBNAIL_MEDIA_PARSER_BRIDGE_H_
-#define CHROME_BROWSER_THUMBNAIL_GENERATOR_ANDROID_THUMBNAIL_MEDIA_PARSER_BRIDGE_H_
-
-#include <memory>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "chrome/browser/thumbnail/generator/android/thumbnail_media_parser.h"
-
-class ThumbnailMediaParser;
-
-// The JNI bridge that uses MediaParser to parse local media file. The
-// bridge is owned by the Java side.
-class ThumbnailMediaParserBridge {
- public:
-  ThumbnailMediaParserBridge(
-      const std::string& mime_type,
-      const base::FilePath& file_path,
-      ThumbnailMediaParser::ParseCompleteCB parse_complete_cb);
-  ~ThumbnailMediaParserBridge();
-
-  void Destroy(JNIEnv* env, jobject obj);
-  void Start(JNIEnv* env, jobject obj);
-
- private:
-  // The media parser that does actual jobs in a sandboxed process.
-  std::unique_ptr<ThumbnailMediaParser> parser_;
-  ThumbnailMediaParser::ParseCompleteCB parse_complete_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(ThumbnailMediaParserBridge);
-};
-
-#endif  // CHROME_BROWSER_THUMBNAIL_GENERATOR_ANDROID_THUMBNAIL_MEDIA_PARSER_BRIDGE_H_
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index c14fd76..89cd1aa 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1976,6 +1976,8 @@
       "ash/crosapi_new_window_delegate.h",
       "ash/default_pinned_apps.cc",
       "ash/default_pinned_apps.h",
+      "ash/desks_client.cc",
+      "ash/desks_client.h",
       "ash/holding_space/holding_space_client_impl.cc",
       "ash/holding_space/holding_space_client_impl.h",
       "ash/holding_space/holding_space_downloads_delegate.cc",
diff --git a/chrome/browser/ui/android/favicon/java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java b/chrome/browser/ui/android/favicon/java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java
index 6e425a6..f43b21b 100644
--- a/chrome/browser/ui/android/favicon/java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java
+++ b/chrome/browser/ui/android/favicon/java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java
@@ -191,7 +191,7 @@
      *         that this callback is not called if this method returns false.
      * @return True if GetLocalFaviconImageForURL is successfully called.
      */
-    public boolean getComposedFaviconImage(Profile profile, @NonNull List<GURL> urls,
+    public boolean getComposedFaviconImage(Profile profile, @NonNull List<String> urls,
             int desiredSizeInPixel, FaviconImageCallback faviconImageCallback) {
         assert mNativeFaviconHelper != 0;
 
@@ -201,14 +201,14 @@
         }
 
         return FaviconHelperJni.get().getComposedFaviconImage(mNativeFaviconHelper, profile,
-                urls.toArray(new GURL[0]), desiredSizeInPixel, faviconImageCallback);
+                urls.toArray(new String[0]), desiredSizeInPixel, faviconImageCallback);
     }
 
     @NativeMethods
     interface Natives {
         long init();
         void destroy(long nativeFaviconHelper);
-        boolean getComposedFaviconImage(long nativeFaviconHelper, Profile profile, GURL[] urls,
+        boolean getComposedFaviconImage(long nativeFaviconHelper, Profile profile, String[] urls,
                 int desiredSizeInDip, FaviconImageCallback faviconImageCallback);
         boolean getLocalFaviconImageForURL(long nativeFaviconHelper, Profile profile,
                 String pageUrl, int desiredSizeInDip, FaviconImageCallback faviconImageCallback);
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn
index 10ccc9e9..7c892c1 100644
--- a/chrome/browser/ui/android/omnibox/BUILD.gn
+++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -6,4 +6,363 @@
 import("//build/config/android/rules.gni")
 import("//chrome/browser/buildflags.gni")
 
-java_group("java") {}
+android_library("java") {
+  sources = [
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java",
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java",
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java",
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java",
+    "java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java",
+    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java",
+    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java",
+    "java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBar.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java",
+    "java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java",
+    "java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java",
+    "java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBar.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java",
+    "java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java",
+    "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java",
+    "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java",
+    "java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java",
+  ]
+
+  public_deps = [ ":partner_location_descriptor_proto_java" ]
+
+  deps = [
+    ":java_resources",
+    "//base:base_java",
+    "//chrome/browser/android/lifecycle:java",
+    "//chrome/browser/feature_engagement:java",
+    "//chrome/browser/flags:java",
+    "//chrome/browser/gsa:java",
+    "//chrome/browser/history_clusters:java",
+    "//chrome/browser/image_fetcher:java",
+    "//chrome/browser/language/android:java",
+    "//chrome/browser/lens:java",
+    "//chrome/browser/locale:java",
+    "//chrome/browser/preferences:java",
+    "//chrome/browser/privacy:java",
+    "//chrome/browser/profiles/android:java",
+    "//chrome/browser/search_engines/android:java",
+    "//chrome/browser/share:java",
+    "//chrome/browser/signin/services/android:java",
+    "//chrome/browser/tab:java",
+    "//chrome/browser/tabmodel:java",
+    "//chrome/browser/ui/android/favicon:java",
+    "//chrome/browser/ui/android/layouts:java",
+    "//chrome/browser/ui/android/native_page:java",
+    "//chrome/browser/ui/android/night_mode:java",
+    "//chrome/browser/ui/android/theme:java",
+    "//chrome/browser/user_education:java",
+    "//chrome/browser/util:java",
+    "//components/browser_ui/bottomsheet/android:java",
+    "//components/browser_ui/share/android:java",
+    "//components/browser_ui/site_settings/android:java",
+    "//components/browser_ui/styles/android:java",
+    "//components/browser_ui/util/android:java",
+    "//components/browser_ui/widget/android:java",
+    "//components/browser_ui/widget/android:java_resources",
+    "//components/content_settings/android:content_settings_enums_java",
+    "//components/embedder_support/android:util_java",
+    "//components/externalauth/android:java",
+    "//components/favicon/android:java",
+    "//components/feature_engagement/public:public_java",
+    "//components/omnibox/browser:browser_java",
+    "//components/page_info/android:java",
+    "//components/permissions/android:java",
+    "//components/prefs/android:java",
+    "//components/query_tiles:java",
+    "//components/search_engines/android:java",
+    "//components/security_state/core:security_state_enums_java",
+    "//components/signin/public/android:java",
+    "//components/user_prefs/android:java",
+    "//content/public/android:content_java",
+    "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:guava_android_java",
+    "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/androidx:androidx_collection_collection_java",
+    "//third_party/metrics_proto:metrics_proto_java",
+    "//ui/android:ui_full_java",
+    "//ui/android:ui_utils_java",
+    "//ui/base/mojom:mojom_java",
+    "//url:gurl_java",
+  ]
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+  resources_package = "org.chromium.chrome.browser.omnibox"
+}
+
+generate_jni("jni_headers") {
+  sources = [
+    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java",
+    "java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java",
+    "java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
+  ]
+}
+
+android_resources("java_resources") {
+  sources = [
+    "java/res/drawable-hdpi/bookmark_edit_active.png",
+    "java/res/drawable-hdpi/btn_mic.png",
+    "java/res/drawable-hdpi/btn_star.png",
+    "java/res/drawable-hdpi/btn_suggestion_refine.png",
+    "java/res/drawable-hdpi/ic_history_googblue_24dp.png",
+    "java/res/drawable-hdpi/ic_suggestion_magnifier.png",
+    "java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png",
+    "java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png",
+    "java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png",
+    "java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png",
+    "java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png",
+    "java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png",
+    "java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png",
+    "java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png",
+    "java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png",
+    "java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png",
+    "java/res/drawable-mdpi/bookmark_edit_active.png",
+    "java/res/drawable-mdpi/btn_mic.png",
+    "java/res/drawable-mdpi/btn_star.png",
+    "java/res/drawable-mdpi/btn_suggestion_refine.png",
+    "java/res/drawable-mdpi/ic_history_googblue_24dp.png",
+    "java/res/drawable-mdpi/ic_suggestion_magnifier.png",
+    "java/res/drawable-xhdpi/bookmark_edit_active.png",
+    "java/res/drawable-xhdpi/btn_mic.png",
+    "java/res/drawable-xhdpi/btn_star.png",
+    "java/res/drawable-xhdpi/btn_suggestion_refine.png",
+    "java/res/drawable-xhdpi/ic_history_googblue_24dp.png",
+    "java/res/drawable-xhdpi/ic_suggestion_magnifier.png",
+    "java/res/drawable-xxhdpi/bookmark_edit_active.png",
+    "java/res/drawable-xxhdpi/btn_mic.png",
+    "java/res/drawable-xxhdpi/btn_star.png",
+    "java/res/drawable-xxhdpi/btn_suggestion_refine.png",
+    "java/res/drawable-xxhdpi/ic_history_googblue_24dp.png",
+    "java/res/drawable-xxhdpi/ic_suggestion_magnifier.png",
+    "java/res/drawable-xxxhdpi/bookmark_edit_active.png",
+    "java/res/drawable-xxxhdpi/btn_mic.png",
+    "java/res/drawable-xxxhdpi/btn_star.png",
+    "java/res/drawable-xxxhdpi/btn_suggestion_refine.png",
+    "java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png",
+    "java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png",
+    "java/res/drawable/ic_book_round.xml",
+    "java/res/drawable/ic_colorful_mic.xml",
+    "java/res/drawable/ic_content_copy_black.xml",
+    "java/res/drawable/ic_equals_sign_round.xml",
+    "java/res/drawable/ic_event_round.xml",
+    "java/res/drawable/ic_google_round.xml",
+    "java/res/drawable/ic_logo_googleg_20dp.xml",
+    "java/res/drawable/ic_loop_round.xml",
+    "java/res/drawable/ic_swap_vert_round.xml",
+    "java/res/drawable/ic_wb_sunny_round.xml",
+    "java/res/drawable/logo_partly_cloudy.xml",
+    "java/res/drawable/logo_translate_round.xml",
+    "java/res/drawable/switch_to_tab.xml",
+    "java/res/drawable/trending_up_black_24dp.xml",
+    "java/res/layout-sw600dp/location_bar.xml",
+    "java/res/layout/assistant_voice_search_consent_ui.xml",
+    "java/res/layout/location_bar.xml",
+    "java/res/layout/location_bar_base.xml",
+    "java/res/layout/location_status.xml",
+    "java/res/layout/location_status_icon.xml",
+    "java/res/layout/location_status_incognito_badge.xml",
+    "java/res/layout/omnibox_answer_suggestion.xml",
+    "java/res/layout/omnibox_basic_suggestion.xml",
+    "java/res/layout/omnibox_entity_suggestion.xml",
+    "java/res/layout/omnibox_query_tiles_suggestion.xml",
+    "java/res/layout/omnibox_results_container.xml",
+    "java/res/layout/suggestions_tile_view.xml",
+    "java/res/layout/url_action_container.xml",
+    "java/res/values/colors.xml",
+    "java/res/values/dimens.xml",
+    "java/res/values/ids.xml",
+    "java/res/values/styles.xml",
+  ]
+
+  deps = [
+    "//chrome/browser/ui/android/strings:ui_strings_grd",
+    "//components/browser_ui/styles/android:java_resources",
+    "//content/public/android:content_java_resources",
+  ]
+}
+
+proto_java_library("partner_location_descriptor_proto_java") {
+  proto_path = "java/src/org/chromium/chrome/browser/omnibox/geo"
+  sources = [ "$proto_path/partner_location_descriptor.proto" ]
+}
+
+java_library("junit") {
+  # Skip platform checks since Robolectric depends on requires_android targets.
+  bypass_platform_checks = true
+  testonly = true
+
+  sources = [
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java",
+    "java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java",
+  ]
+  deps = [
+    ":java",
+    "//base:base_java",
+    "//base:base_java_test_support",
+    "//base:base_junit_test_support",
+    "//chrome/android:base_module_java",
+    "//chrome/browser/flags:java",
+    "//chrome/browser/gsa:java",
+    "//chrome/browser/lens:java",
+    "//chrome/browser/locale:java",
+    "//chrome/browser/preferences:java",
+    "//chrome/browser/privacy:java",
+    "//chrome/browser/profiles/android:java",
+    "//chrome/browser/signin/services/android:java",
+    "//chrome/browser/tab:java",
+    "//chrome/browser/ui/android/favicon:java",
+    "//chrome/browser/ui/android/theme:java",
+    "//chrome/browser/ui/android/toolbar:java",
+    "//chrome/browser/util:java",
+    "//chrome/test/android:chrome_java_test_support",
+    "//components/browser_ui/site_settings/android:java",
+    "//components/browser_ui/widget/android:java",
+    "//components/content_settings/android:content_settings_enums_java",
+    "//components/embedder_support/android:browser_context_java",
+    "//components/embedder_support/android:util_java",
+    "//components/externalauth/android:java",
+    "//components/omnibox/browser:browser_java",
+    "//components/search_engines/android:java",
+    "//components/signin/public/android:java",
+    "//components/signin/public/android:signin_java_test_support",
+    "//content/public/android:content_full_java",
+    "//content/public/android:content_main_dex_java",
+    "//content/public/test/android:content_java_test_support",
+    "//testing/android/junit:junit_test_support",
+    "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:robolectric_all_java",
+    "//third_party/android_support_test_runner:runner_java",
+    "//third_party/androidx:androidx_annotation_annotation_java",
+    "//third_party/hamcrest:hamcrest_library_java",
+    "//third_party/junit",
+    "//third_party/mockito:mockito_java",
+    "//ui/android:ui_no_recycler_view_java",
+    "//ui/android:ui_recycler_view_java",
+    "//url:gurl_java",
+    "//url:gurl_junit_test_support",
+  ]
+  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+  resources_package = "org.chromium.chrome.browser.omnibox"
+}
diff --git a/chrome/browser/ui/android/omnibox/DEPS b/chrome/browser/ui/android/omnibox/DEPS
new file mode 100644
index 0000000..aa2cfcc
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/DEPS
@@ -0,0 +1,18 @@
+include_rules = [
+  "+base/android/java/src/org/chromium/base",
+  "+components/browser_ui/settings/android",
+  "+components/browser_ui/share/android",
+  "+components/browser_ui/styles/android",
+  "+components/browser_ui/widget/android",
+  "+components/embedder_support/android",
+  "+components/externalauth/android",
+  "+components/favicon/android",
+  "+components/feature_engagement/public/android",
+  "+components/omnibox/browser/android",
+  "+components/page_info/android/java/src/org/chromium/components/page_info",
+  "+components/search_engines/android",
+  "+components/signin/public/android",
+  "+content/public/android",
+  "+ui/android",
+  "+url/android",
+]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DIR_METADATA b/chrome/browser/ui/android/omnibox/DIR_METADATA
similarity index 79%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/DIR_METADATA
rename to chrome/browser/ui/android/omnibox/DIR_METADATA
index 07a4669..db98947 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/DIR_METADATA
+++ b/chrome/browser/ui/android/omnibox/DIR_METADATA
@@ -1,3 +1,4 @@
 monorail {
   component: "UI>Browser>Omnibox"
 }
+os: ANDROID
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OWNERS b/chrome/browser/ui/android/omnibox/OWNERS
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OWNERS
rename to chrome/browser/ui/android/omnibox/OWNERS
diff --git a/chrome/android/java/res/drawable-hdpi/bookmark_edit_active.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/bookmark_edit_active.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/bookmark_edit_active.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/bookmark_edit_active.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_mic.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_mic.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/btn_mic.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_mic.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_star.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_star.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/btn_star.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_star.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_history_googblue_24dp.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/ic_history_googblue_24dp.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/ic_history_googblue_24dp.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/ic_history_googblue_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-hdpi/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-hdpi-v17/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-hdpi-v17/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-mdpi-v17/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-mdpi-v17/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xhdpi-v17/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xhdpi-v17/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxhdpi-v17/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxhdpi-v17/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxxhdpi-v17/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-ldrtl-xxxhdpi-v17/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bookmark_edit_active.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/bookmark_edit_active.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/bookmark_edit_active.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/bookmark_edit_active.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_mic.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_mic.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/btn_mic.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_mic.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_star.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_star.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/btn_star.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_star.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_history_googblue_24dp.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/ic_history_googblue_24dp.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/ic_history_googblue_24dp.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/ic_history_googblue_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-mdpi/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bookmark_edit_active.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/bookmark_edit_active.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/bookmark_edit_active.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/bookmark_edit_active.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_mic.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_mic.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/btn_mic.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_mic.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_star.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_star.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/btn_star.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_star.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_history_googblue_24dp.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/ic_history_googblue_24dp.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/ic_history_googblue_24dp.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/ic_history_googblue_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xhdpi/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bookmark_edit_active.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/bookmark_edit_active.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/bookmark_edit_active.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/bookmark_edit_active.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_mic.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_mic.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/btn_mic.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_mic.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_star.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_star.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/btn_star.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_star.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_history_googblue_24dp.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/ic_history_googblue_24dp.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/ic_history_googblue_24dp.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/ic_history_googblue_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxhdpi/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bookmark_edit_active.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/bookmark_edit_active.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/bookmark_edit_active.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/bookmark_edit_active.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_mic.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_mic.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/btn_mic.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_mic.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_star.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_star.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/btn_star.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_star.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/btn_suggestion_refine.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_suggestion_refine.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/btn_suggestion_refine.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/btn_suggestion_refine.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/ic_history_googblue_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png b/chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png
rename to chrome/browser/ui/android/omnibox/java/res/drawable-xxxhdpi/ic_suggestion_magnifier.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/ic_book_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_book_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_book_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_book_round.xml
diff --git a/chrome/android/java/res/drawable/ic_colorful_mic.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_colorful_mic.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_colorful_mic.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_colorful_mic.xml
diff --git a/chrome/android/java/res/drawable/ic_content_copy_black.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_content_copy_black.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_content_copy_black.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_content_copy_black.xml
diff --git a/chrome/android/java/res/drawable/ic_equals_sign_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_equals_sign_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_equals_sign_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_equals_sign_round.xml
diff --git a/chrome/android/java/res/drawable/ic_event_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_event_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml
diff --git a/chrome/android/java/res/drawable/ic_google_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_google_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_google_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_google_round.xml
diff --git a/chrome/android/java/res/drawable/ic_logo_googleg_20dp.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_logo_googleg_20dp.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_logo_googleg_20dp.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_logo_googleg_20dp.xml
diff --git a/chrome/android/java/res/drawable/ic_loop_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_loop_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_loop_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_loop_round.xml
diff --git a/chrome/android/java/res/drawable/ic_swap_vert_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_swap_vert_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_swap_vert_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_swap_vert_round.xml
diff --git a/chrome/android/java/res/drawable/ic_wb_sunny_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/ic_wb_sunny_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_wb_sunny_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/ic_wb_sunny_round.xml
diff --git a/chrome/android/java/res/drawable/logo_partly_cloudy.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml
similarity index 100%
rename from chrome/android/java/res/drawable/logo_partly_cloudy.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml
diff --git a/chrome/android/java/res/drawable/logo_translate_round.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml
similarity index 100%
rename from chrome/android/java/res/drawable/logo_translate_round.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml
diff --git a/chrome/android/java/res/drawable/switch_to_tab.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/switch_to_tab.xml
similarity index 100%
rename from chrome/android/java/res/drawable/switch_to_tab.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/switch_to_tab.xml
diff --git a/chrome/android/java/res/drawable/trending_up_black_24dp.xml b/chrome/browser/ui/android/omnibox/java/res/drawable/trending_up_black_24dp.xml
similarity index 100%
rename from chrome/android/java/res/drawable/trending_up_black_24dp.xml
rename to chrome/browser/ui/android/omnibox/java/res/drawable/trending_up_black_24dp.xml
diff --git a/chrome/android/java/res/layout-sw600dp/location_bar.xml b/chrome/browser/ui/android/omnibox/java/res/layout-sw600dp/location_bar.xml
similarity index 100%
rename from chrome/android/java/res/layout-sw600dp/location_bar.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout-sw600dp/location_bar.xml
diff --git a/chrome/android/java/res/layout/assistant_voice_search_consent_ui.xml b/chrome/browser/ui/android/omnibox/java/res/layout/assistant_voice_search_consent_ui.xml
similarity index 100%
rename from chrome/android/java/res/layout/assistant_voice_search_consent_ui.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/assistant_voice_search_consent_ui.xml
diff --git a/chrome/android/java/res/layout/location_bar.xml b/chrome/browser/ui/android/omnibox/java/res/layout/location_bar.xml
similarity index 100%
rename from chrome/android/java/res/layout/location_bar.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/location_bar.xml
diff --git a/chrome/android/java/res/layout/location_bar_base.xml b/chrome/browser/ui/android/omnibox/java/res/layout/location_bar_base.xml
similarity index 100%
rename from chrome/android/java/res/layout/location_bar_base.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/location_bar_base.xml
diff --git a/chrome/android/java/res/layout/location_status.xml b/chrome/browser/ui/android/omnibox/java/res/layout/location_status.xml
similarity index 100%
rename from chrome/android/java/res/layout/location_status.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/location_status.xml
diff --git a/chrome/android/java/res/layout/location_status_icon.xml b/chrome/browser/ui/android/omnibox/java/res/layout/location_status_icon.xml
similarity index 100%
rename from chrome/android/java/res/layout/location_status_icon.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/location_status_icon.xml
diff --git a/chrome/android/java/res/layout/location_status_incognito_badge.xml b/chrome/browser/ui/android/omnibox/java/res/layout/location_status_incognito_badge.xml
similarity index 100%
rename from chrome/android/java/res/layout/location_status_incognito_badge.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/location_status_incognito_badge.xml
diff --git a/chrome/android/java/res/layout/omnibox_answer_suggestion.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml
similarity index 100%
rename from chrome/android/java/res/layout/omnibox_answer_suggestion.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml
diff --git a/chrome/android/java/res/layout/omnibox_basic_suggestion.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_basic_suggestion.xml
similarity index 100%
rename from chrome/android/java/res/layout/omnibox_basic_suggestion.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/omnibox_basic_suggestion.xml
diff --git a/chrome/android/java/res/layout/omnibox_entity_suggestion.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_entity_suggestion.xml
similarity index 100%
rename from chrome/android/java/res/layout/omnibox_entity_suggestion.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/omnibox_entity_suggestion.xml
diff --git a/chrome/android/java/res/layout/omnibox_query_tiles_suggestion.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_query_tiles_suggestion.xml
similarity index 100%
rename from chrome/android/java/res/layout/omnibox_query_tiles_suggestion.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/omnibox_query_tiles_suggestion.xml
diff --git a/chrome/android/java/res/layout/omnibox_results_container.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_results_container.xml
similarity index 100%
rename from chrome/android/java/res/layout/omnibox_results_container.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/omnibox_results_container.xml
diff --git a/chrome/android/java/res/layout/suggestions_tile_view.xml b/chrome/browser/ui/android/omnibox/java/res/layout/suggestions_tile_view.xml
similarity index 100%
rename from chrome/android/java/res/layout/suggestions_tile_view.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/suggestions_tile_view.xml
diff --git a/chrome/android/java/res/layout/url_action_container.xml b/chrome/browser/ui/android/omnibox/java/res/layout/url_action_container.xml
similarity index 100%
rename from chrome/android/java/res/layout/url_action_container.xml
rename to chrome/browser/ui/android/omnibox/java/res/layout/url_action_container.xml
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/colors.xml b/chrome/browser/ui/android/omnibox/java/res/values/colors.xml
new file mode 100644
index 0000000..342713e
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Please see src/ui/android/java/res/values/colors.xml for the shared common colors. -->
+
+    <!-- Omnibox Suggestion colors -->
+    <color name="suggestion_url_dark_modern">@color/default_text_color_link</color>
+    <color name="suggestion_url_light_modern">@color/modern_blue_300</color>
+    <color name="answers_description_text_negative">@color/default_red</color>
+    <color name="answers_description_text_positive">@color/default_green</color>
+
+    <!-- LocationBar colors -->
+    <color name="locationbar_dark_hint_text">@color/search_box_hint</color>
+    <color name="locationbar_light_hint_text">@color/white_alpha_70</color>
+    <color name="locationbar_status_offline_color">@color/modern_grey_900</color>
+    <color name="locationbar_status_offline_color_light">@android:color/white</color>
+    <color name="locationbar_status_preview_color">@color/modern_blue_600</color>
+    <color name="locationbar_status_preview_color_light">@color/modern_blue_300</color>
+    <color name="omnibox_focused_fading_background_color">@color/black_alpha_65</color>
+    <color name="omnibox_focused_fading_background_color_light">@color/white_alpha_65</color>
+
+</resources>
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml b/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml
new file mode 100644
index 0000000..e5e65f6
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/res/values/dimens.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+    <!-- Toolbar dimensions -->
+    <dimen name="toolbar_height_no_shadow">56dp</dimen>
+    <dimen name="toolbar_progress_bar_height">2dp</dimen>
+    <dimen name="toolbar_button_width">48dp</dimen>
+    <dimen name="toolbar_identity_disc_size">24dp</dimen>
+    <dimen name="toolbar_identity_disc_size_duet">32dp</dimen>
+    <dimen name="toolbar_url_focus_translation_x">10dp</dimen>
+
+    <!-- Bottom Toolbar -->
+    <dimen name="split_toolbar_button_height">56dp</dimen>
+    <dimen name="split_toolbar_button_width">@dimen/split_toolbar_button_height</dimen>
+    <dimen name="bottom_toolbar_button_wrapper_width">56dp</dimen>
+
+    <dimen name="toolbar_edge_padding">8dp</dimen>
+    <dimen name="location_bar_vertical_margin">8dp</dimen>
+    <dimen name="location_bar_url_text_size">16sp</dimen>
+    <dimen name="location_bar_icon_width">28dp</dimen>
+    <dimen name="location_bar_action_icon_width">48dp</dimen>
+    <dimen name="location_bar_icon_margin_end">4dp</dimen>
+    <dimen name="location_bar_status_separator_width">1dp</dimen>
+    <dimen name="location_bar_status_separator_spacer">8dp</dimen>
+    <dimen name="location_bar_min_url_width">68dp</dimen>
+    <dimen name="location_bar_min_verbose_status_text_width">48dp</dimen>
+
+    <dimen name="location_bar_lateral_padding">8dp</dimen>
+    <dimen name="fake_search_box_lateral_padding">10dp</dimen>
+    <dimen name="location_bar_status_icon_width">24dp</dimen>
+    <dimen name="location_bar_icon_end_padding">4dp</dimen>
+    <dimen name="location_bar_icon_end_padding_focused">16dp</dimen>
+    <dimen name="location_bar_verbose_start_padding_verbose_text">4dp</dimen>
+    <dimen name="location_bar_status_extra_padding">4dp</dimen>
+    <dimen name="location_bar_url_action_offset">-8dp</dimen>
+
+    <dimen name="tablet_toolbar_start_padding">4dp</dimen>
+    <dimen name="toolbar_optional_button_animation_translation">10dp</dimen>
+
+    <!-- Omnibox suggestions -->
+    <dimen name="omnibox_suggestion_header_margin_start">
+        @dimen/omnibox_suggestion_24dp_icon_margin_start
+    </dimen>
+    <dimen name="omnibox_suggestion_header_height">48dp</dimen>
+    <dimen name="omnibox_suggestion_comfortable_height">60dp</dimen>
+    <dimen name="omnibox_suggestion_semicompact_height">56dp</dimen>
+    <dimen name="omnibox_suggestion_compact_height">52dp</dimen>
+    <dimen name="omnibox_suggestion_comfortable_padding">10dp</dimen>
+    <dimen name="omnibox_suggestion_semicompact_padding">8dp</dimen>
+    <dimen name="omnibox_suggestion_compact_padding">6dp</dimen>
+    <dimen name="omnibox_suggestion_list_padding_bottom">8dp</dimen>
+    <dimen name="omnibox_suggestion_start_offset_without_icon">18dp</dimen>
+    <dimen name="omnibox_carousel_suggestion_padding">12dp</dimen>
+
+    <dimen name="omnibox_suggestion_36dp_icon_size">36dp</dimen>
+    <dimen name="omnibox_suggestion_24dp_icon_size">24dp</dimen>
+    <dimen name="omnibox_suggestion_36dp_icon_margin_start">10dp</dimen>
+    <dimen name="omnibox_suggestion_36dp_icon_margin_end">10dp</dimen>
+    <dimen name="omnibox_suggestion_24dp_icon_margin_start">16dp</dimen>
+    <dimen name="omnibox_suggestion_24dp_icon_margin_end">16dp</dimen>
+    <dimen name="omnibox_suggestion_favicon_size">24dp</dimen>
+    <dimen name="omnibox_suggestion_decoration_image_size">36dp</dimen>
+    <dimen name="omnibox_suggestion_icon_area_size">56dp</dimen>
+
+    <dimen name="omnibox_suggestion_action_icon_width">48dp</dimen>
+    <dimen name="omnibox_suggestion_refine_view_modern_end_padding">4dp</dimen>
+    <dimen name="omnibox_suggestion_carousel_horizontal_spacing">8dp</dimen>
+
+    <!-- Adding search engine logo to the omnibox. -->
+    <!-- Max size which will fit completely in the composed/rounded bg. -->
+    <dimen name="omnibox_search_engine_logo_favicon_size">17dp</dimen>
+    <dimen name="omnibox_search_engine_logo_composed_size">24dp</dimen>
+
+</resources>
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/ids.xml b/chrome/browser/ui/android/omnibox/java/res/values/ids.xml
new file mode 100644
index 0000000..62df2587
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/res/values/ids.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- 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.
+-->
+
+<resources>
+    <!-- Tags -->
+    <item type="id" name="highlight_color" />
+    <item type="id" name="omnibox_results_container_stub" />
+</resources>
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/styles.xml b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
new file mode 100644
index 0000000..7ed2e5de
--- /dev/null
+++ b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+    <style name="Base.Theme.Chromium.TabbedMode" parent="Theme.Chromium.WithWindowAnimation">
+        <!-- Attributes for material design component. See https://crbug.com/1186712 -->
+        <item name="colorSurface">@color/material_color_surface</item>
+    </style>
+    <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode" />
+
+    <!-- Omnibox -->
+    <style name="TextAppearance.OmniboxVerboseStatus" parent="@android:style/TextAppearance.Medium">
+        <item name="android:textSize">@dimen/location_bar_url_text_size</item>
+    </style>
+
+    <!-- Omnibox suggestions -->
+    <style name="TextAppearance.OmniboxAnswerDescriptionNegativeSmall">
+        <item name="android:textSize">@dimen/text_size_small</item>
+        <item name="android:textColor">@color/answers_description_text_negative</item>
+    </style>
+
+    <style name="TextAppearance.OmniboxAnswerDescriptionPositiveSmall">
+        <item name="android:textSize">@dimen/text_size_small</item>
+        <item name="android:textColor">@color/answers_description_text_positive</item>
+    </style>
+
+    <style name="OmniboxIcon" parent="LocationBarButton">
+        <item name="android:layout_width">@dimen/location_bar_status_icon_width</item>
+        <item name="android:layout_height">match_parent</item>
+    </style>
+
+</resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModel.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextModelBase.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteState.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/AutocompleteStateUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/BackKeyBehaviorDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteProviderClient.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/ChromeAutocompleteSchemeClassifier.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelper.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/KeyboardHideHelperUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBar.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
index 8ffc657..3744d58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -20,7 +20,6 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.lens.LensController;
 import org.chromium.chrome.browser.lens.LensFeature;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorPhone.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinatorTablet.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarDataProvider.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 57312a93..21a1135 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -23,7 +23,6 @@
 import androidx.core.view.MarginLayoutParamsCompat;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.lens.LensFeature;
 import org.chromium.chrome.browser.omnibox.status.StatusCoordinator;
 import org.chromium.chrome.browser.omnibox.status.StatusView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediatorTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index 608783c2..b91ca330 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -12,7 +12,6 @@
 import android.view.View;
 import android.widget.FrameLayout;
 import org.chromium.base.TraceEvent;
-import org.chromium.chrome.R;
 
 /**
  * A location bar implementation specific for smaller/phone screens.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
index 2e33211..15417e0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java
@@ -4,13 +4,13 @@
 
 package org.chromium.chrome.browser.omnibox;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 
-import org.chromium.chrome.R;
 import org.chromium.ui.base.LocalizationUtils;
 
 /**
@@ -57,6 +57,7 @@
         mTargets = new View[] {mUrlBar, mDeleteButton};
     }
 
+    @SuppressLint("ClickableViewAccessibility")
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         if (mTargets == null) return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/NewTabPageDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxFocusReason.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxPrerender.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxStub.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxViewUtil.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OverrideUrlLoadingDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
index 2ba69da..b7c95de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtils.java
@@ -18,7 +18,6 @@
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.omnibox.status.StatusProperties.StatusIconResource;
 import org.chromium.chrome.browser.profiles.Profile;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarApi26.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarEditingTextStateProvider.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarProperties.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
index ffca547..c7cf6cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
@@ -14,7 +14,6 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Callback;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.UrlBarProperties.AutocompleteText;
 import org.chromium.chrome.browser.omnibox.UrlBarProperties.UrlBarTextState;
 import org.chromium.ui.modelutil.PropertyKey;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlFocusChangeListener.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationTracker.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/geo/partner_location_descriptor.proto
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
index a87dde8..36f0e80 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/PageInfoIPHController.java
@@ -9,8 +9,8 @@
 import android.os.Looper;
 import android.view.View;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
 import org.chromium.chrome.browser.user_education.UserEducationHelper;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java
index 5b039a5..d7411ead 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusCoordinator.java
@@ -13,8 +13,8 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.profiles.Profile;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
index 310f948f..940db253 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -20,8 +20,8 @@
 import org.chromium.base.MathUtils;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.status.StatusProperties.PermissionIconResource;
@@ -414,8 +414,8 @@
      */
     private void updateColorTheme() {
         @ColorRes
-        int separatorColor =
-                mDarkTheme ? R.color.divider_line_bg_color_dark : R.color.divider_line_bg_color_light;
+        int separatorColor = mDarkTheme ? R.color.divider_line_bg_color_dark
+                                        : R.color.divider_line_bg_color_light;
 
         @ColorRes
         int textColor = 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
index a4ca9e0..40b94ff3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusProperties.java
@@ -22,7 +22,7 @@
 import androidx.core.util.ObjectsCompat;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.ui.UiUtils;
 import org.chromium.ui.base.ViewUtils;
 import org.chromium.ui.modelutil.PropertyKey;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
index cb74319..c63f93dc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
@@ -25,8 +25,8 @@
 import androidx.annotation.StringRes;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
 import org.chromium.components.browser_ui.widget.CompositeTouchDelegate;
 import org.chromium.components.browser_ui.widget.animation.Interpolators;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
index e53de29..83e6d7f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
@@ -11,8 +11,8 @@
 import androidx.annotation.DrawableRes;
 import androidx.core.content.ContextCompat;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
+import org.chromium.chrome.browser.omnibox.R;
 
 /** Provides resources specific to Omnibox. */
 public class OmniboxResourceProvider {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProviderTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteControllerFactory.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
index b6847390..6592b06 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java
@@ -20,9 +20,9 @@
 import org.chromium.base.StrictModeContext;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.UrlBar.UrlTextChangeListener;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index 5c6261e6..7f5a04f1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -22,12 +22,12 @@
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
@@ -35,7 +35,6 @@
 import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor.BookmarkState;
 import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.query_tiles.QueryTileUtils;
 import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabSelectionType;
@@ -404,11 +403,15 @@
         return mAutocompleteResult.getNativeObjectRef();
     }
 
+    private static boolean isQueryEditingEnabled() {
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES_ENABLE_QUERY_EDITING);
+    }
+
     /** Called when a query tile is selected by the user. */
     void onQueryTileSelected(QueryTile queryTile) {
         // For last level tile, start a search query, unless we want to let user have a chance to
         // edit the query.
-        if (queryTile.children.isEmpty() && !QueryTileUtils.isQueryEditingEnabled()) {
+        if (queryTile.children.isEmpty() && !isQueryEditingEnabled()) {
             launchSearchUrlForQueryTileSuggestion(queryTile);
             return;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemProcessor.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
index 7a406d4..65c6b4e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.omnibox.suggestions;
 
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.View;
 
 import androidx.annotation.NonNull;
@@ -22,17 +23,17 @@
 /** Manages the list of DropdownItemViewInfo elements. */
 class DropdownItemViewInfoListManager {
     private final ModelList mManagedModel;
+    private final SparseBooleanArray mGroupsCollapsedState;
     private int mLayoutDirection;
     private @OmniboxTheme int mOmniboxTheme;
     private List<DropdownItemViewInfo> mSourceViewInfoList;
-    private SparseArray<Boolean> mGroupsCollapsedState;
 
     DropdownItemViewInfoListManager(@NonNull ModelList managedModel) {
         assert managedModel != null : "Must specify a non-null model.";
         mLayoutDirection = View.LAYOUT_DIRECTION_INHERIT;
         mOmniboxTheme = OmniboxTheme.LIGHT_THEME;
         mSourceViewInfoList = Collections.emptyList();
-        mGroupsCollapsedState = new SparseArray<>();
+        mGroupsCollapsedState = new SparseBooleanArray();
         mManagedModel = managedModel;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
index 02d24bd..8517ac6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java
@@ -77,7 +77,7 @@
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         ViewGroup suggestionView = (ViewGroup) inflater.inflate(
-                org.chromium.chrome.R.layout.omnibox_query_tiles_suggestion, null);
+                org.chromium.chrome.browser.omnibox.R.layout.omnibox_query_tiles_suggestion, null);
 
         View tilesView = getTileCoordinator().getView();
         if (tilesView.getParent() != null) UiUtils.removeViewFromParent(tilesView);
@@ -128,7 +128,7 @@
     private void getVisuals(ImageTile tile, Callback<List<Bitmap>> callback) {
         if (mTileWidth == null) {
             mTileWidth = mContext.getResources().getDimensionPixelSize(
-                    org.chromium.chrome.R.dimen.tile_ideal_width);
+                    org.chromium.chrome.browser.omnibox.R.dimen.tile_ideal_width);
         }
 
         QueryTile queryTile = (QueryTile) tile;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
index 3b90516..3962da1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdown.java
@@ -29,8 +29,8 @@
 
 import org.chromium.base.TraceEvent;
 import org.chromium.base.task.PostTask;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
 import org.chromium.components.browser_ui.styles.ChromeColors;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownAdapter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionsDropdownEmbedder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionCommonProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionHost.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionListViewBinder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionProcessor.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/SuggestionsMetrics.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/UrlBarDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
index 2015c50..407627d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -11,9 +11,9 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
index 1743ab7b..236e17e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewBinder.java
@@ -7,7 +7,7 @@
 import android.view.View;
 import android.widget.TextView;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerText.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java
index 9d97005..888ca91 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerTextNewLayout.java
@@ -10,8 +10,8 @@
 
 import androidx.annotation.StyleRes;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.components.omnibox.AnswerTextType;
 import org.chromium.components.omnibox.AnswerType;
 import org.chromium.components.omnibox.AutocompleteMatch;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
index 752ebea..1632b65 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionView.java
@@ -15,7 +15,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.widget.AppCompatImageView;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
 import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
index d66affc..6c46c85 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
@@ -19,7 +19,7 @@
 import androidx.core.view.ViewCompat;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
index 753ecbe..5b2f89a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
@@ -14,9 +14,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.MatchClassificationStyle;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionProcessor;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProperties.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java
index 721c6f3..745b594e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/DecoratedSuggestionView.java
@@ -9,7 +9,7 @@
 import android.view.ViewGroup;
 import android.widget.ImageView;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutView.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionDrawableState.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannable.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
index 850b567c..c5961c1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
@@ -11,9 +11,9 @@
 import androidx.annotation.NonNull;
 
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.MatchClassificationStyle;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
index ed66cbd..85d4979 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
@@ -11,7 +11,7 @@
 import androidx.annotation.ColorRes;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java
similarity index 96%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java
index de8d50c..634bb3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionProcessor.java
@@ -6,7 +6,7 @@
 
 import android.content.Context;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionProcessor;
 
 /** The base processor implementation for the Carousel suggestions. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManager.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
index 467dd37..ba28f4f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionView.java
@@ -15,7 +15,7 @@
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderView;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
 import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java
index b1fc6900..963c23c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinder.java
@@ -6,7 +6,7 @@
 
 import android.view.View;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
index 572f348a..0a41958e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
@@ -14,10 +14,10 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
index 6ff307b2..df3710e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -8,9 +8,9 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.history_clusters.HistoryClustersTabHelper;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
 import org.chromium.chrome.browser.omnibox.suggestions.UrlBarDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java
index 9d4f2c7..443dc9d8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionView.java
@@ -9,7 +9,7 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionView;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
index f3dff21..27ae43a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
@@ -16,9 +16,9 @@
 import org.chromium.base.SysUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.image_fetcher.ImageFetcher;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
similarity index 96%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
index 21a89c8..9f141331 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewBinder.java
@@ -8,7 +8,7 @@
 import android.view.View;
 import android.widget.TextView;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java
index fa887e2..d83cff7f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderProcessor.java
@@ -7,7 +7,7 @@
 import android.content.Context;
 
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.DropdownItemProcessor;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java
index 74ca6638..bb024cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderView.java
@@ -22,7 +22,7 @@
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
 import androidx.core.widget.TextViewCompat;
 
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.base.SimpleHorizontalLayoutView;
 import org.chromium.chrome.browser.util.KeyNavigationUtil;
 import org.chromium.components.browser_ui.styles.ChromeColors;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java
index 9907c24..0f1bb606 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinder.java
@@ -8,7 +8,7 @@
 import androidx.core.widget.TextViewCompat;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.components.browser_ui.styles.ChromeColors;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
index bd46fa3..46cf1dfd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
@@ -15,8 +15,8 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManager.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
index c8d9331..1ceb3fe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
@@ -6,8 +6,8 @@
 
 import android.content.Context;
 
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost;
 import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
index e0e043f..47f94f1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionView.java
@@ -11,7 +11,7 @@
 import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 
 /** Container view for omnibox tail suggestions. */
 public class TailSuggestionView extends TextView {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java
index 7aa1e6de..c1ef188 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewBinder.java
@@ -7,7 +7,7 @@
 import androidx.annotation.ColorRes;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
 import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
 import org.chromium.ui.modelutil.PropertyKey;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionViewProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
similarity index 96%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
index c7334a7..0bbb12b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProcessor.java
@@ -32,7 +32,7 @@
             Context context, Callback<List<QueryTile>> queryTileSuggestionCallback) {
         mQueryTileSuggestionCallback = queryTileSuggestionCallback;
         mMinViewHeight = context.getResources().getDimensionPixelSize(
-                org.chromium.chrome.R.dimen.omnibox_suggestion_comfortable_height);
+                org.chromium.chrome.browser.omnibox.R.dimen.omnibox_suggestion_comfortable_height);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tiles/TileSuggestionProperties.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
index cf3b8dd..1c4032e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
@@ -19,7 +19,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.R;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
index 2bf67b5..8c3b9694 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchService.java
@@ -24,9 +24,9 @@
 import org.chromium.base.SysUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.gsa.GSAState;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
similarity index 100%
rename from chrome/android/junit/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchServiceUnitTest.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
similarity index 99%
rename from chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
index 5ebf5d84f..1d086374 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
@@ -25,10 +25,10 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.LocationBarDataProvider;
+import org.chromium.chrome.browser.omnibox.R;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinator;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
@@ -238,7 +238,6 @@
          */
         void loadUrlFromVoice(String url);
 
-
         /**
          * Sets the query string in the omnibox (ensuring the URL bar has focus and triggering
          * autocomplete for the specified query) as if the user typed it.
diff --git a/chrome/browser/ui/android/omnibox/omnibox_view_util.cc b/chrome/browser/ui/android/omnibox/omnibox_view_util.cc
index 57afd9c..c119ad7 100644
--- a/chrome/browser/ui/android/omnibox/omnibox_view_util.cc
+++ b/chrome/browser/ui/android/omnibox/omnibox_view_util.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/ui/android/omnibox/omnibox_view_util.h"
 
 #include "base/android/jni_string.h"
-#include "chrome/android/chrome_jni_headers/OmniboxViewUtil_jni.h"
+#include "chrome/browser/ui/android/omnibox/jni_headers/OmniboxViewUtil_jni.h"
 #include "components/omnibox/browser/omnibox_view.h"
 
 using base::android::JavaParamRef;
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index fb566d8d..228cca9 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -3557,6 +3557,9 @@
       <message name="IDS_OMNIBOX_CONFIRM_DELETE" desc="A message within a modal dialog that confirms the user wants to delete a suggestion from the list dropdown in the omnibox">
         Remove suggestion from history?
       </message>
+      <message name="IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD" desc="A message within a modal dialog that confirms the user wants to delete a clipboard suggestion from the list dropdown in the omnibox." formatter_data="android_java">
+        Remove suggestion from clipboard?
+      </message>
       <message name="IDS_MOST_VISITED_TILES_HEADER" desc="A header above a row with most visited tiles carousel in the Omnibox suggestions dropdown">
         Frequently visited
       </message>
@@ -4208,6 +4211,9 @@
       <message name="IDS_SMS_FETCHER_NOTIFICATION_TEXT" translateable="false" desc="Content text shown when the browser has received an SMS on the user's behalf.">
         Let Chrome submit <ph name="ONE_TIME_CODE">%1$s<ex>123</ex></ph> on <ph name="ORIGIN">%2$s<ex>example.com</ex></ph>
       </message>
+      <message name="IDS_SMS_FETCHER_NOTIFICATION_TEXT_FOR_EMBEDDED_FRAME" translateable="false" desc="Content text shown when the browser has received an SMS on the user's behalf. User is on TOP_ORIGIN and they need to use service provided by EMBEDDED_ORIGIN. EMBEDDED_ORIGIN sends out an SMS to verify user identity.">
+        Tap OK to submit <ph name="ONE_TIME_CODE">%1$s<ex>123</ex></ph> on <ph name="EMBEDDED_ORIGIN">%3$s<ex>payment.com</ex></ph> to continue on <ph name="TOP_ORIGIN">%2$s<ex>shopping.com</ex></ph>
+      </message>
 
       <!-- Interventions -->
       <message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
diff --git a/chrome/app/generated_resources_grd/IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD.png.sha1
similarity index 100%
rename from chrome/app/generated_resources_grd/IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD.png.sha1
rename to chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_OMNIBOX_CONFIRM_DELETE_FROM_CLIPBOARD.png.sha1
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
index bd301b9..ac1ba55 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/ui/ash/chrome_new_window_client.h"
 #include "chrome/browser/ui/ash/chrome_new_window_delegate_provider.h"
 #include "chrome/browser/ui/ash/crosapi_new_window_delegate.h"
+#include "chrome/browser/ui/ash/desks_client.h"
 #include "chrome/browser/ui/ash/ime_controller_client.h"
 #include "chrome/browser/ui/ash/in_session_auth_dialog_client.h"
 #include "chrome/browser/ui/ash/login_screen_client_impl.h"
@@ -246,6 +247,8 @@
 
   // Initialize TabScrubber after the Ash Shell has been initialized.
   TabScrubber::GetInstance();
+
+  desks_client_ = std::make_unique<DesksClient>();
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostBrowserStart() {
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
index f7e46c2..72c8084 100644
--- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
@@ -28,6 +28,7 @@
 class AppListClientImpl;
 class AshShellInit;
 class CastConfigControllerMediaRouter;
+class DesksClient;
 class ImeControllerClient;
 class InSessionAuthDialogClient;
 class LoginScreenClientImpl;
@@ -115,6 +116,7 @@
   std::unique_ptr<MicrophoneMuteNotificationDelegateImpl>
       microphone_mute_notification_delegate_;
   std::unique_ptr<policy::DisplaySettingsHandler> display_settings_handler_;
+  std::unique_ptr<DesksClient> desks_client_;
 
   // Initialized in PostBrowserStart in all configs:
   std::unique_ptr<MobileDataNotifications> mobile_data_notifications_;
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc
index b9ad1e518..afab4cc 100644
--- a/chrome/browser/ui/ash/chrome_new_window_client.cc
+++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -58,6 +58,7 @@
 #include "chrome/browser/web_applications/components/web_app_id.h"
 #include "chrome/browser/web_applications/components/web_app_provider_base.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
@@ -788,14 +789,15 @@
   apps::RecordAppLaunch(extension_misc::kCameraAppId,
                         apps::mojom::LaunchSource::kFromArc);
 
-  if (web_app::SystemWebAppManager::IsAppEnabled(
-          web_app::SystemAppType::CAMERA)) {
+  Profile* const profile = ProfileManager::GetActiveUserProfile();
+  auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile);
+  if (provider && provider->system_web_app_manager().IsAppEnabled(
+                      web_app::SystemAppType::CAMERA)) {
     ChromeCameraAppUIDelegate::CameraAppDialog::ShowIntent(
         queries, arc::GetArcWindow(task_id));
     return;
   }
 
-  Profile* const profile = ProfileManager::GetActiveUserProfile();
   const extensions::ExtensionRegistry* registry =
       extensions::ExtensionRegistry::Get(profile);
   const extensions::Extension* extension =
@@ -826,10 +828,14 @@
 }
 
 bool ChromeNewWindowClient::IsCameraAppEnabled() {
-  return extensions::ExtensionRegistry::Get(
-             ProfileManager::GetActiveUserProfile())
-                 ->enabled_extensions()
-                 .GetByID(extension_misc::kCameraAppId) != nullptr ||
-         web_app::SystemWebAppManager::IsAppEnabled(
-             web_app::SystemAppType::CAMERA);
+  Profile* const profile = ProfileManager::GetActiveUserProfile();
+
+  if (extensions::ExtensionRegistry::Get(profile)->enabled_extensions().GetByID(
+          extension_misc::kCameraAppId) != nullptr)
+    return true;
+
+  auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile);
+
+  return provider && provider->system_web_app_manager().IsAppEnabled(
+                         web_app::SystemAppType::CAMERA);
 }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 95094f1..ead5708 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -266,6 +266,21 @@
   return base::FilePath();
 }
 
+std::vector<GURL> ChromeShellDelegate::GetURLsIfApplicable(
+    aura::Window* window) {
+  BrowserView* browser_view =
+      BrowserView::GetBrowserViewForNativeWindow(window);
+  if (!browser_view)
+    return std::vector<GURL>();
+
+  TabStripModel* tab_strip_model = browser_view->browser()->tab_strip_model();
+  std::vector<GURL> urls;
+  for (int i = 0; i < tab_strip_model->count(); ++i)
+    urls.push_back(tab_strip_model->GetWebContentsAt(i)->GetLastCommittedURL());
+
+  return urls;
+}
+
 // static
 void ChromeShellDelegate::SetDisableLoggingRedirectForTesting(bool value) {
   disable_logging_redirect_for_testing = value;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index e43b7e4..fa8c0975 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -52,6 +52,7 @@
   int GetUiDevToolsPort() const override;
   bool IsLoggingRedirectDisabled() const override;
   base::FilePath GetPrimaryUserDownloadsFolder() const override;
+  std::vector<GURL> GetURLsIfApplicable(aura::Window* window) override;
 
   static void SetDisableLoggingRedirectForTesting(bool value);
   static void ResetDisableLoggingRedirectForTesting();
diff --git a/chrome/browser/ui/ash/desks_client.cc b/chrome/browser/ui/ash/desks_client.cc
new file mode 100644
index 0000000..528f1e1
--- /dev/null
+++ b/chrome/browser/ui/ash/desks_client.cc
@@ -0,0 +1,43 @@
+// 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 "chrome/browser/ui/ash/desks_client.h"
+
+#include "ash/public/cpp/desks_helper.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
+
+namespace {
+
+DesksClient* g_desks_client_instance = nullptr;
+
+}  // namespace
+
+DesksClient::DesksClient() : desks_helper_(ash::DesksHelper::Get()) {
+  DCHECK(!g_desks_client_instance);
+  g_desks_client_instance = this;
+}
+DesksClient::~DesksClient() {
+  DCHECK_EQ(this, g_desks_client_instance);
+  g_desks_client_instance = nullptr;
+}
+
+// static
+DesksClient* DesksClient::Get() {
+  return g_desks_client_instance;
+}
+
+std::unique_ptr<ash::DeskTemplate> DesksClient::CaptureActiveDeskAsTemplate() {
+  const user_manager::User* primary_user =
+      user_manager::UserManager::Get()->GetPrimaryUser();
+  if (!primary_user)
+    return nullptr;
+
+  Profile* user_profile =
+      ash::ProfileHelper::Get()->GetProfileByUser(primary_user);
+  if (!user_profile)
+    return nullptr;
+
+  return desks_helper_->CaptureActiveDeskAsTemplate(user_profile->GetPath());
+}
diff --git a/chrome/browser/ui/ash/desks_client.h b/chrome/browser/ui/ash/desks_client.h
new file mode 100644
index 0000000..e0c3d197
--- /dev/null
+++ b/chrome/browser/ui/ash/desks_client.h
@@ -0,0 +1,37 @@
+// 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 CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
+#define CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
+
+#include <memory>
+
+namespace ash {
+class DesksHelper;
+class DeskTemplate;
+}  // namespace ash
+
+// Class to handle all Desks in-browser functionalities. Will call into
+// ash::DesksController (via ash::DesksHelper) to do actual desk related
+// operations.
+class DesksClient {
+ public:
+  DesksClient();
+  DesksClient(const DesksClient&) = delete;
+  DesksClient& operator=(const DesksClient&) = delete;
+  ~DesksClient();
+
+  static DesksClient* Get();
+
+  // Captures the active desk and returns it as a desk template containing
+  // necessary information that can be used to recreate a same desk later.
+  // Returns a nullptr if no such template can be captured. Note the captured
+  // template will not be saved to storage.
+  std::unique_ptr<ash::DeskTemplate> CaptureActiveDeskAsTemplate();
+
+ private:
+  ash::DesksHelper* const desks_helper_ = nullptr;
+};
+
+#endif  // CHROME_BROWSER_UI_ASH_DESKS_CLIENT_H_
diff --git a/chrome/browser/ui/ash/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks_client_browsertest.cc
new file mode 100644
index 0000000..e81d712
--- /dev/null
+++ b/chrome/browser/ui/ash/desks_client_browsertest.cc
@@ -0,0 +1,210 @@
+// 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 "chrome/browser/ui/ash/desks_client.h"
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include "ash/public/cpp/desks_helper.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
+#include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
+#include "chrome/browser/web_applications/system_web_apps/system_web_app_types.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/ui/base/window_state_type.h"
+#include "components/full_restore/app_launch_info.h"
+#include "components/full_restore/features.h"
+#include "components/full_restore/full_restore_utils.h"
+#include "components/full_restore/restore_data.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/common/constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/display/screen.h"
+#include "url/gurl.h"
+
+namespace {
+
+constexpr int32_t kSettingsWindowId = 100;
+
+constexpr char kExampleUrl1[] = "https://examples.com";
+constexpr char kExampleUrl2[] = "https://examples.com";
+
+aura::Window* FindAppWindow(int32_t window_id) {
+  for (auto* browser : *BrowserList::GetInstance()) {
+    aura::Window* window = browser->window()->GetNativeWindow();
+    if (window->GetProperty(::full_restore::kRestoreWindowIdKey) == window_id)
+      return window;
+  }
+  return nullptr;
+}
+
+std::vector<GURL> GetURLsForBrowserWindow(Browser* browser) {
+  TabStripModel* tab_strip_model = browser->tab_strip_model();
+  std::vector<GURL> urls;
+  for (int i = 0; i < tab_strip_model->count(); ++i)
+    urls.push_back(tab_strip_model->GetWebContentsAt(i)->GetLastCommittedURL());
+  return urls;
+}
+
+}  // namespace
+
+class DesksClientTest : public InProcessBrowserTest {
+ public:
+  DesksClientTest() {
+    // This feature depends on full restore feature, so need to enable it.
+    scoped_feature_list_.InitAndEnableFeature(
+        full_restore::features::kFullRestore);
+  }
+  ~DesksClientTest() override = default;
+
+  void SetUpOnMainThread() override {
+    ::full_restore::SetActiveProfilePath(browser()->profile()->GetPath());
+    InProcessBrowserTest::SetUpOnMainThread();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that a browser's urls can be captured correctly in the desk template.
+IN_PROC_BROWSER_TEST_F(DesksClientTest, CaptureBrowserUrlsTest) {
+  // Create a new browser and add a few tabs to it.
+  Browser::CreateParams params(Browser::TYPE_NORMAL, browser()->profile(),
+                               /*user_gesture=*/false);
+  Browser* browser = Browser::Create(params);
+  chrome::AddTabAt(browser, GURL(kExampleUrl1), /*index=*/-1,
+                   /*foreground=*/true);
+  chrome::AddTabAt(browser, GURL(kExampleUrl2), /*index=*/-1,
+                   /*foreground=*/true);
+  browser->window()->Show();
+  aura::Window* window = browser->window()->GetNativeWindow();
+
+  const int32_t browser_window_id =
+      window->GetProperty(::full_restore::kWindowIdKey);
+  // Get current tabs from browser.
+  std::vector<GURL> urls = GetURLsForBrowserWindow(browser);
+
+  std::unique_ptr<ash::DeskTemplate> desk_template =
+      DesksClient::Get()->CaptureActiveDeskAsTemplate();
+
+  ASSERT_TRUE(desk_template);
+  full_restore::RestoreData* restore_data = desk_template->desk_restore_data();
+  const auto& app_id_to_launch_list = restore_data->app_id_to_launch_list();
+  EXPECT_EQ(app_id_to_launch_list.size(), 1u);
+
+  // Find |browser| window's app restore data.
+  auto iter = app_id_to_launch_list.find(extension_misc::kChromeAppId);
+  ASSERT_TRUE(iter != app_id_to_launch_list.end());
+  auto app_restore_data_iter = iter->second.find(browser_window_id);
+  ASSERT_TRUE(app_restore_data_iter != iter->second.end());
+  const auto& data = app_restore_data_iter->second;
+  // Check the urls are captured correctly in the |desk_template|.
+  EXPECT_EQ(data->urls.value(), urls);
+}
+
+// Tests that browsers and chrome apps can be captured correctly in the desk
+// template.
+IN_PROC_BROWSER_TEST_F(DesksClientTest, CaptureActiveDeskAsTemplateTest) {
+  // Test that Singleton was properly initialized.
+  ASSERT_TRUE(DesksClient::Get());
+  Profile* profile = browser()->profile();
+
+  // Change |browser|'s bounds.
+  const gfx::Rect browser_bounds = gfx::Rect(0, 0, 800, 200);
+  aura::Window* window = browser()->window()->GetNativeWindow();
+  window->SetBounds(browser_bounds);
+  // Make window visible on all desks.
+  window->SetProperty(aura::client::kVisibleOnAllWorkspacesKey, true);
+  const int32_t browser_window_id =
+      window->GetProperty(::full_restore::kWindowIdKey);
+
+  // Create a Chrome settings app.
+  web_app::WebAppProvider::Get(profile)
+      ->system_web_app_manager()
+      .InstallSystemAppsForTesting();
+  web_app::AppId settings_app_id = *web_app::GetAppIdForSystemWebApp(
+      profile, web_app::SystemAppType::SETTINGS);
+  apps::AppLaunchParams params(
+      settings_app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow,
+      WindowOpenDisposition::NEW_WINDOW,
+      apps::mojom::AppLaunchSource::kSourceTest);
+  params.restore_id = kSettingsWindowId;
+  apps::AppServiceProxyFactory::GetForProfile(profile)
+      ->BrowserAppLauncher()
+      ->LaunchAppWithParams(std::move(params));
+  web_app::FlushSystemWebAppLaunchesForTesting(profile);
+
+  // Change the Settings app's bounds too.
+  const gfx::Rect settings_app_bounds = gfx::Rect(100, 100, 800, 300);
+  aura::Window* settings_window = FindAppWindow(kSettingsWindowId);
+  const int32_t settings_window_id =
+      settings_window->GetProperty(::full_restore::kWindowIdKey);
+  ASSERT_TRUE(settings_window);
+  settings_window->SetBounds(settings_app_bounds);
+
+  std::unique_ptr<ash::DeskTemplate> desk_template =
+      DesksClient::Get()->CaptureActiveDeskAsTemplate();
+  ASSERT_TRUE(desk_template);
+
+  // Test the default template's name is the current desk's name.
+  auto* desks_helper = ash::DesksHelper::Get();
+  EXPECT_EQ(desk_template->desk_name(),
+            desks_helper->GetDeskName(desks_helper->GetActiveDeskIndex()));
+
+  full_restore::RestoreData* restore_data = desk_template->desk_restore_data();
+  const auto& app_id_to_launch_list = restore_data->app_id_to_launch_list();
+  EXPECT_EQ(app_id_to_launch_list.size(), 2u);
+
+  // Find |browser| window's app restore data.
+  auto iter = app_id_to_launch_list.find(extension_misc::kChromeAppId);
+  ASSERT_TRUE(iter != app_id_to_launch_list.end());
+  auto app_restore_data_iter = iter->second.find(browser_window_id);
+  ASSERT_TRUE(app_restore_data_iter != iter->second.end());
+  const auto& data = app_restore_data_iter->second;
+  // Verify window info are correctly captured.
+  EXPECT_EQ(browser_bounds, data->current_bounds.value());
+  EXPECT_EQ(window->GetProperty(aura::client::kVisibleOnAllWorkspacesKey),
+            data->visible_on_all_workspaces.value());
+  auto* screen = display::Screen::GetScreen();
+  EXPECT_EQ(screen->GetDisplayNearestWindow(window).id(),
+            data->display_id.value());
+  EXPECT_EQ(window->GetProperty(aura::client::kShowStateKey),
+            chromeos::ToWindowShowState(data->window_state_type.value()));
+  // We don't capture the window's desk_id as a template will always create in
+  // a new desk.
+  EXPECT_FALSE(data->desk_id.has_value());
+
+  // Find Setting app's app restore data.
+  auto iter2 = app_id_to_launch_list.find(settings_app_id);
+  ASSERT_TRUE(iter2 != app_id_to_launch_list.end());
+  auto app_restore_data_iter2 = iter2->second.find(settings_window_id);
+  ASSERT_TRUE(app_restore_data_iter2 != iter2->second.end());
+  const auto& data2 = app_restore_data_iter2->second;
+  EXPECT_EQ(
+      static_cast<int>(apps::mojom::LaunchContainer::kLaunchContainerWindow),
+      data2->container.value());
+  EXPECT_EQ(static_cast<int>(WindowOpenDisposition::NEW_WINDOW),
+            data2->disposition.value());
+  // Verify window info are correctly captured.
+  EXPECT_EQ(settings_app_bounds, data2->current_bounds.value());
+  EXPECT_FALSE(data2->visible_on_all_workspaces.has_value());
+  EXPECT_EQ(screen->GetDisplayNearestWindow(window).id(),
+            data->display_id.value());
+  EXPECT_EQ(window->GetProperty(aura::client::kShowStateKey),
+            chromeos::ToWindowShowState(data->window_state_type.value()));
+  EXPECT_EQ(window->GetProperty(aura::client::kShowStateKey),
+            chromeos::ToWindowShowState(data->window_state_type.value()));
+  EXPECT_FALSE(data2->desk_id.has_value());
+}
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index 9189880b..ba0a2a4 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -166,8 +166,8 @@
     &kTabSearchRecentlyClosed, "TabSearchRecentlyClosedDefaultItemDisplayCount",
     8};
 
-const base::FeatureParam<int> kTabSearchRecentlyClosedMaxEntries{
-    &kTabSearchRecentlyClosed, "TabSearchRecentlyClosedMaxEntries", 100};
+const base::FeatureParam<int> kTabSearchRecentlyClosedTabCountThreshold{
+    &kTabSearchRecentlyClosed, "TabSearchRecentlyClosedTabCountThreshold", 100};
 
 const base::Feature kToolbarUseHardwareBitmapDraw{
     "ToolbarUseHardwareBitmapDraw", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index de9fdfb..f9a209c 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -117,9 +117,10 @@
 extern const base::FeatureParam<int>
     kTabSearchRecentlyClosedDefaultItemDisplayCount;
 
-// Maximum number of recently closed entries to send in the profile data
-// payload.
-extern const base::FeatureParam<int> kTabSearchRecentlyClosedMaxEntries;
+// A threshold of recently closed tabs after which to stop adding recently
+// closed item data to the profile data payload should the minimum display
+// count have been met.
+extern const base::FeatureParam<int> kTabSearchRecentlyClosedTabCountThreshold;
 
 // Determines how screenshots of the toolbar uses Software or Hardware drawing.
 // Works on Android 10+.
diff --git a/chrome/browser/ui/views/overlay/hang_up_button.cc b/chrome/browser/ui/views/overlay/hang_up_button.cc
index 4b741d6..7b711bd 100644
--- a/chrome/browser/ui/views/overlay/hang_up_button.cc
+++ b/chrome/browser/ui/views/overlay/hang_up_button.cc
@@ -4,12 +4,17 @@
 
 #include "chrome/browser/ui/views/overlay/hang_up_button.h"
 
-#include "chrome/browser/ui/views/overlay/constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/paint_vector_icon.h"
 
+namespace {
+
+constexpr SkColor kHangUpButtonColor = gfx::kGoogleRed300;
+
+}  // namespace
+
 HangUpButton::HangUpButton(PressedCallback callback)
     : ImageButton(std::move(callback)) {
   SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
@@ -29,5 +34,5 @@
 void HangUpButton::UpdateImage() {
   SetImage(views::Button::STATE_NORMAL,
            gfx::CreateVectorIcon(vector_icons::kCallEndIcon, width(),
-                                 kPipWindowIconColor));
+                                 kHangUpButtonColor));
 }
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index c7eb11e..6da231c 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -74,7 +74,7 @@
 constexpr int kOverlayBorderThickness = 10;
 
 // The opacity of the controls scrim.
-constexpr double kControlsScrimOpacity = 0.6;
+constexpr double kControlsScrimOpacity = 0.76;
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // The opacity of the resize handle control.
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
index 0f4363da..dfc2d994 100644
--- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
+++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -507,12 +507,14 @@
 
   void WaitForSystemWebAppInstall(Profile* profile) {
     base::RunLoop run_loop;
+
     web_app::WebAppProvider::GetForSystemWebApps(profile)
         ->system_web_app_manager()
         .on_apps_synchronized()
         .Post(FROM_HERE, base::BindLambdaForTesting([&]() {
-                // Wait one execution loop for on_apps_synchronized() to be
-                // called on all listeners.
+                // Wait one execution loop for
+                // on_apps_synchronized() to be called on all
+                // listeners.
                 base::ThreadTaskRunnerHandle::Get()->PostTask(
                     FROM_HERE, run_loop.QuitClosure());
               }));
@@ -523,7 +525,6 @@
     SystemWebAppManager& manager =
         web_app::WebAppProvider::GetForSystemWebApps(profile)
             ->system_web_app_manager();
-
     absl::optional<AppId> app_id =
         manager.GetAppIdForSystemApp(installation_->GetType());
     CHECK(app_id.has_value());
@@ -573,19 +574,21 @@
   // Login two users.
   LoginUser(account_id1_);
   base::RunLoop().RunUntilIdle();
-  chromeos::UserAddingScreen::Get()->Start();
-  AddUser(account_id2_);
-  base::RunLoop().RunUntilIdle();
 
   // Wait for System Apps to be installed on both user profiles.
   auto* user_manager = user_manager::UserManager::Get();
   Profile* profile1 = chromeos::ProfileHelper::Get()->GetProfileByUser(
       user_manager->FindUser(account_id1_));
+  WaitForSystemWebAppInstall(profile1);
+
+  installation_ =
+      TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+  chromeos::UserAddingScreen::Get()->Start();
+  AddUser(account_id2_);
+  base::RunLoop().RunUntilIdle();
   Profile* profile2 = chromeos::ProfileHelper::Get()->GetProfileByUser(
       user_manager->FindUser(account_id2_));
-  WaitForSystemWebAppInstall(profile1);
   WaitForSystemWebAppInstall(profile2);
-
   // Set user 1 to be active.
   user_manager->SwitchActiveUser(account_id1_);
   EXPECT_TRUE(multi_user_util::IsProfileFromActiveUser(profile1));
@@ -625,17 +628,20 @@
   // Login two users.
   LoginUser(account_id1_);
   base::RunLoop().RunUntilIdle();
-  chromeos::UserAddingScreen::Get()->Start();
-  AddUser(account_id2_);
-  base::RunLoop().RunUntilIdle();
 
   // Wait for System Apps to be installed on both user profiles.
   auto* user_manager = user_manager::UserManager::Get();
   Profile* profile1 = chromeos::ProfileHelper::Get()->GetProfileByUser(
       user_manager->FindUser(account_id1_));
+  WaitForSystemWebAppInstall(profile1);
+
+  installation_ =
+      TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation();
+  chromeos::UserAddingScreen::Get()->Start();
+  AddUser(account_id2_);
+  base::RunLoop().RunUntilIdle();
   Profile* profile2 = chromeos::ProfileHelper::Get()->GetProfileByUser(
       user_manager->FindUser(account_id2_));
-  WaitForSystemWebAppInstall(profile1);
   WaitForSystemWebAppInstall(profile2);
 
   g_browser_process->profile_manager()->ScheduleProfileForDeletion(
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 3513da31..e0b6441a 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -62,6 +62,7 @@
 #include "chrome/browser/ui/webui/version/version_ui.h"
 #include "chrome/browser/ui/webui/whats_new/whats_new_ui.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_manager.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
@@ -854,10 +855,12 @@
     return &NewWebUI<SysInternalsUI>;
   if (url.host_piece() == chrome::kChromeUIAssistantOptInHost)
     return &NewWebUI<chromeos::AssistantOptInUI>;
-  if (url.host_piece() == chromeos::kChromeUICameraAppHost &&
-      web_app::SystemWebAppManager::IsAppEnabled(
-          web_app::SystemAppType::CAMERA)) {
-    return &NewComponentUI<chromeos::CameraAppUI, ChromeCameraAppUIDelegate>;
+  if (url.host_piece() == chromeos::kChromeUICameraAppHost) {
+    auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile);
+    if (provider && provider->system_web_app_manager().IsAppEnabled(
+                        web_app::SystemAppType::CAMERA)) {
+      return &NewComponentUI<chromeos::CameraAppUI, ChromeCameraAppUIDelegate>;
+    }
   }
   if (url.host_piece() == chrome::kChromeUINearbyInternalsHost)
     return &NewWebUI<NearbyInternalsUI>;
diff --git a/chrome/browser/ui/webui/history_clusters/memories_ui.cc b/chrome/browser/ui/webui/history_clusters/memories_ui.cc
index 62c46aae..a960cb37 100644
--- a/chrome/browser/ui/webui/history_clusters/memories_ui.cc
+++ b/chrome/browser/ui/webui/history_clusters/memories_ui.cc
@@ -41,7 +41,7 @@
   source->AddString("searchPrompt", u"Search clusters");
   source->AddString("titleDescription", u"Based on previous web activity");
   source->AddString("visitsSectionHeader", u"From Chrome History");
-  source->AddString("relatedSearchesSectionHeader", u"Try searching for");
+  source->AddString("relatedSearchesLabel", u"Related:");
   source->AddString("removeAllFromHistory", u"Remove all from history");
 
   webui::SetupWebUIDataSource(
diff --git a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
index 5d22fb9..fec9971 100644
--- a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
@@ -426,14 +426,6 @@
       l10n_util::GetStringFUTF16(
           IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_LOCATE,
           base::UTF8ToUTF16(plugin_vm::kChromeOSBaseDirectoryDisplayText)));
-  html_source->AddBoolean(
-      "showPluginVmCameraPermissions",
-      base::FeatureList::IsEnabled(
-          chromeos::features::kPluginVmShowCameraPermissions));
-  html_source->AddBoolean(
-      "showPluginVmMicrophonePermissions",
-      base::FeatureList::IsEnabled(
-          chromeos::features::kPluginVmShowMicrophonePermissions));
 }
 
 void AppsSection::UpdateAndroidSearchTags() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
index 79f7cfa..9d8a47a 100644
--- a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
@@ -222,6 +222,12 @@
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION},
       {"inputMethodOptionsXkbLayout",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_XKB_LAYOUT},
+      {"inputMethodOptionsZhuyinKeyboardLayout",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT},
+      {"inputMethodOptionsZhuyinSelectKeys",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS},
+      {"inputMethodOptionsZhuyinPageSize",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE},
       {"inputMethodOptionsEditUserDict",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_EDIT_USER_DICT},
       {"inputMethodOptionsPinyinChinesePunctuation",
@@ -244,6 +250,12 @@
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION_AGGRESSIVE},
       {"inputMethodOptionsUsKeyboard",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_US},
+      {"inputMethodOptionsZhuyinLayoutDefault",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT},
+      {"inputMethodOptionsZhuyinLayoutIBM",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM},
+      {"inputMethodOptionsZhuyinLayoutEten",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN},
       {"inputMethodOptionsDvorakKeyboard",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_DVORAK},
       {"inputMethodOptionsColemakKeyboard",
diff --git a/chrome/browser/ui/webui/tab_search/tab_search.mojom b/chrome/browser/ui/webui/tab_search/tab_search.mojom
index 9b37079..0e6fefd7 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search.mojom
+++ b/chrome/browser/ui/webui/tab_search/tab_search.mojom
@@ -4,15 +4,16 @@
 
 module tab_search.mojom;
 
+import "components/tab_groups/public/mojom/tab_group_types.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/token.mojom";
-import "components/tab_groups/public/mojom/tab_group_types.mojom";
 
 // Collection of window details associated with a profile.
 struct ProfileData {
   array<Window> windows;
-  array<RecentlyClosedTab> recently_closed_tabs;
   array<TabGroup> tab_groups;
+  array<RecentlyClosedTab> recently_closed_tabs;
+  array<RecentlyClosedTabGroup> recently_closed_tab_groups;
 };
 
 // Properties and tabs associated with a window.
@@ -63,11 +64,21 @@
   string last_active_elapsed_text;
 };
 
-// Information about a recently closed tab.
+// Information about a recently closed tab. Recently closed tabs that were
+// closed as part of closing a group will contain a session id belonging to
+// the group while recently closed tabs that were closed individually will
+// contain a group id that associates them with either an open or no longer
+// present tab group.
 struct RecentlyClosedTab {
   // The unique identifier of the tab.
   int32 tab_id;
 
+  // The session identifier of the tab's group.
+  int32 session_id;
+
+  // The group identifier of the tab.
+  mojo_base.mojom.Token? group_id;
+
   // The title of the tab.
   string title;
 
@@ -95,6 +106,28 @@
   string title;
 };
 
+// Information about a recently closed tab group.
+struct RecentlyClosedTabGroup {
+  // The unique identifier of the tab group that is only valid for the duration
+  // of the session.
+  int32 session_id;
+
+  // The color of the tab group.
+  tab_groups.mojom.Color color;
+
+  // The title of the tab group.
+  string title;
+
+  // A count of tabs that belong to the tab group.
+  uint32 tab_count;
+
+  // Elapsed time since the group was closed.
+  mojo_base.mojom.Time last_active_time;
+
+  // String representing the elapsed time since the group was closed.
+  string last_active_elapsed_text;
+};
+
 // Information about switching to a tab.
 struct SwitchToTabInfo {
   int32 tab_id;
@@ -118,8 +151,8 @@
   // Switch to a specific tab.
   SwitchToTab(SwitchToTabInfo switch_to_tab_info);
 
-  // Open a recently closed tab.
-  OpenRecentlyClosedTab(int32 tab_id);
+  // Open a recently closed tab or tab group.
+  OpenRecentlyClosedEntry(int32 session_id);
 
   // Notify the backend that the UI is ready to be shown.
   ShowUI();
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index da7fbe6..1afcd727 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -152,7 +152,7 @@
   details.browser->window()->Activate();
 }
 
-void TabSearchPageHandler::OpenRecentlyClosedTab(int32_t tab_id) {
+void TabSearchPageHandler::OpenRecentlyClosedEntry(int32_t session_id) {
   sessions::TabRestoreService* tab_restore_service =
       TabRestoreServiceFactory::GetForProfile(Profile::FromWebUI(web_ui_));
   if (!tab_restore_service)
@@ -163,7 +163,7 @@
   tab_restore_service->RestoreEntryById(
       BrowserLiveTabContext::FindContextForWebContents(
           active_browser->tab_strip_model()->GetActiveWebContents()),
-      SessionID::FromSerializedValue(tab_id),
+      SessionID::FromSerializedValue(session_id),
       WindowOpenDisposition::NEW_FOREGROUND_TAB);
 }
 
@@ -180,6 +180,7 @@
     return profile_data;
 
   std::set<std::string> tab_urls;
+  std::set<tab_groups::TabGroupId> tab_group_ids;
   for (auto* browser : *BrowserList::GetInstance()) {
     if (!ShouldTrackBrowser(browser))
       continue;
@@ -208,54 +209,112 @@
       tab_group->id = tab_group_id.token();
       tab_group->title = base::UTF16ToUTF8(tab_group_visual_data->title());
       tab_group->color = tab_group_visual_data->color();
+
+      tab_group_ids.insert(tab_group_id);
       profile_data->tab_groups.push_back(std::move(tab_group));
     }
   }
 
-  AddRecentlyClosedTabs(profile_data->recently_closed_tabs, tab_urls);
-  DCHECK(features::kTabSearchRecentlyClosedMaxEntries.Get() >= 0);
-  DCHECK(profile_data->recently_closed_tabs.size() <=
-         static_cast<unsigned int>(
-             features::kTabSearchRecentlyClosedMaxEntries.Get()));
+  AddRecentlyClosedEntries(profile_data->recently_closed_tabs,
+                           profile_data->recently_closed_tab_groups,
+                           tab_group_ids, profile_data->tab_groups, tab_urls);
+  DCHECK(features::kTabSearchRecentlyClosedTabCountThreshold.Get() >= 0);
   return profile_data;
 }
 
-void TabSearchPageHandler::AddRecentlyClosedTabs(
+void TabSearchPageHandler::AddRecentlyClosedEntries(
     std::vector<tab_search::mojom::RecentlyClosedTabPtr>& recently_closed_tabs,
+    std::vector<tab_search::mojom::RecentlyClosedTabGroupPtr>&
+        recently_closed_tab_groups,
+    std::set<tab_groups::TabGroupId>& tab_group_ids,
+    std::vector<tab_search::mojom::TabGroupPtr>& tab_groups,
     std::set<std::string>& tab_urls) {
   sessions::TabRestoreService* tab_restore_service =
       TabRestoreServiceFactory::GetForProfile(Profile::FromWebUI(web_ui_));
-  const size_t kMaxTabCount =
-      static_cast<size_t>(features::kTabSearchRecentlyClosedMaxEntries.Get());
   if (tab_restore_service) {
-    // Flatten tab restore service entries into tabs. Ignore any entries that
-    // match URLs that are currently open.
+    const int kRecentlyClosedTabCountThreshold = static_cast<size_t>(
+        features::kTabSearchRecentlyClosedTabCountThreshold.Get());
+    int recently_closed_tab_count = 0;
+    // The minimum number of desired recently closed items (tab or group) to be
+    // shown in the 'Recently Closed' section of the UI.
+    const int kMinRecentlyClosedItemDisplayCount = static_cast<size_t>(
+        features::kTabSearchRecentlyClosedDefaultItemDisplayCount.Get());
+    int recently_closed_item_count = 0;
+
+    // Attempt to add as many recently closed items as necessary to support the
+    // default item display count. On reaching this minimum, keep adding
+    // items until we have reached or exceeded a tab count threshold value.
+    // Ignore any entries that match URLs that are currently open.
     for (auto& entry : tab_restore_service->entries()) {
+      if (recently_closed_item_count >= kMinRecentlyClosedItemDisplayCount &&
+          recently_closed_tab_count >= kRecentlyClosedTabCountThreshold) {
+        return;
+      }
+
       if (entry->type == sessions::TabRestoreService::Type::WINDOW) {
         sessions::TabRestoreService::Window* window =
             static_cast<sessions::TabRestoreService::Window*>(entry.get());
         for (auto& tab : window->tabs) {
-          if (!AddRecentlyClosedTab(recently_closed_tabs, tab.get(), tab_urls,
-                                    kMaxTabCount)) {
+          AddRecentlyClosedTab(recently_closed_tabs, tab.get(), tab_urls, 0);
+          recently_closed_tab_count += 1;
+          recently_closed_item_count += 1;
+
+          if (recently_closed_item_count >=
+                  kMinRecentlyClosedItemDisplayCount &&
+              recently_closed_tab_count >= kRecentlyClosedTabCountThreshold) {
             return;
           }
         }
       } else if (entry->type == sessions::TabRestoreService::Type::TAB) {
         sessions::TabRestoreService::Tab* tab =
             static_cast<sessions::TabRestoreService::Tab*>(entry.get());
-        if (!AddRecentlyClosedTab(recently_closed_tabs, tab, tab_urls,
-                                  kMaxTabCount)) {
-          return;
+
+        // If a recently closed tab is associated to a group that is no longer
+        // open we create TabGroup entry with the required fields to support
+        // rendering the tab's associated group information in the UI.
+        if (tab->group.has_value() &&
+            !base::Contains(tab_group_ids, tab->group.value())) {
+          tab_groups::TabGroupId tab_group_id = tab->group.value();
+          const tab_groups::TabGroupVisualData* tab_group_visual_data =
+              &tab->group_visual_data.value();
+          auto tab_group = tab_search::mojom::TabGroup::New();
+          tab_group->id = tab_group_id.token();
+          tab_group->color = tab_group_visual_data->color();
+          tab_group->title = base::UTF16ToUTF8(tab_group_visual_data->title());
+
+          tab_group_ids.insert(tab_group_id);
+          tab_groups.push_back(std::move(tab_group));
         }
+
+        AddRecentlyClosedTab(recently_closed_tabs, tab, tab_urls, 0);
+        recently_closed_tab_count += 1;
+        recently_closed_item_count += 1;
       } else if (entry->type == sessions::TabRestoreService::Type::GROUP) {
         sessions::TabRestoreService::Group* group =
             static_cast<sessions::TabRestoreService::Group*>(entry.get());
+
+        const tab_groups::TabGroupVisualData* tab_group_visual_data =
+            &group->visual_data;
+        auto recently_closed_tab_group =
+            tab_search::mojom::RecentlyClosedTabGroup::New();
+        recently_closed_tab_group->session_id = entry->id.id();
+        recently_closed_tab_group->color = tab_group_visual_data->color();
+        recently_closed_tab_group->title =
+            base::UTF16ToUTF8(tab_group_visual_data->title());
+        recently_closed_tab_group->tab_count = group->tabs.size();
+        recently_closed_tab_group->last_active_time = entry->timestamp;
+        recently_closed_tab_group->last_active_elapsed_text =
+            GetLastActiveElapsedText(entry->timestamp);
+        recently_closed_tab_groups.push_back(
+            std::move(recently_closed_tab_group));
+
         for (auto& tab : group->tabs) {
-          if (!AddRecentlyClosedTab(recently_closed_tabs, tab.get(), tab_urls,
-                                    kMaxTabCount)) {
-            return;
-          }
+          AddRecentlyClosedTab(recently_closed_tabs, tab.get(), tab_urls,
+                               group->id.id());
+          recently_closed_tab_count += 1;
         }
+        // Restored recently closed tab groups map to a single display item.
+        recently_closed_item_count += 1;
       }
     }
   }
@@ -265,10 +324,7 @@
     std::vector<tab_search::mojom::RecentlyClosedTabPtr>& recently_closed_tabs,
     sessions::TabRestoreService::Tab* tab,
     std::set<std::string>& tab_urls,
-    size_t max_tab_count) {
-  if (recently_closed_tabs.size() >= max_tab_count)
-    return false;
-
+    int32_t session_id) {
   if (tab->navigations.size() == 0)
     return true;
 
@@ -286,7 +342,11 @@
   if (tab_urls.count(recently_closed_tab->url))
     return true;
 
+  if (session_id)
+    recently_closed_tab->session_id = session_id;
+
   tab_urls.insert(recently_closed_tab->url);
+
   recently_closed_tabs.push_back(std::move(recently_closed_tab));
 
   return true;
@@ -350,6 +410,11 @@
   recently_closed_tab->last_active_time_ticks = last_active_time_ticks;
   recently_closed_tab->last_active_elapsed_text =
       GetLastActiveElapsedText(last_active_time_ticks);
+
+  if (tab->group.has_value()) {
+    recently_closed_tab->group_id = tab->group.value().token();
+  }
+
   return recently_closed_tab;
 }
 
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
index 6114edd8..02bda4d 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -50,7 +50,7 @@
   void GetProfileData(GetProfileDataCallback callback) override;
   void SwitchToTab(
       tab_search::mojom::SwitchToTabInfoPtr switch_to_tab_info) override;
-  void OpenRecentlyClosedTab(int32_t tab_id) override;
+  void OpenRecentlyClosedEntry(int32_t session_id) override;
   void ShowUI() override;
   // TODO(tluk): Remove this once all uses of the CloseUI() interface are
   // removed from the Tab Search WebUI code.
@@ -87,10 +87,14 @@
 
   tab_search::mojom::ProfileDataPtr CreateProfileData();
 
-  // Adds recently closed tabs in a flattened list.
-  void AddRecentlyClosedTabs(
+  // Adds recently closed tabs and tab groups.
+  void AddRecentlyClosedEntries(
       std::vector<tab_search::mojom::RecentlyClosedTabPtr>&
           recently_closed_tabs,
+      std::vector<tab_search::mojom::RecentlyClosedTabGroupPtr>&
+          recently_closed_tab_groups,
+      std::set<tab_groups::TabGroupId>& tab_group_ids,
+      std::vector<tab_search::mojom::TabGroupPtr>& tab_groups,
       std::set<std::string>& tab_urls);
 
   // Tries to add a single recently closed tab to a flattened list. Returns
@@ -100,7 +104,7 @@
           recently_closed_tabs,
       sessions::TabRestoreService::Tab* tab,
       std::set<std::string>& tab_urls,
-      size_t max_tab_count);
+      int32_t session_id);
 
   tab_search::mojom::TabPtr GetTab(TabStripModel* tab_strip_model,
                                    content::WebContents* contents,
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
index 7f5f343..99d9be4 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
@@ -292,7 +292,11 @@
   handler()->GetProfileData(std::move(callback3));
 }
 
-TEST_F(TabSearchPageHandlerTest, GetTabsAndGroups) {
+TEST_F(TabSearchPageHandlerTest, TabsAndGroups) {
+  TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
+      profile(),
+      base::BindRepeating(&TabSearchPageHandlerTest::GetTabRestoreService));
+
   // Add tabs to a browser.
   AddTabWithTitle(browser1(), GURL(kTabUrl1), kTabName1);
   AddTabWithTitle(browser1(), GURL(kTabUrl2), kTabName2);
@@ -300,8 +304,6 @@
   TabStripModel* tab_strip_model = browser1()->tab_strip_model();
   TabGroupModel* tab_group_model = tab_strip_model->group_model();
 
-  EXPECT_CALL(page_, TabUpdated(_)).Times(1);
-  EXPECT_CALL(page_, TabsRemoved(_)).Times(1);
   // Associate a tab to a given tab group.
   tab_groups::TabGroupId group1 = tab_strip_model->AddToNewGroup({0});
 
@@ -326,6 +328,96 @@
             ASSERT_EQ(base::UTF16ToUTF8(sample_title), tab_group->title);
           });
   handler()->GetProfileData(std::move(callback1));
+
+  // Close a group's tab.
+  int tab_id = extensions::ExtensionTabUtil::GetTabId(
+      browser1()->tab_strip_model()->GetWebContentsAt(0));
+  handler()->CloseTab(tab_id);
+
+  // Assert the closed tab's data is correct in ProfileData.
+  tab_search::mojom::PageHandler::GetProfileDataCallback callback2 =
+      base::BindLambdaForTesting(
+          [&](tab_search::mojom::ProfileDataPtr profile_tabs) {
+            ASSERT_EQ(2u, profile_tabs->windows.size());
+            auto* window1 = profile_tabs->windows[0].get();
+            ASSERT_TRUE(window1->active);
+            ASSERT_EQ(1u, window1->tabs.size());
+
+            auto& tab_groups = profile_tabs->tab_groups;
+            ASSERT_EQ(1u, tab_groups.size());
+            tab_search::mojom::TabGroup* tab_group = tab_groups[0].get();
+            ASSERT_EQ(sample_color, tab_group->color);
+            ASSERT_EQ(base::UTF16ToUTF8(sample_title), tab_group->title);
+
+            auto& recently_closed_tabs = profile_tabs->recently_closed_tabs;
+            ASSERT_EQ(1u, recently_closed_tabs.size());
+            tab_search::mojom::RecentlyClosedTab* tab =
+                recently_closed_tabs[0].get();
+            ExpectRecentlyClosedTab(tab, kTabUrl2, kTabName2);
+            ASSERT_TRUE(tab->group_id);
+            ASSERT_EQ(tab_group->id, tab->group_id);
+          });
+  handler()->GetProfileData(std::move(callback2));
+
+  EXPECT_CALL(page_, TabUpdated(_)).Times(1);
+  EXPECT_CALL(page_, TabsRemoved(_)).Times(2);
+}
+
+TEST_F(TabSearchPageHandlerTest, RecentlyClosedTabGroup) {
+  TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
+      profile(),
+      base::BindRepeating(&TabSearchPageHandlerTest::GetTabRestoreService));
+
+  // Add tabs to a browser.
+  AddTabWithTitle(browser1(), GURL(kTabUrl1), kTabName1);
+  AddTabWithTitle(browser1(), GURL(kTabUrl2), kTabName2);
+
+  TabStripModel* tab_strip_model = browser1()->tab_strip_model();
+  TabGroupModel* tab_group_model = tab_strip_model->group_model();
+
+  // Associate a tab to a given tab group.
+  tab_groups::TabGroupId group1 = tab_strip_model->AddToNewGroup({0});
+
+  std::u16string sample_title = u"Sample title";
+  const tab_groups::TabGroupColorId sample_color =
+      tab_groups::TabGroupColorId::kGrey;
+  tab_groups::TabGroupVisualData visual_data1(sample_title, sample_color);
+  tab_group_model->GetTabGroup(group1)->SetVisualData(visual_data1);
+
+  // Close a group and its tabs.
+  tab_strip_model->CloseAllTabsInGroup(group1);
+
+  // Assert the closed tab group and tab data is correct in ProfileData.
+  tab_search::mojom::PageHandler::GetProfileDataCallback callback =
+      base::BindLambdaForTesting(
+          [&](tab_search::mojom::ProfileDataPtr profile_tabs) {
+            ASSERT_EQ(2u, profile_tabs->windows.size());
+            auto* window1 = profile_tabs->windows[0].get();
+            ASSERT_TRUE(window1->active);
+            ASSERT_EQ(1u, window1->tabs.size());
+
+            ASSERT_EQ(0u, profile_tabs->tab_groups.size());
+
+            auto& recently_closed_tab_groups =
+                profile_tabs->recently_closed_tab_groups;
+            ASSERT_EQ(1u, recently_closed_tab_groups.size());
+            tab_search::mojom::RecentlyClosedTabGroup* tab_group =
+                recently_closed_tab_groups[0].get();
+            ASSERT_EQ(sample_color, tab_group->color);
+            ASSERT_EQ(base::UTF16ToUTF8(sample_title), tab_group->title);
+
+            auto& recently_closed_tabs = profile_tabs->recently_closed_tabs;
+            ASSERT_EQ(1u, recently_closed_tabs.size());
+            tab_search::mojom::RecentlyClosedTab* tab =
+                recently_closed_tabs[0].get();
+            ExpectRecentlyClosedTab(tab, kTabUrl2, kTabName2);
+            ASSERT_TRUE(tab->group_id);
+            ASSERT_EQ(tab_group->session_id, tab->session_id);
+          });
+  handler()->GetProfileData(std::move(callback));
+
+  EXPECT_CALL(page_, TabUpdated(_)).Times(1);
+  EXPECT_CALL(page_, TabsRemoved(_)).Times(2);
 }
 
 // Ensure that repeated tab model changes do not result in repeated calls to
@@ -460,7 +552,7 @@
             tab_id = recently_closed_tabs[0]->tab_id;
           });
   handler()->GetProfileData(std::move(callback1));
-  handler()->OpenRecentlyClosedTab(tab_id);
+  handler()->OpenRecentlyClosedEntry(tab_id);
   tab_search::mojom::PageHandler::GetProfileDataCallback callback2 =
       base::BindLambdaForTesting(
           [&](tab_search::mojom::ProfileDataPtr profile_tabs) {
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index 2288f7ca..8ca4104 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -46,6 +46,9 @@
       {"a11yOpenTab", IDS_TAB_SEARCH_A11Y_OPEN_TAB},
       {"a11yRecentlyClosedTab", IDS_TAB_SEARCH_A11Y_RECENTLY_CLOSED_TAB},
       {"openTabs", IDS_TAB_SEARCH_OPEN_TABS},
+      {"oneTab", IDS_TAB_SEARCH_ONE_TAB},
+      {"tabCount", IDS_TAB_SEARCH_TAB_COUNT},
+      {"recentlyClosed", IDS_TAB_SEARCH_RECENTLY_CLOSED},
       {"recentlyClosedTabs", IDS_TAB_SEARCH_RECENTLY_CLOSED_TABS},
   };
   source->AddLocalizedStrings(kStrings);
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos.cc b/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
index 5dcc47cd..6f9b456 100644
--- a/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_chromeos.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
+#include "chrome/browser/apps/app_service/menu_item_constants.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/arc_web_contents_data.h"
diff --git a/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc b/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
index 80428fd4..a5abe740 100644
--- a/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_publisher_host.cc
@@ -4,11 +4,16 @@
 
 #include "chrome/browser/web_applications/app_service/web_apps_publisher_host.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/one_shot_event.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
+#include "chrome/browser/apps/app_service/menu_item_constants.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/web_applications/components/app_icon_manager.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -168,6 +173,70 @@
   return publisher_helper().SetWindowMode(app_id, window_mode);
 }
 
+void WebAppsPublisherHost::GetMenuModel(const std::string& app_id,
+                                        GetMenuModelCallback callback) {
+  const WebApp* web_app = GetWebApp(app_id);
+  auto menu_items = crosapi::mojom::MenuItems::New();
+  if (!web_app) {
+    std::move(callback).Run(std::move(menu_items));
+    return;
+  }
+
+  // Read shortcuts menu item icons from disk, if any.
+  if (!web_app->shortcuts_menu_item_infos().empty()) {
+    provider_->icon_manager().ReadAllShortcutsMenuIcons(
+        app_id, base::BindOnce(&WebAppsPublisherHost::OnShortcutsMenuIconsRead,
+                               weak_ptr_factory_.GetWeakPtr(), app_id,
+                               std::move(menu_items), std::move(callback)));
+  } else {
+    std::move(callback).Run(std::move(menu_items));
+  }
+}
+
+void WebAppsPublisherHost::OnShortcutsMenuIconsRead(
+    const std::string& app_id,
+    crosapi::mojom::MenuItemsPtr menu_items,
+    GetMenuModelCallback callback,
+    ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps) {
+  const WebApp* web_app = GetWebApp(app_id);
+  if (!web_app) {
+    std::move(callback).Run(crosapi::mojom::MenuItems::New());
+    return;
+  }
+
+  size_t menu_item_index = 0;
+
+  for (const WebApplicationShortcutsMenuItemInfo& menu_item_info :
+       web_app->shortcuts_menu_item_infos()) {
+    const std::map<SquareSizePx, SkBitmap>* menu_item_icon_bitmaps = nullptr;
+    if (menu_item_index < shortcuts_menu_icon_bitmaps.size()) {
+      // We prefer |MASKABLE| icons, but fall back to icons with purpose |ANY|.
+      menu_item_icon_bitmaps =
+          &shortcuts_menu_icon_bitmaps[menu_item_index].maskable;
+      if (menu_item_icon_bitmaps->empty()) {
+        menu_item_icon_bitmaps =
+            &shortcuts_menu_icon_bitmaps[menu_item_index].any;
+      }
+    }
+
+    gfx::ImageSkia icon;
+    if (menu_item_icon_bitmaps) {
+      icon = apps::ConvertIconBitmapsToImageSkia(
+          *menu_item_icon_bitmaps,
+          /*size_hint_in_dip=*/apps::kAppShortcutIconSizeDip);
+    }
+
+    auto menu_item = crosapi::mojom::MenuItem::New();
+    menu_item->label = base::UTF16ToUTF8(menu_item_info.name);
+    menu_item->image = icon;
+    menu_items->items.push_back(std::move(menu_item));
+
+    ++menu_item_index;
+  }
+
+  std::move(callback).Run(std::move(menu_items));
+}
+
 void WebAppsPublisherHost::OnWebAppInstalled(const AppId& app_id) {
   const WebApp* web_app = GetWebApp(app_id);
   if (!web_app) {
diff --git a/chrome/browser/web_applications/app_service/web_apps_publisher_host.h b/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
index 9862a0e..85f195d 100644
--- a/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
+++ b/chrome/browser/web_applications/app_service/web_apps_publisher_host.h
@@ -106,6 +106,8 @@
                  bool report_abuse) override;
   void PauseApp(const std::string& app_id) override;
   void UnpauseApp(const std::string& app_id) override;
+  void GetMenuModel(const std::string& app_id,
+                    GetMenuModelCallback callback) override;
 
   // WebAppPublisherHelper::Delegate:
   void PublishWebApps(std::vector<apps::mojom::AppPtr> apps) override;
@@ -136,6 +138,12 @@
                               absl::optional<bool> accessing_camera,
                               absl::optional<bool> accessing_microphone);
 
+  void OnShortcutsMenuIconsRead(
+      const std::string& app_id,
+      crosapi::mojom::MenuItemsPtr menu_items,
+      GetMenuModelCallback callback,
+      ShortcutsMenuIconBitmaps shortcuts_menu_icon_bitmaps);
+
   Profile* const profile_;
   WebAppProvider* const provider_;
   WebAppPublisherHelper publisher_helper_;
diff --git a/chrome/browser/web_applications/components/app_shortcut_manager.cc b/chrome/browser/web_applications/components/app_shortcut_manager.cc
index e267837..4f3033b 100644
--- a/chrome/browser/web_applications/components/app_shortcut_manager.cc
+++ b/chrome/browser/web_applications/components/app_shortcut_manager.cc
@@ -27,10 +27,6 @@
 constexpr const char* kCreationResultMetric =
     "WebApp.Shortcuts.Creation.Result";
 
-// UMA metric name for shortcuts deletion result.
-constexpr const char* kDeletionResultMetric =
-    "WebApp.Shortcuts.Deletion.Success";
-
 // Result of shortcuts creation process.
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
@@ -199,7 +195,6 @@
                                             DeleteShortcutsCallback callback,
                                             bool success) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  UMA_HISTOGRAM_BOOLEAN(kDeletionResultMetric, success);
 
   std::move(callback).Run(success);
 }
diff --git a/chrome/browser/web_applications/components/external_install_options.cc b/chrome/browser/web_applications/components/external_install_options.cc
index 328a4373..517239c 100644
--- a/chrome/browser/web_applications/components/external_install_options.cc
+++ b/chrome/browser/web_applications/components/external_install_options.cc
@@ -74,7 +74,6 @@
         options.uninstall_and_replace,
         options.additional_search_terms,
         options.only_use_app_info_factory,
-        options.app_info_factory,
         options.system_app_type,
         options.oem_installed,
         options.disable_if_touchscreen_with_stylus_not_supported
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 5a9a07e..7498389 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -13,7 +13,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/banners/app_banner_manager_desktop.h"
-#include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_icon_generator.h"
 #include "chrome/browser/web_applications/components/web_application_info.h"
 #include "chrome/common/chrome_features.h"
@@ -497,4 +496,43 @@
   return uninstall_source;
 }
 
+// TODO(loyso): Call sites should specify Source explicitly as a part of
+// AppTraits parameter object.
+Source::Type InferSourceFromMetricsInstallSource(
+    webapps::WebappInstallSource install_source) {
+  switch (install_source) {
+    case webapps::WebappInstallSource::MENU_BROWSER_TAB:
+    case webapps::WebappInstallSource::MENU_CUSTOM_TAB:
+    case webapps::WebappInstallSource::AUTOMATIC_PROMPT_BROWSER_TAB:
+    case webapps::WebappInstallSource::AUTOMATIC_PROMPT_CUSTOM_TAB:
+    case webapps::WebappInstallSource::API_BROWSER_TAB:
+    case webapps::WebappInstallSource::API_CUSTOM_TAB:
+    case webapps::WebappInstallSource::DEVTOOLS:
+    case webapps::WebappInstallSource::MANAGEMENT_API:
+    case webapps::WebappInstallSource::AMBIENT_BADGE_BROWSER_TAB:
+    case webapps::WebappInstallSource::AMBIENT_BADGE_CUSTOM_TAB:
+    case webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON:
+    case webapps::WebappInstallSource::SYNC:
+    case webapps::WebappInstallSource::MENU_CREATE_SHORTCUT:
+      return Source::kSync;
+
+    case webapps::WebappInstallSource::INTERNAL_DEFAULT:
+    case webapps::WebappInstallSource::EXTERNAL_DEFAULT:
+      return Source::kDefault;
+
+    case webapps::WebappInstallSource::EXTERNAL_POLICY:
+      return Source::kPolicy;
+
+    case webapps::WebappInstallSource::SYSTEM_DEFAULT:
+      return Source::kSystem;
+
+    case webapps::WebappInstallSource::ARC:
+      return Source::kWebAppStore;
+
+    case webapps::WebappInstallSource::COUNT:
+      NOTREACHED();
+      return Source::kSync;
+  }
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.h b/chrome/browser/web_applications/components/web_app_install_utils.h
index b28728c..41408ce 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.h
+++ b/chrome/browser/web_applications/components/web_app_install_utils.h
@@ -9,6 +9,7 @@
 #include <set>
 #include <vector>
 
+#include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "url/gurl.h"
 
 struct WebApplicationInfo;
@@ -29,9 +30,6 @@
 
 namespace web_app {
 
-enum class ExternalInstallSource;
-enum class InstallResultCode;
-
 enum class ForInstallableSite {
   kYes,
   kNo,
@@ -72,6 +70,9 @@
 webapps::WebappUninstallSource ConvertExternalInstallSourceToUninstallSource(
     ExternalInstallSource external_install_source);
 
+Source::Type InferSourceFromMetricsInstallSource(
+    webapps::WebappInstallSource install_source);
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_INSTALL_UTILS_H_
diff --git a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
index 803af818..b10d012 100644
--- a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/json/json_reader.h"
 #include "base/run_loop.h"
+#include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/browser_prefs.h"
@@ -18,12 +19,16 @@
 #include "chrome/browser/web_applications/components/externally_managed_app_manager.h"
 #include "chrome/browser/web_applications/components/policy/web_app_policy_constants.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_install_utils.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager_observer.h"
 #include "chrome/browser/web_applications/test/test_app_registry_controller.h"
-#include "chrome/browser/web_applications/test/test_externally_managed_app_manager.h"
+#include "chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h"
 #include "chrome/browser/web_applications/test/test_os_integration_manager.h"
 #include "chrome/browser/web_applications/test/test_web_app_provider.h"
+#include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/scoped_testing_local_state.h"
@@ -218,6 +223,25 @@
   return options;
 }
 
+std::unique_ptr<WebApp> CreateWebApp(const GURL& start_url,
+                                     Source::Type source_type) {
+  const AppId app_id = GenerateAppIdFromURL(start_url);
+
+  auto web_app = std::make_unique<WebApp>(app_id);
+  web_app->SetStartUrl(start_url);
+  web_app->SetName("App Name");
+  web_app->AddSource(source_type);
+  web_app->SetDisplayMode(DisplayMode::kStandalone);
+  web_app->SetUserDisplayMode(DisplayMode::kStandalone);
+  return web_app;
+}
+
+Source::Type ConvertExternalInstallSourceToSourceType(
+    ExternalInstallSource external_install_source) {
+  return InferSourceFromMetricsInstallSource(
+      ConvertExternalInstallSourceToInstallSource(external_install_source));
+}
+
 }  // namespace
 
 class WebAppPolicyManagerTest : public ChromeRenderViewHostTestHarness {
@@ -233,12 +257,16 @@
 
     auto* provider = TestWebAppProvider::Get(profile());
 
-    auto test_app_registrar = std::make_unique<TestAppRegistrar>();
+    auto test_app_registrar =
+        std::make_unique<WebAppRegistrarMutable>(profile());
     test_app_registrar_ = test_app_registrar.get();
     provider->SetRegistrar(std::move(test_app_registrar));
 
+    externally_installed_app_prefs_ =
+        std::make_unique<ExternallyInstalledWebAppPrefs>(profile()->GetPrefs());
+
     auto test_externally_managed_app_manager =
-        std::make_unique<TestExternallyManagedAppManager>(test_app_registrar_);
+        std::make_unique<TestExternallyManagedAppManagerImpl>(profile());
     test_externally_managed_app_manager_ =
         test_externally_managed_app_manager.get();
     provider->SetExternallyManagedAppManager(
@@ -258,13 +286,48 @@
     web_app_policy_manager_ = web_app_policy_manager.get();
     provider->SetWebAppPolicyManager(std::move(web_app_policy_manager));
 
+    externally_managed_app_manager()->SetHandleInstallRequestCallback(
+        base::BindLambdaForTesting(
+            [this](const ExternalInstallOptions& install_options)
+                -> ExternallyManagedAppManager::InstallResult {
+              const GURL& install_url = install_options.install_url;
+              if (!app_registrar()->GetAppById(
+                      GenerateAppIdFromURL(install_url))) {
+                const auto install_source = install_options.install_source;
+                std::unique_ptr<WebApp> web_app = CreateWebApp(
+                    install_url,
+                    ConvertExternalInstallSourceToSourceType(install_source));
+                RegisterApp(std::move(web_app));
+
+                externally_installed_app_prefs().Insert(
+                    install_url, GenerateAppIdFromURL(install_url),
+                    install_source);
+              }
+              return {.code = install_result_code_};
+            }));
+    externally_managed_app_manager()->SetHandleUninstallRequestCallback(
+        base::BindLambdaForTesting(
+            [this](const GURL& app_url,
+                   ExternalInstallSource install_source) -> bool {
+              absl::optional<AppId> app_id =
+                  app_registrar()->LookupExternalAppId(app_url);
+              if (app_id) {
+                UnregisterApp(*app_id);
+              }
+              return true;
+            }));
+
     provider->Start();
   }
 
   void SimulatePreviouslyInstalledApp(GURL url,
                                       ExternalInstallSource install_source) {
-    externally_managed_app_manager()->SimulatePreviouslyInstalledApp(
-        url, install_source);
+    auto web_app = CreateWebApp(
+        url, ConvertExternalInstallSourceToSourceType(install_source));
+    RegisterApp(std::move(web_app));
+
+    externally_installed_app_prefs().Insert(url, GenerateAppIdFromURL(url),
+                                            install_source);
   }
 
   void AwaitPolicyManagerAppsSynchronized() {
@@ -282,13 +345,19 @@
   }
 
  protected:
-  TestExternallyManagedAppManager* externally_managed_app_manager() {
+  TestExternallyManagedAppManagerImpl* externally_managed_app_manager() {
     return test_externally_managed_app_manager_;
   }
 
+  WebAppRegistrar* app_registrar() { return test_app_registrar_; }
+
   WebAppPolicyManager* policy_manager() { return web_app_policy_manager_; }
   ScopedTestingLocalState testing_local_state_;
 
+  ExternallyInstalledWebAppPrefs& externally_installed_app_prefs() {
+    return *externally_installed_app_prefs_;
+  }
+
   void SetWebAppSettingsDictPref(const base::StringPiece pref) {
     base::JSONReader::ValueWithError result =
         base::JSONReader::ReadAndReturnValueWithError(
@@ -308,9 +377,32 @@
               expected_default.run_on_os_login_policy);
   }
 
+  void RegisterApp(std::unique_ptr<web_app::WebApp> web_app) {
+    web_app::AppId app_id = web_app->app_id();
+    DCHECK(!test_app_registrar_->GetAppById(app_id));
+    test_app_registrar_->registry().emplace(std::move(app_id),
+                                            std::move(web_app));
+  }
+
+  void UnregisterApp(const AppId& app_id) {
+    auto it = test_app_registrar_->registry().find(app_id);
+    DCHECK(it != test_app_registrar_->registry().end());
+
+    test_app_registrar_->registry().erase(it);
+  }
+
+  void SetInstallResultCode(InstallResultCode result_code) {
+    install_result_code_ = result_code;
+  }
+
  private:
-  TestAppRegistrar* test_app_registrar_ = nullptr;
-  TestExternallyManagedAppManager* test_externally_managed_app_manager_ =
+  InstallResultCode install_result_code_ =
+      InstallResultCode::kSuccessNewInstall;
+
+  WebAppRegistrarMutable* test_app_registrar_ = nullptr;
+  std::unique_ptr<ExternallyInstalledWebAppPrefs>
+      externally_installed_app_prefs_;
+  TestExternallyManagedAppManagerImpl* test_externally_managed_app_manager_ =
       nullptr;
   WebAppPolicyManager* web_app_policy_manager_ = nullptr;
 };
@@ -765,7 +857,7 @@
     base::Value list(base::Value::Type::LIST);
     list.Append(GetTabbedItem());
     list.Append(GetNoContainerItem());
-    externally_managed_app_manager()->SetInstallResultCode(
+    SetInstallResultCode(
         InstallResultCode::kCancelledOnWebAppProviderShuttingDown);
 
     profile()->GetPrefs()->Set(prefs::kWebAppInstallForceList, std::move(list));
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.cc b/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.cc
index 2f4d3c2..ef8eff9 100644
--- a/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.cc
+++ b/chrome/browser/web_applications/system_web_apps/system_web_app_delegate.cc
@@ -16,14 +16,17 @@
   return origin;
 }
 
-SystemWebAppDelegate::SystemWebAppDelegate(const SystemAppType type,
-                                           const std::string& internal_name,
-                                           const GURL& install_url,
-                                           Profile* profile)
+SystemWebAppDelegate::SystemWebAppDelegate(
+    const SystemAppType type,
+    const std::string& internal_name,
+    const GURL& install_url,
+    Profile* profile,
+    const OriginTrialsMap& origin_trials_map)
     : type_(type),
       internal_name_(internal_name),
       install_url_(install_url),
-      profile_(profile) {}
+      profile_(profile),
+      origin_trials_map_(origin_trials_map) {}
 
 SystemWebAppDelegate::~SystemWebAppDelegate() = default;
 
@@ -44,8 +47,8 @@
   return false;
 }
 
-OriginTrialsMap SystemWebAppDelegate::GetEnabledOriginTrials() const {
-  return {};
+const OriginTrialsMap& SystemWebAppDelegate::GetEnabledOriginTrials() const {
+  return origin_trials_map_;
 }
 
 std::vector<int> SystemWebAppDelegate::GetAdditionalSearchTerms() const {
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 cb04532df..935377874 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
@@ -13,96 +13,9 @@
 class Browser;
 
 namespace web_app {
+class SystemWebAppDelegate;
 
 using OriginTrialsMap = std::map<url::Origin, std::vector<std::string>>;
-using WebApplicationInfoFactory =
-    base::RepeatingCallback<std::unique_ptr<WebApplicationInfo>()>;
-
-// The configuration options for a System App.
-struct SystemAppInfo {
-  // When installing via a WebApplicationInfo, 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.
-  SystemAppInfo(const std::string& internal_name,
-                const GURL& install_url,
-                const WebApplicationInfoFactory& info_factory);
-  SystemAppInfo(const SystemAppInfo& other);
-  ~SystemAppInfo();
-
-  SystemAppType type;
-
-  // A developer-friendly name for, among other things, reporting metrics
-  // and interacting with tast tests. It should follow PascalCase
-  // convention, and have a corresponding entry in
-  // WebAppSystemAppInternalName histogram suffixes. The internal name
-  // shouldn't be changed afterwards.
-  std::string internal_name;
-
-  // The URL that the System App will be installed from.
-  GURL install_url;
-
-  // If specified, the apps in |uninstall_and_replace| will have their data
-  // migrated to this System App.
-  std::vector<AppId> uninstall_and_replace;
-
-  // Minimum window size in DIPs. Empty if the app does not have a minimum.
-  // TODO(https://github.com/w3c/manifest/issues/436): Replace with PWA manifest
-  // properties for window size.
-  gfx::Size minimum_window_size;
-
-  // If set, we allow only a single window for this app.
-  bool single_window = true;
-
-  // If set, when the app is launched through the File Handling Web API, we will
-  // include the file's directory in window.launchQueue as the first value.
-  bool include_launch_directory = false;
-
-  // Map from origin to enabled origin trial names for this app. For example,
-  // "chrome://sample-web-app/" to ["Frobulate"]. If set, we will enable the
-  // given origin trials when the corresponding origin is loaded in the app.
-  OriginTrialsMap enabled_origin_trials;
-
-  // Resource Ids for additional search terms.
-  std::vector<int> additional_search_terms;
-
-  // If set to false, this app will be hidden from the Chrome OS app launcher.
-  bool show_in_launcher = true;
-
-  // If set to false, this app will be hidden from the Chrome OS search.
-  bool show_in_search = true;
-
-  // If set to true, navigations (e.g. Omnibox URL, anchor link) to this app
-  // will open in the app's window instead of the navigation's context (e.g.
-  // browser tab).
-  bool capture_navigations = false;
-
-  // If set to false, the app will non-resizeable.
-  bool is_resizeable = true;
-
-  // If set to false, the surface of app will can be non-maximizable.
-  bool is_maximizable = true;
-
-  // If set to true, the App's window will have a tab-strip.
-  bool has_tab_strip = false;
-
-  // If set to false, the app will not have the reload button in minimal ui
-  // mode.
-  bool should_have_reload_button_in_minimal_ui = true;
-
-  // If set, allows the app to close the window through scripts, for example
-  // using `window.close()`.
-  bool allow_scripts_to_close_windows = false;
-
-  WebApplicationInfoFactory app_info_factory;
-
-  // Setup information to drive a background task.
-  absl::optional<SystemAppBackgroundTaskInfo> timer_info;
-
-  // If set, this function will be called to determine the default bounds
-  // (window location and size) when the app's window is created.
-  base::RepeatingCallback<gfx::Rect(Browser*)> get_default_bounds =
-      base::NullCallback();
-};
 
 // Use #if defined to avoid compiler error on unused function.
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -121,10 +34,13 @@
   // When installing via a WebApplicationInfo, 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(const SystemAppType type,
-                       const std::string& internal_name,
-                       const GURL& install_url,
-                       Profile* profile);
+  SystemWebAppDelegate(
+      const SystemAppType type,
+      const std::string& internal_name,
+      const GURL& install_url,
+      Profile* profile,
+      const OriginTrialsMap& origin_trials_map = OriginTrialsMap());
+
   SystemWebAppDelegate(const SystemWebAppDelegate& other) = delete;
   virtual ~SystemWebAppDelegate();
 
@@ -162,7 +78,7 @@
   // Map from origin to enabled origin trial names for this app. For example,
   // "chrome://sample-web-app/" to ["Frobulate"]. If set, we will enable the
   // given origin trials when the corresponding origin is loaded in the app.
-  virtual OriginTrialsMap GetEnabledOriginTrials() const;
+  const OriginTrialsMap& GetEnabledOriginTrials() const;
 
   // Resource Ids for additional search terms.
   virtual std::vector<int> GetAdditionalSearchTerms() const;
@@ -184,7 +100,7 @@
   // If false, the surface of app will can be non-maximizable.
   virtual bool ShouldAllowMaximize() const;
 
-  // If frue, the App's window will have a tab-strip.
+  // If true, the App's window will have a tab-strip.
   virtual bool ShouldHaveTabStrip() const;
 
   // If false, the app will not have the reload button in minimal ui
@@ -209,6 +125,7 @@
   std::string internal_name_;
   GURL install_url_;
   const Profile* profile_;
+  OriginTrialsMap origin_trials_map_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
index 223b403..cdf55a6 100644
--- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/version.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/web_applications/system_web_apps/system_web_app_background_task.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 // TODO(b/174811949): Hide behind ChromeOS build flag.
 #include "chrome/browser/ash/web_applications/chrome_camera_app_ui_constants.h"
@@ -107,8 +108,7 @@
 // bailing out.
 const int kInstallFailureAttempts = 3;
 
-base::flat_map<SystemAppType, SystemAppInfo> CreateSystemWebApps(
-    Profile* profile) {
+SystemAppDelegateMap CreateSystemWebApps(Profile* profile) {
   std::vector<std::unique_ptr<SystemWebAppDelegate>> info_vec;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // TODO(crbug.com/1051229): Currently unused, will be hooked up
@@ -144,273 +144,17 @@
   info_vec.emplace_back(std::make_unique<SampleSystemAppDelegate>(profile));
 #endif  // !defined(OFFICIAL_BUILD)
 
-  base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>> info_map;
+  SystemAppDelegateMap delegate_map;
   for (auto& info : info_vec) {
     if (info->IsAppEnabled() ||
         base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps)) {
-      info_map.emplace(info->GetType(), std::move(info));
+      delegate_map.emplace(info->GetType(), std::move(info));
     }
   }
-  // return info_map;
+  return delegate_map;
 #else
-  // return {};
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-  base::flat_map<SystemAppType, SystemAppInfo> infos;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-  // SystemAppInfo's |name| field should be defined. These names are persisted
-  // to logs and should not be renamed.
-  // If new names are added, update tool/metrics/histograms/histograms.xml:
-  // "SystemWebAppName"
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::CAMERA)) {
-    infos.emplace(
-        SystemAppType::CAMERA,
-        SystemAppInfo(
-            "Camera", GURL("chrome://camera-app/views/main.html"),
-            base::BindRepeating(&CreateWebAppInfoForCameraSystemWebApp)));
-    if (!profile->GetPrefs()->GetBoolean(
-            chromeos::prefs::kHasCameraAppMigratedToSWA)) {
-      infos.at(SystemAppType::CAMERA).uninstall_and_replace = {
-          extension_misc::kCameraAppId};
-    }
-    // We need "FileHandling" to use File Handling API to set launch directory.
-    infos.at(SystemAppType::CAMERA).enabled_origin_trials =
-        OriginTrialsMap({{GetOrigin("chrome://camera-app"),
-                          {"FileHandling", "IdleDetection"}}});
-    infos.at(SystemAppType::CAMERA).capture_navigations = true;
-
-    // Minimum height +32 for top bar height.
-    infos.at(SystemAppType::CAMERA).minimum_window_size = {
-        kChromeCameraAppMinimumWidth, kChromeCameraAppMinimumHeight + 32};
-
-    infos.at(SystemAppType::CAMERA).get_default_bounds =
-        base::BindRepeating(&GetDefaultBoundsForCameraApp);
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::DIAGNOSTICS)) {
-    infos.emplace(
-        SystemAppType::DIAGNOSTICS,
-        SystemAppInfo(
-            "Diagnostics", GURL("chrome://diagnostics"),
-            base::BindRepeating(&CreateWebAppInfoForDiagnosticsSystemWebApp)));
-    infos.at(SystemAppType::DIAGNOSTICS).minimum_window_size = {600, 390};
-    infos.at(SystemAppType::DIAGNOSTICS).show_in_launcher = false;
-  }
-
-  infos.emplace(
-      SystemAppType::SETTINGS,
-      SystemAppInfo(
-          "OSSettings", GURL(chrome::kChromeUIOSSettingsURL),
-          base::BindRepeating(&CreateWebAppInfoForOSSettingsSystemWebApp)));
-  infos.at(SystemAppType::SETTINGS).uninstall_and_replace = {
-      kSettingsAppId, ash::kInternalAppIdSettings};
-  // Large enough to see the heading text "Settings" in the top-left.
-  infos.at(SystemAppType::SETTINGS).minimum_window_size = {300, 100};
-  infos.at(SystemAppType::SETTINGS).capture_navigations = true;
-
-  infos.emplace(SystemAppType::CROSH,
-                SystemAppInfo("Crosh", GURL(chrome::kChromeUIUntrustedCroshURL),
-                              base::BindRepeating(
-                                  &CreateWebAppInfoForCroshSystemWebApp)));
-  infos.at(SystemAppType::CROSH).single_window = false;
-  infos.at(SystemAppType::CROSH).show_in_launcher = false;
-  infos.at(SystemAppType::CROSH).show_in_search = false;
-  infos.at(SystemAppType::CROSH).has_tab_strip = true;
-
-  infos.emplace(
-      SystemAppType::TERMINAL,
-      SystemAppInfo(
-          "Terminal", GURL(chrome::kChromeUIUntrustedTerminalURL),
-          base::BindRepeating(&CreateWebAppInfoForTerminalSystemWebApp)));
-  infos.at(SystemAppType::TERMINAL).single_window = false;
-  infos.at(SystemAppType::TERMINAL).has_tab_strip = true;
-  infos.at(SystemAppType::TERMINAL).get_default_bounds =
-      base::BindRepeating(&GetDefaultBoundsForTerminal);
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::HELP)) {
-    infos.emplace(
-        SystemAppType::HELP,
-        SystemAppInfo("Help", GURL("chrome://help-app/pwa.html"),
-                      base::BindRepeating(&CreateWebAppInfoForHelpWebApp)));
-    infos.at(SystemAppType::HELP).additional_search_terms = {
-        IDS_GENIUS_APP_NAME, IDS_HELP_APP_PERKS, IDS_HELP_APP_OFFERS};
-    infos.at(SystemAppType::HELP).minimum_window_size = {600, 320};
-    infos.at(SystemAppType::HELP).capture_navigations = true;
-    infos.at(SystemAppType::HELP).get_default_bounds =
-        base::BindRepeating(&GetDefaultBoundsForHelpApp);
-    if (base::FeatureList::IsEnabled(
-            chromeos::features::kHelpAppBackgroundPage)) {
-      infos.at(SystemAppType::HELP).timer_info = SystemAppBackgroundTaskInfo(
-          absl::nullopt, GURL("chrome://help-app/background"),
-          /*open_immediately=*/true);
-    }
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::MEDIA)) {
-    infos.emplace(
-        SystemAppType::MEDIA,
-        SystemAppInfo("Media", GURL("chrome://media-app/pwa.html"),
-                      base::BindRepeating(&CreateWebAppInfoForMediaWebApp)));
-    infos.at(SystemAppType::MEDIA).include_launch_directory = true;
-    infos.at(SystemAppType::MEDIA).show_in_launcher = false;
-    infos.at(SystemAppType::MEDIA).show_in_search = false;
-    infos.at(SystemAppType::MEDIA).capture_navigations = true;
-    infos.at(SystemAppType::MEDIA).enabled_origin_trials =
-        OriginTrialsMap({{GetOrigin("chrome://media-app"), {"FileHandling"}}});
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::PRINT_MANAGEMENT)) {
-    infos.emplace(
-        SystemAppType::PRINT_MANAGEMENT,
-        SystemAppInfo(
-            "PrintManagement", GURL("chrome://print-management/pwa.html"),
-            base::BindRepeating(&CreateWebAppInfoForPrintManagementApp)));
-    infos.at(SystemAppType::PRINT_MANAGEMENT).show_in_launcher = false;
-    infos.at(SystemAppType::PRINT_MANAGEMENT).minimum_window_size = {600, 320};
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::SCANNING)) {
-    infos.emplace(SystemAppType::SCANNING,
-                  SystemAppInfo("Scanning", GURL("chrome://scanning"),
-                                base::BindRepeating(
-                                    &CreateWebAppInfoForScanningSystemWebApp)));
-    infos.at(SystemAppType::SCANNING).minimum_window_size = {600, 420};
-    infos.at(SystemAppType::SCANNING).capture_navigations = true;
-    infos.at(SystemAppType::SCANNING).show_in_launcher = false;
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::SHIMLESS_RMA)) {
-    infos.emplace(
-        SystemAppType::SHIMLESS_RMA,
-        SystemAppInfo(
-            "ShimlessRMA", GURL(ash::kChromeUIShimlessRMAUrl),
-            base::BindRepeating(&CreateWebAppInfoForShimlessRMASystemWebApp)));
-    infos.at(SystemAppType::SHIMLESS_RMA).capture_navigations = true;
-    infos.at(SystemAppType::SHIMLESS_RMA).show_in_launcher = false;
-    infos.at(SystemAppType::SHIMLESS_RMA).show_in_search = false;
-    infos.at(SystemAppType::SHIMLESS_RMA).is_resizeable = false;
-    infos.at(SystemAppType::SHIMLESS_RMA).allow_scripts_to_close_windows = true;
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(
-          SystemAppType::CONNECTIVITY_DIAGNOSTICS)) {
-    infos.emplace(
-        SystemAppType::CONNECTIVITY_DIAGNOSTICS,
-        SystemAppInfo(
-            "ConnectivityDiagnostics",
-            GURL(chromeos::kChromeUIConnectivityDiagnosticsUrl),
-            base::BindRepeating(
-                &CreateWebAppInfoForConnectivityDiagnosticsSystemWebApp)));
-    infos.at(SystemAppType::CONNECTIVITY_DIAGNOSTICS).show_in_launcher = false;
-    infos.at(SystemAppType::CONNECTIVITY_DIAGNOSTICS).show_in_search = false;
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::ECHE)) {
-    infos.emplace(
-        SystemAppType::ECHE,
-        SystemAppInfo("Eche", GURL("chrome://eche-app"),
-                      base::BindRepeating(&CreateWebAppInfoForEcheApp)));
-    infos.at(SystemAppType::ECHE).capture_navigations = true;
-    infos.at(SystemAppType::ECHE).show_in_launcher = false;
-    infos.at(SystemAppType::ECHE).show_in_search = false;
-
-    if (base::FeatureList::IsEnabled(chromeos::features::kEcheSWAResizing)) {
-      infos.at(SystemAppType::ECHE).is_resizeable = true;
-    } else {
-      infos.at(SystemAppType::ECHE).is_resizeable = false;
-    }
-
-    infos.at(SystemAppType::ECHE).is_maximizable = false;
-    infos.at(SystemAppType::ECHE).should_have_reload_button_in_minimal_ui =
-        false;
-    infos.at(SystemAppType::ECHE).allow_scripts_to_close_windows = true;
-    infos.at(SystemAppType::ECHE).get_default_bounds =
-        base::BindRepeating(&GetDefaultBoundsForEche);
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::OS_FEEDBACK)) {
-    infos.emplace(
-        SystemAppType::OS_FEEDBACK,
-        SystemAppInfo(
-            "OSFeedback", GURL(ash::kChromeUIOSFeedbackUrl),
-            base::BindRepeating(&CreateWebAppInfoForOSFeedbackSystemWebApp)));
-    auto& config = infos.at(SystemAppType::OS_FEEDBACK);
-
-    config.allow_scripts_to_close_windows = true;
-    config.capture_navigations = true;
-    // Only allow users to minimize or close the App.
-    config.is_maximizable = false;
-    config.is_resizeable = false;
-    config.get_default_bounds =
-        base::BindRepeating(&GetDefaultBoundsForOSFeedbackApp);
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::PERSONALIZATION)) {
-    infos.emplace(
-        SystemAppType::PERSONALIZATION,
-        SystemAppInfo(
-            "Personalization", GURL(chromeos::kChromeUIPersonalizationAppURL),
-            base::BindRepeating(&CreateWebAppInfoForPersonalizationApp)));
-    auto& personalization_info = infos.at(SystemAppType::PERSONALIZATION);
-    personalization_info.capture_navigations = true;
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(
-          SystemAppType::SHORTCUT_CUSTOMIZATION)) {
-    infos.emplace(
-        SystemAppType::SHORTCUT_CUSTOMIZATION,
-        SystemAppInfo(
-            "ShortcutCustomization",
-            GURL(ash::kChromeUIShortcutCustomizationAppURL),
-            base::BindRepeating(
-                &CreateWebAppInfoForShortcutCustomizationSystemWebApp)));
-  }
-
-#if !defined(OFFICIAL_BUILD)
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::TELEMETRY)) {
-    infos.emplace(
-        SystemAppType::TELEMETRY,
-        SystemAppInfo(
-            "Telemetry", GURL("chrome://telemetry-extension"),
-            base::BindRepeating(&CreateWebAppInfoForTelemetryExtension)));
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::FILE_MANAGER)) {
-    infos.emplace(
-        SystemAppType::FILE_MANAGER,
-        SystemAppInfo("File Manager", GURL("chrome://file-manager"),
-                      base::BindRepeating(&CreateWebAppInfoForFileManager)));
-    infos.at(SystemAppType::FILE_MANAGER).capture_navigations = true;
-    infos.at(SystemAppType::FILE_MANAGER).single_window = false;
-  }
-
-  if (SystemWebAppManager::IsAppEnabled(SystemAppType::DEMO_MODE)) {
-    infos.emplace(
-        SystemAppType::DEMO_MODE,
-        SystemAppInfo("DemoMode", GURL("chrome://demo-mode-app"),
-                      base::BindRepeating(&CreateWebAppInfoForDemoModeApp)));
-    infos.at(SystemAppType::DEMO_MODE).capture_navigations = true;
-  }
-
-  infos.emplace(
-      SystemAppType::SAMPLE,
-      SystemAppInfo(
-          "Sample", GURL("chrome://sample-system-web-app/pwa.html"),
-          base::BindRepeating(&CreateWebAppInfoForSampleSystemWebApp)));
-  // Frobulate is the name for Sample Origin Trial API, and has no impact on the
-  // Web App's functionality. Here we use it to demonstrate how to enable origin
-  // trials for a System Web App.
-  infos.at(SystemAppType::SAMPLE).enabled_origin_trials = OriginTrialsMap(
-      {{GetOrigin("chrome://sample-system-web-app"), {"Frobulate"}},
-       {GetOrigin("chrome-untrusted://sample-system-web-app"), {"Frobulate"}}});
-  infos.at(SystemAppType::SAMPLE).capture_navigations = true;
-  infos.at(SystemAppType::SAMPLE).timer_info = SystemAppBackgroundTaskInfo(
-      base::TimeDelta::FromSeconds(30),
-      GURL("chrome://sample-system-web-app/timer.html"));
-#endif  // !defined(OFFICIAL_BUILD)
-
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-
-  return infos;
+  return {};
+#endif
 }
 
 bool HasSystemWebAppScheme(const GURL& url) {
@@ -420,29 +164,37 @@
 
 ExternalInstallOptions CreateInstallOptionsForSystemApp(
     const SystemAppType app_type,
-    const SystemAppInfo& info,
+
+    const SystemWebAppDelegate& delegate,
     bool force_update,
+
     bool is_disabled) {
-  DCHECK(info.install_url.scheme() == content::kChromeUIScheme ||
-         info.install_url.scheme() == content::kChromeUIUntrustedScheme);
+  DCHECK(delegate.GetInstallUrl().scheme() == content::kChromeUIScheme ||
+         delegate.GetInstallUrl().scheme() ==
+             content::kChromeUIUntrustedScheme);
 
   ExternalInstallOptions install_options(
-      info.install_url, DisplayMode::kStandalone,
+      delegate.GetInstallUrl(), DisplayMode::kStandalone,
       ExternalInstallSource::kSystemInstalled);
-  install_options.only_use_app_info_factory = !!info.app_info_factory;
-  install_options.app_info_factory = info.app_info_factory;
-  install_options.add_to_applications_menu = info.show_in_launcher;
+  install_options.only_use_app_info_factory = true;
+  // This can be Unretained because it's referring to the delegate owning this
+  // factory method. The lifetime of that is the same as the
+  // SystemWebAppManager.
+  install_options.app_info_factory = base::BindRepeating(
+      &SystemWebAppDelegate::GetWebAppInfo, base::Unretained(&delegate));
+  install_options.add_to_applications_menu = delegate.ShouldShowInLauncher();
   install_options.add_to_desktop = false;
   install_options.add_to_quick_launch_bar = false;
-  install_options.add_to_search = info.show_in_search;
+  install_options.add_to_search = delegate.ShouldShowInSearch();
   install_options.add_to_management = false;
   install_options.is_disabled = is_disabled;
   install_options.bypass_service_worker_check = true;
   install_options.force_reinstall = force_update;
-  install_options.uninstall_and_replace = info.uninstall_and_replace;
+  install_options.uninstall_and_replace =
+      delegate.GetAppIdsToUninstallAndReplace();
   install_options.system_app_type = app_type;
 
-  const auto& search_terms = info.additional_search_terms;
+  const auto& search_terms = delegate.GetAdditionalSearchTerms();
   std::transform(search_terms.begin(), search_terms.end(),
                  std::back_inserter(install_options.additional_search_terms),
                  [](int term) { return l10n_util::GetStringUTF8(term); });
@@ -451,84 +203,10 @@
 
 }  // namespace
 
-SystemAppInfo::SystemAppInfo(const std::string& internal_name,
-                             const GURL& install_url,
-                             const WebApplicationInfoFactory& app_info_factory)
-    : internal_name(internal_name),
-      install_url(install_url),
-      app_info_factory(app_info_factory) {}
-
-SystemAppInfo::SystemAppInfo(const SystemAppInfo& other) = default;
-
-SystemAppInfo::~SystemAppInfo() = default;
-
 // static
 const char SystemWebAppManager::kInstallResultHistogramName[];
 const char SystemWebAppManager::kInstallDurationHistogramName[];
 
-// static
-bool SystemWebAppManager::IsAppEnabled(SystemAppType type) {
-  if (base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps))
-    return true;
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-
-#if !defined(OFFICIAL_BUILD)
-  bool install_experimental_apps = true;
-#else
-  bool install_experimental_apps = false;
-#endif
-
-  switch (type) {
-    case SystemAppType::SETTINGS:
-      return true;
-    case SystemAppType::CAMERA:
-      return true;
-    case SystemAppType::CROSH:
-      return true;
-    case SystemAppType::TERMINAL:
-      return true;
-    case SystemAppType::MEDIA:
-      return true;
-    case SystemAppType::HELP:
-      return true;
-    case SystemAppType::PRINT_MANAGEMENT:
-      return true;
-    case SystemAppType::SCANNING:
-      return true;
-    case SystemAppType::SHIMLESS_RMA:
-      return ash::features::IsShimlessRMAFlowEnabled();
-    case SystemAppType::DIAGNOSTICS:
-      return base::FeatureList::IsEnabled(chromeos::features::kDiagnosticsApp);
-    case SystemAppType::CONNECTIVITY_DIAGNOSTICS:
-      return true;
-    case SystemAppType::TELEMETRY:
-      return install_experimental_apps &&
-             base::FeatureList::IsEnabled(
-                 chromeos::features::kTelemetryExtension);
-    case SystemAppType::FILE_MANAGER:
-      return install_experimental_apps &&
-             base::FeatureList::IsEnabled(chromeos::features::kFilesSWA);
-    case SystemAppType::SAMPLE:
-      if (install_experimental_apps)
-        NOTREACHED();
-      return false;
-    case SystemAppType::ECHE:
-      return base::FeatureList::IsEnabled(chromeos::features::kEcheSWA);
-    case SystemAppType::PERSONALIZATION:
-      return chromeos::features::IsWallpaperWebUIEnabled();
-    case SystemAppType::SHORTCUT_CUSTOMIZATION:
-      return features::IsShortcutCustomizationAppEnabled();
-    case SystemAppType::DEMO_MODE:
-      return chromeos::features::IsDemoModeSWAEnabled();
-    case SystemAppType::OS_FEEDBACK:
-      return base::FeatureList::IsEnabled(ash::features::kOsFeedback);
-  }
-#else
-  return false;
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
-}
-
 SystemWebAppManager::SystemWebAppManager(Profile* profile)
     : profile_(profile),
       on_apps_synchronized_(new base::OneShotEvent()),
@@ -543,7 +221,7 @@
 
     // Populate with real system apps if the test asks for it.
     if (base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps))
-      system_app_infos_ = CreateSystemWebApps(profile_);
+      system_app_delegates_ = CreateSystemWebApps(profile_);
 
     return;
   }
@@ -556,7 +234,7 @@
   update_policy_ = UpdatePolicy::kAlwaysUpdate;
 #endif
 
-  system_app_infos_ = CreateSystemWebApps(profile_);
+  system_app_delegates_ = CreateSystemWebApps(profile_);
 }
 
 SystemWebAppManager::~SystemWebAppManager() = default;
@@ -567,6 +245,17 @@
   }
 }
 
+bool SystemWebAppManager::IsAppEnabled(SystemAppType type) {
+  if (base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps))
+    return true;
+
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
+    return false;
+
+  return it->second->IsAppEnabled();
+}
+
 void SystemWebAppManager::Shutdown() {
   shutting_down_ = true;
   StopBackgroundTasks();
@@ -591,10 +280,10 @@
   const base::TimeTicks install_start_time = base::TimeTicks::Now();
 
 #if DCHECK_IS_ON()
-  for (const auto& type_and_app_info : system_app_infos_) {
-    // Check Origin Trials are defined correctly.
+  // Check Origin Trials are defined correctly.
+  for (const auto& type_and_app_info : system_app_delegates_) {
     for (const auto& origin_to_trial_names :
-         type_and_app_info.second.enabled_origin_trials) {
+         type_and_app_info.second->GetEnabledOriginTrials()) {
       // Only allow force enabled origin trials on chrome:// and
       // chrome-untrusted:// URLs.
       const auto& scheme = origin_to_trial_names.first.scheme();
@@ -607,8 +296,8 @@
 
     // App's install_url and start_url should share the same origin.
     DCHECK(url::IsSameOriginWith(
-        type_and_app_info.second.install_url,
-        type_and_app_info.second.app_info_factory.Run()->start_url));
+        type_and_app_info.second->GetInstallUrl(),
+        type_and_app_info.second->GetWebAppInfo()->start_url));
   }
 #endif  // DCHECK_IS_ON()
 
@@ -621,9 +310,9 @@
   const auto& disabled_system_apps =
       web_app_policy_manager_->GetDisabledSystemWebApps();
 
-  for (const auto& app : system_app_infos_) {
+  for (const auto& app : system_app_delegates_) {
     install_options_list.push_back(CreateInstallOptionsForSystemApp(
-        app.first, app.second, should_force_install_apps,
+        app.first, *app.second, should_force_install_apps,
         base::Contains(disabled_system_apps, app.first)));
   }
 
@@ -641,7 +330,7 @@
 void SystemWebAppManager::InstallSystemAppsForTesting() {
   on_apps_synchronized_ = std::make_unique<base::OneShotEvent>();
   on_tasks_started_ = std::make_unique<base::OneShotEvent>();
-  system_app_infos_ = CreateSystemWebApps(profile_);
+  system_app_delegates_ = CreateSystemWebApps(profile_);
   Start();
 
   // Wait for the System Web Apps to install.
@@ -650,19 +339,18 @@
   run_loop.Run();
 }
 
-const base::flat_map<SystemAppType, SystemAppInfo>&
+const base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>&
 SystemWebAppManager::GetRegisteredSystemAppsForTesting() const {
-  return system_app_infos_;
+  return system_app_delegates_;
 }
 
 absl::optional<AppId> SystemWebAppManager::GetAppIdForSystemApp(
     SystemAppType id) const {
-  auto app_url_it = system_app_infos_.find(id);
-
-  if (app_url_it == system_app_infos_.end())
+  auto app_url_it = system_app_delegates_.find(id);
+  if (app_url_it == system_app_delegates_.end())
     return absl::optional<AppId>();
 
-  return registrar_->LookupExternalAppId(app_url_it->second.install_url);
+  return registrar_->LookupExternalAppId(app_url_it->second->GetInstallUrl());
 }
 
 absl::optional<SystemAppType> SystemWebAppManager::GetSystemAppTypeForAppId(
@@ -686,7 +374,7 @@
   // crashing when looking up that type).
   SystemAppType proto_type =
       web_app->client_data().system_web_app_data->system_app_type;
-  if (system_app_infos_.contains(proto_type)) {
+  if (system_app_delegates_.contains(proto_type)) {
     return proto_type;
   }
 
@@ -695,7 +383,7 @@
 
 std::vector<AppId> SystemWebAppManager::GetAppIds() const {
   std::vector<AppId> app_ids;
-  for (const auto& app_type_to_app_info : system_app_infos_) {
+  for (const auto& app_type_to_app_info : system_app_delegates_) {
     absl::optional<AppId> app_id =
         GetAppIdForSystemApp(app_type_to_app_info.first);
     if (app_id.has_value()) {
@@ -710,27 +398,28 @@
 }
 
 bool SystemWebAppManager::IsSingleWindow(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.single_window;
+  return it->second->ShouldBeSingleWindow();
 }
 
 bool SystemWebAppManager::AppShouldReceiveLaunchDirectory(
     SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
-  return it->second.include_launch_directory;
+  return it->second->ShouldIncludeLaunchDirectory();
 }
 
 const std::vector<std::string>* SystemWebAppManager::GetEnabledOriginTrials(
     const SystemAppType type,
-    const GURL& url) {
+    const GURL& url) const {
   const auto& origin_to_origin_trials =
-      system_app_infos_.at(type).enabled_origin_trials;
+      system_app_delegates_.at(type)->GetEnabledOriginTrials();
   auto iter_trials = origin_to_origin_trials.find(url::Origin::Create(url));
+
   if (iter_trials == origin_to_origin_trials.end())
     return nullptr;
 
@@ -738,9 +427,9 @@
 }
 
 bool SystemWebAppManager::AppHasFileHandlingOriginTrial(SystemAppType type) {
-  const auto& info = system_app_infos_.at(type);
+  const auto& info = system_app_delegates_.at(type);
   const std::vector<std::string>* trials =
-      GetEnabledOriginTrials(type, info.install_url);
+      GetEnabledOriginTrials(type, info->GetInstallUrl());
   return trials && base::Contains(*trials, kFileHandlingOriginTrial);
 }
 
@@ -759,17 +448,18 @@
 
   const std::vector<std::string>* trials =
       GetEnabledOriginTrials(type.value(), navigation_handle->GetURL());
-  if (trials)
+  if (trials) {
     navigation_handle->ForceEnableOriginTrials(*trials);
+  }
 }
 
 std::vector<std::string> SystemWebAppManager::GetAdditionalSearchTerms(
     SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return {};
 
-  const auto& search_terms = it->second.additional_search_terms;
+  const auto& search_terms = it->second->GetAdditionalSearchTerms();
 
   std::vector<std::string> search_terms_strings;
   std::transform(search_terms.begin(), search_terms.end(),
@@ -779,58 +469,58 @@
 }
 
 bool SystemWebAppManager::ShouldShowInLauncher(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
-  return it->second.show_in_launcher;
+  return it->second->ShouldShowInLauncher();
 }
 
 bool SystemWebAppManager::ShouldShowInSearch(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
-  return it->second.show_in_search;
+  return it->second->ShouldShowInSearch();
 }
 
 bool SystemWebAppManager::IsResizeableWindow(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.is_resizeable;
+  return it->second->ShouldAllowResize();
 }
 
 bool SystemWebAppManager::IsMaximizableWindow(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.is_maximizable;
+  return it->second->ShouldAllowMaximize();
 }
 
 bool SystemWebAppManager::ShouldHaveReloadButtonInMinimalUi(
     SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.should_have_reload_button_in_minimal_ui;
+  return it->second->ShouldHaveReloadButtonInMinimalUi();
 }
 
 bool SystemWebAppManager::AllowScriptsToCloseWindows(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.allow_scripts_to_close_windows;
+  return it->second->ShouldAllowScriptsToCloseWindows();
 }
 
 bool SystemWebAppManager::ShouldHaveTabStrip(SystemAppType type) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return false;
 
-  return it->second.has_tab_strip;
+  return it->second->ShouldHaveTabStrip();
 }
 
 absl::optional<SystemAppType> SystemWebAppManager::GetCapturingSystemAppForURL(
@@ -846,13 +536,15 @@
   if (!type.has_value())
     return absl::nullopt;
 
-  const auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end())
+  const auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end())
     return absl::nullopt;
 
-  if (!it->second.capture_navigations)
+  if (!it->second->ShouldCaptureNavigations())
     return absl::nullopt;
 
+    // TODO(crbug://1051229): Expand ShouldCaptureNavigation to take a GURL, and
+    // move this into the camera one.
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   if (type == SystemAppType::CAMERA &&
       url.spec() != chromeos::kChromeUICameraAppMainURL)
@@ -864,13 +556,12 @@
 
 gfx::Rect SystemWebAppManager::GetDefaultBounds(SystemAppType type,
                                                 Browser* browser) const {
-  auto it = system_app_infos_.find(type);
-  if (it == system_app_infos_.end() ||
-      it->second.get_default_bounds.is_null()) {
+  auto it = system_app_delegates_.find(type);
+  if (it == system_app_delegates_.end()) {
     return gfx::Rect();
   }
 
-  return it->second.get_default_bounds.Run(browser);
+  return it->second->GetDefaultBounds(browser);
 }
 
 gfx::Size SystemWebAppManager::GetMinimumWindowSize(const AppId& app_id) const {
@@ -878,18 +569,19 @@
 
   if (!app_type.has_value())
     return gfx::Size();
-  auto app_type_to_app_info = system_app_infos_.find(app_type.value());
+  auto app_type_to_app_info = system_app_delegates_.find(app_type.value());
 
-  if (app_type_to_app_info == system_app_infos_.end()) {
+  if (app_type_to_app_info == system_app_delegates_.end()) {
     return gfx::Size();
   }
 
-  return app_type_to_app_info->second.minimum_window_size;
+  return app_type_to_app_info->second->GetMinimumWindowSize();
 }
 
 void SystemWebAppManager::SetSystemAppsForTesting(
-    base::flat_map<SystemAppType, SystemAppInfo> system_apps) {
-  system_app_infos_ = std::move(system_apps);
+    base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>
+        system_apps) {
+  system_app_delegates_ = std::move(system_apps);
 }
 
 const std::vector<std::unique_ptr<SystemAppBackgroundTask>>&
@@ -967,13 +659,13 @@
   }
 
   // Record per-app result.
-  for (const auto& type_and_app_info : system_app_infos_) {
-    const GURL& install_url = type_and_app_info.second.install_url;
+  for (const auto& type_and_app_info : system_app_delegates_) {
+    const GURL& install_url = type_and_app_info.second->GetInstallUrl();
     const auto url_and_result = results_to_report.find(install_url);
     if (url_and_result != results_to_report.cend()) {
       const std::string app_histogram_name =
           std::string(kInstallResultHistogramName) + ".Apps." +
-          type_and_app_info.second.internal_name;
+          type_and_app_info.second->GetInternalName();
       base::UmaHistogramEnumeration(
           app_histogram_name,
           shutting_down_
@@ -991,7 +683,7 @@
   // TODO(crbug.com/1053371): Clean up File Handler install. We install SWA file
   // handlers here, because the code that registers file handlers for regular
   // Web Apps, does not run when for apps installed in the background.
-  for (const auto& it : system_app_infos_) {
+  for (const auto& it : system_app_delegates_) {
     const SystemAppType& type = it.first;
     absl::optional<AppId> app_id = GetAppIdForSystemApp(type);
     if (!app_id)
@@ -1024,12 +716,12 @@
 
   RecordSystemWebAppInstallResults(install_results);
 
-  for (const auto& it : system_app_infos_) {
-    const SystemAppInfo& app_info = it.second;
-
-    if (app_info.timer_info) {
+  for (const auto& it : system_app_delegates_) {
+    absl::optional<SystemAppBackgroundTaskInfo> background_info =
+        it.second->GetTimerInfo();
+    if (background_info) {
       tasks_.push_back(std::make_unique<SystemAppBackgroundTask>(
-          profile_, app_info.timer_info.value()));
+          profile_, background_info.value()));
     }
   }
   // May be called more than once in tests.
@@ -1048,7 +740,8 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   bool is_camera_app_installed =
-      system_app_infos_.find(SystemAppType::CAMERA) != system_app_infos_.end();
+      system_app_delegates_.find(SystemAppType::CAMERA) !=
+      system_app_delegates_.end();
   profile_->GetPrefs()->SetBoolean(chromeos::prefs::kHasCameraAppMigratedToSWA,
                                    is_camera_app_installed);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h
index c1ae3ffd..cf1529c6 100644
--- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h
+++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h
@@ -52,6 +52,9 @@
 class AppRegistryController;
 class WebAppPolicyManager;
 
+using SystemAppDelegateMap =
+    base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>;
+
 // Installs, uninstalls, and updates System Web Apps.
 // System Web Apps are built-in, highly-privileged Web Apps for Chrome OS. They
 // have access to more APIs and are part of the Chrome OS image.
@@ -71,7 +74,7 @@
       "Webapp.SystemApps.FreshInstallDuration";
 
   // Returns whether the given app type is enabled.
-  static bool IsAppEnabled(SystemAppType type);
+  bool IsAppEnabled(SystemAppType type);
 
   explicit SystemWebAppManager(Profile* profile);
   SystemWebAppManager(const SystemWebAppManager&) = delete;
@@ -162,8 +165,7 @@
 
   // Returns a map of registered system app types and infos, these apps will be
   // installed on the system.
-  const base::flat_map<SystemAppType, SystemAppInfo>&
-  GetRegisteredSystemAppsForTesting() const;
+  const SystemAppDelegateMap& GetRegisteredSystemAppsForTesting() const;
 
   const base::OneShotEvent& on_apps_synchronized() const {
     return *on_apps_synchronized_;
@@ -177,8 +179,7 @@
 
   // This call will override default System Apps configuration. You should call
   // Start() after this call to install |system_apps|.
-  void SetSystemAppsForTesting(
-      base::flat_map<SystemAppType, SystemAppInfo> system_apps);
+  void SetSystemAppsForTesting(SystemAppDelegateMap system_apps);
 
   // Overrides the update policy. If AlwaysReinstallSystemWebApps feature is
   // enabled, this method does nothing, and system apps will be reinstalled.
@@ -192,16 +193,18 @@
   const std::vector<std::unique_ptr<SystemAppBackgroundTask>>&
   GetBackgroundTasksForTesting();
 
+  const Profile* profile() const { return profile_; }
+
  protected:
   virtual const base::Version& CurrentVersion() const;
   virtual const std::string& CurrentLocale() const;
 
  private:
-  // Returns the list of origin trials to enable for |url| loaded in System App
-  // |type|. Returns nullptr if the App does not specify origin trials for
-  // |url|.
+  // Returns the list of origin trials to enable for |url| loaded in System
+  // App |type|. Returns an empty vector if the App does not specify origin
+  // trials for |url|.
   const std::vector<std::string>* GetEnabledOriginTrials(SystemAppType type,
-                                                         const GURL& url);
+                                                         const GURL& url) const;
 
   bool AppHasFileHandlingOriginTrial(SystemAppType type);
 
@@ -239,7 +242,7 @@
 
   UpdatePolicy update_policy_;
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_app_infos_;
+  SystemAppDelegateMap system_app_delegates_;
 
   PrefService* const pref_service_;
 
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 52aa21f1..4bf29aa0 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
@@ -17,6 +17,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
+#include "chrome/browser/web_applications/components/external_install_options.h"
 #include "chrome/browser/web_applications/components/externally_installed_web_app_prefs.h"
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
@@ -25,6 +26,9 @@
 #include "chrome/browser/web_applications/externally_managed_app_manager_impl.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
 #include "chrome/browser/web_applications/system_web_apps/system_web_app_background_task.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"
+#include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.h"
 #include "chrome/browser/web_applications/test/test_data_retriever.h"
 #include "chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h"
@@ -54,6 +58,9 @@
 const char kSettingsAppInternalName[] = "OSSettings";
 const char kCameraAppInternalName[] = "Camera";
 
+using SystemAppMapType =
+    base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>;
+
 GURL AppUrl1() {
   return GURL(content::GetWebUIURL("system-app1"));
 }
@@ -289,13 +296,16 @@
 TEST_F(SystemWebAppManagerTest, Enabled) {
   InitEmptyRegistrar();
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>
+      system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemAppType::CAMERA,
-                      SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                    GetApp2WebAppInfoFactory()));
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::CAMERA, kCameraAppInternalName,
+                          AppUrl2(), GetApp2WebAppInfoFactory()));
 
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
   StartAndWaitForAppsToSynchronize();
@@ -316,10 +326,12 @@
         GURL(content::GetWebUIURL("system-app3/app.ico")),
         ExternalInstallSource::kInternalDefault}});
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>
+      system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
 
   system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
   StartAndWaitForAppsToSynchronize();
@@ -353,13 +365,14 @@
       SystemWebAppManager::UpdatePolicy::kAlwaysUpdate);
 
   InitEmptyRegistrar();
-
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
-  system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
-
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+  }
   system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
   StartAndWaitForAppsToSynchronize();
 
@@ -367,11 +380,19 @@
 
   // Create another app. The version hasn't changed but the app should still
   // install.
-  system_apps.emplace(SystemAppType::CAMERA,
-                      SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                    GetApp2WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+  {
+    SystemAppMapType system_apps;
 
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_apps.emplace(SystemAppType::CAMERA,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::CAMERA, kCameraAppInternalName,
+                            AppUrl2(), GetApp2WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+  }
   // This one returns because on_apps_synchronized runs immediately.
   StartAndWaitForAppsToSynchronize();
 
@@ -386,27 +407,37 @@
       SystemWebAppManager::UpdatePolicy::kOnVersionChange);
 
   InitEmptyRegistrar();
-
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
-  system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
-
-  system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+    system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
+  }
   StartAndWaitForAppsToSynchronize();
 
   EXPECT_EQ(1u, install_requests.size());
   EXPECT_TRUE(install_requests[0].force_reinstall);
   EXPECT_TRUE(IsInstalled(AppUrl1()));
 
-  // Create another app. The version hasn't changed, but we should immediately
-  // install anyway, as if a user flipped a chrome://flag. The first app won't
-  // force reinstall.
-  system_apps.emplace(SystemAppType::CAMERA,
-                      SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                    GetApp2WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    // Create another app. The version hasn't changed, but we should immediately
+    // install anyway, as if a user flipped a chrome://flag. The first app won't
+    // force reinstall.
+    system_apps.emplace(SystemAppType::CAMERA,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::CAMERA, kCameraAppInternalName,
+                            AppUrl2(), GetApp2WebAppInfoFactory()));
+
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+  }
   StartAndWaitForAppsToSynchronize();
 
   EXPECT_EQ(3u, install_requests.size());
@@ -429,10 +460,22 @@
   // Changing the install URL of a system app propagates even without a
   // version change.
   const GURL kAppUrl3(content::GetWebUIURL("system-app3"));
-  system_apps.find(SystemAppType::SETTINGS)->second.install_url = kAppUrl3;
-  system_apps.find(SystemAppType::SETTINGS)->second.app_info_factory =
-      base::BindRepeating(&GetWebApplicationInfo, kAppUrl3);
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(
+        SystemAppType::SETTINGS,
+        std::make_unique<UnittestingSystemAppDelegate>(
+            SystemAppType::SETTINGS, kSettingsAppInternalName, kAppUrl3,
+            base::BindRepeating(&GetWebApplicationInfo, kAppUrl3)));
+
+    system_apps.emplace(SystemAppType::CAMERA,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::CAMERA, kCameraAppInternalName,
+                            AppUrl2(), GetApp2WebAppInfoFactory()));
+
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+  }
   StartAndWaitForAppsToSynchronize();
 
   EXPECT_EQ(7u, install_requests.size());
@@ -452,11 +495,12 @@
 
   InitEmptyRegistrar();
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   // First execution.
   system_web_app_manager().set_current_locale("en-US");
@@ -498,11 +542,12 @@
       SystemWebAppManager::UpdatePolicy::kAlwaysUpdate);
 
   {
-    base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+    SystemAppMapType system_apps;
     system_apps.emplace(SystemAppType::SETTINGS,
-                        SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                      GetApp1WebAppInfoFactory()));
-    system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
     histograms.ExpectTotalCount(
         SystemWebAppManager::kInstallResultHistogramName, 0);
@@ -538,14 +583,16 @@
           }));
 
   {
-    base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+    SystemAppMapType system_apps;
     system_apps.emplace(SystemAppType::SETTINGS,
-                        SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                      GetApp1WebAppInfoFactory()));
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
     system_apps.emplace(SystemAppType::CAMERA,
-                        SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                      GetApp2WebAppInfoFactory()));
-    system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::CAMERA, kCameraAppInternalName,
+                            AppUrl2(), GetApp2WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
     StartAndWaitForAppsToSynchronize();
 
@@ -562,11 +609,12 @@
   }
 
   {
-    base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+    SystemAppMapType system_apps;
     system_apps.emplace(SystemAppType::SETTINGS,
-                        SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                      GetApp1WebAppInfoFactory()));
-    system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
     histograms.ExpectTotalCount(
         SystemWebAppManager::kInstallDurationHistogramName, 2);
@@ -618,14 +666,16 @@
       ".Profiles.Other";
 
   InitEmptyRegistrar();
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemAppType::CAMERA,
-                      SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                    GetApp2WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::CAMERA, kCameraAppInternalName,
+                          AppUrl2(), GetApp2WebAppInfoFactory()));
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   externally_managed_app_manager().SetHandleInstallRequestCallback(
       base::BindLambdaForTesting(
@@ -651,14 +701,16 @@
   base::HistogramTester histograms;
 
   InitEmptyRegistrar();
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
   system_apps.emplace(SystemAppType::CAMERA,
-                      SystemAppInfo(kCameraAppInternalName, AppUrl2(),
-                                    GetApp2WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::CAMERA, kCameraAppInternalName,
+                          AppUrl2(), GetApp2WebAppInfoFactory()));
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
   system_web_app_manager().SetUpdatePolicy(
       SystemWebAppManager::UpdatePolicy::kOnVersionChange);
 
@@ -707,11 +759,12 @@
 
   InitEmptyRegistrar();
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
   StartAndWaitForAppsToSynchronize();
@@ -777,11 +830,13 @@
 
   InitEmptyRegistrar();
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
+
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
   system_web_app_manager().set_current_locale("en/us");
@@ -845,11 +900,13 @@
   InitEmptyRegistrar();
 
   // Set up and install a baseline
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
+
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
   StartAndWaitForAppsToSynchronize();
@@ -915,11 +972,13 @@
       SystemWebAppManager::UpdatePolicy::kOnVersionChange);
 
   // Register a test system app.
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(SystemAppType::SETTINGS,
-                      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                                    GetApp1WebAppInfoFactory()));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
+                      std::make_unique<UnittestingSystemAppDelegate>(
+                          SystemAppType::SETTINGS, kSettingsAppInternalName,
+                          AppUrl1(), GetApp1WebAppInfoFactory()));
+
+  system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
 
   // Install the App normally.
   {
@@ -950,13 +1009,14 @@
   InitEmptyRegistrar();
 
   // Set up and install a baseline
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
-  system_apps.emplace(
-      SystemAppType::SETTINGS,
-      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                    base::BindRepeating(&GetWebApplicationInfo, AppUrl1())));
-  system_web_app_manager().SetSystemAppsForTesting(system_apps);
-
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
+  }
   system_web_app_manager().set_current_version(base::Version("1.0.0.0"));
   StartAndWaitForAppsToSynchronize();
   EXPECT_TRUE(
@@ -969,13 +1029,44 @@
       &externally_managed_app_manager(), &controller().registrar(),
       &controller().sync_bridge(), &ui_manager(),
       &controller().os_integration_manager(), &web_app_policy_manager());
-
-  unsynced_system_web_app_manager->SetSystemAppsForTesting(system_apps);
+  {
+    SystemAppMapType system_apps;
+    system_apps.emplace(SystemAppType::SETTINGS,
+                        std::make_unique<UnittestingSystemAppDelegate>(
+                            SystemAppType::SETTINGS, kSettingsAppInternalName,
+                            AppUrl1(), GetApp1WebAppInfoFactory()));
+    unsynced_system_web_app_manager->SetSystemAppsForTesting(
+        std::move(system_apps));
+  }
 
   EXPECT_TRUE(unsynced_system_web_app_manager->IsSystemWebApp(
       GenerateAppIdFromURL(AppUrl1())));
 }
 
+class TimerSystemAppDelegate : public UnittestingSystemAppDelegate {
+ public:
+  TimerSystemAppDelegate(SystemAppType type,
+                         const std::string& name,
+                         const GURL& url,
+                         WebApplicationInfoFactory info_factory,
+                         absl::optional<base::TimeDelta> period,
+                         bool open_immediately)
+      : UnittestingSystemAppDelegate(type, name, url, info_factory),
+        period_(period),
+        open_immediately_(open_immediately) {}
+  absl::optional<SystemAppBackgroundTaskInfo> GetTimerInfo() const override;
+
+ private:
+  absl::optional<base::TimeDelta> period_;
+  bool open_immediately_;
+};
+
+absl::optional<SystemAppBackgroundTaskInfo>
+TimerSystemAppDelegate::GetTimerInfo() const {
+  return SystemAppBackgroundTaskInfo(period_, GetInstallUrl(),
+                                     open_immediately_);
+}
+
 class SystemWebAppManagerTimerTest : public SystemWebAppManagerTest {
  public:
   SystemWebAppManagerTimerTest()
@@ -985,14 +1076,12 @@
                   bool open_immediately) {
     InitEmptyRegistrar();
 
-    base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+    SystemAppMapType system_apps;
     system_apps.emplace(
         SystemAppType::SETTINGS,
-        SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                      base::BindRepeating(&GetWebApplicationInfo, AppUrl1())));
-
-    system_apps.at(SystemAppType::SETTINGS).timer_info =
-        SystemAppBackgroundTaskInfo(period, AppUrl1(), open_immediately);
+        std::make_unique<TimerSystemAppDelegate>(
+            SystemAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
+            GetApp1WebAppInfoFactory(), period, open_immediately));
 
     system_web_app_manager().SetSystemAppsForTesting(std::move(system_apps));
   }
@@ -1271,11 +1360,12 @@
        HonorsRegisteredAppsDespiteOfPersistedWebAppInfo) {
   InitEmptyRegistrar();
 
-  base::flat_map<SystemAppType, SystemAppInfo> system_apps;
+  SystemAppMapType system_apps;
   system_apps.emplace(
       SystemAppType::SETTINGS,
-      SystemAppInfo(kSettingsAppInternalName, AppUrl1(),
-                    base::BindRepeating(&GetWebApplicationInfo, AppUrl1())));
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::SETTINGS, kSettingsAppInternalName, AppUrl1(),
+          base::BindRepeating(&GetWebApplicationInfo, 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 accba7d..5d21de2 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
@@ -5,13 +5,18 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
+#include "base/debug/stack_trace.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/components/app_registrar.h"
+#include "chrome/browser/web_applications/components/web_application_info.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"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.h"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_url_data_source.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
@@ -81,15 +86,148 @@
 
 }  // namespace
 
-TestSystemWebAppInstallation::TestSystemWebAppInstallation(SystemAppType type,
-                                                           SystemAppInfo info)
+UnittestingSystemAppDelegate::UnittestingSystemAppDelegate(
+    SystemAppType type,
+    const std::string& name,
+    const GURL& url,
+    WebApplicationInfoFactory info_factory)
+    : web_app::SystemWebAppDelegate(type, name, url, nullptr),
+      info_factory_(info_factory) {}
+
+UnittestingSystemAppDelegate::~UnittestingSystemAppDelegate() = default;
+
+std::unique_ptr<WebApplicationInfo>
+UnittestingSystemAppDelegate::GetWebAppInfo() const {
+  return info_factory_.Run();
+}
+
+std::vector<AppId>
+UnittestingSystemAppDelegate::GetAppIdsToUninstallAndReplace() const {
+  return uninstall_and_replace_;
+}
+
+gfx::Size UnittestingSystemAppDelegate::GetMinimumWindowSize() const {
+  return minimum_window_size_;
+}
+bool UnittestingSystemAppDelegate::ShouldBeSingleWindow() const {
+  return single_window_;
+}
+bool UnittestingSystemAppDelegate::ShouldIncludeLaunchDirectory() const {
+  return include_launch_directory_;
+}
+
+std::vector<int> UnittestingSystemAppDelegate::GetAdditionalSearchTerms()
+    const {
+  return additional_search_terms_;
+}
+bool UnittestingSystemAppDelegate::ShouldShowInLauncher() const {
+  return show_in_launcher_;
+}
+bool UnittestingSystemAppDelegate::ShouldShowInSearch() const {
+  return show_in_search_;
+}
+bool UnittestingSystemAppDelegate::ShouldCaptureNavigations() const {
+  return capture_navigations_;
+}
+bool UnittestingSystemAppDelegate::ShouldAllowResize() const {
+  return is_resizeable_;
+}
+bool UnittestingSystemAppDelegate::ShouldAllowMaximize() const {
+  return is_maximizable_;
+}
+bool UnittestingSystemAppDelegate::ShouldHaveTabStrip() const {
+  return has_tab_strip_;
+}
+bool UnittestingSystemAppDelegate::ShouldHaveReloadButtonInMinimalUi() const {
+  return should_have_reload_button_in_minimal_ui_;
+}
+bool UnittestingSystemAppDelegate::ShouldAllowScriptsToCloseWindows() const {
+  return allow_scripts_to_close_windows_;
+}
+absl::optional<SystemAppBackgroundTaskInfo>
+UnittestingSystemAppDelegate::GetTimerInfo() const {
+  return timer_info_;
+}
+gfx::Rect UnittestingSystemAppDelegate::GetDefaultBounds(
+    Browser* browser) const {
+  if (get_default_bounds_) {
+    return get_default_bounds_.Run(browser);
+  }
+  return gfx::Rect();
+}
+bool UnittestingSystemAppDelegate::IsAppEnabled() const {
+  return true;
+}
+
+void UnittestingSystemAppDelegate::SetAppIdsToUninstallAndReplace(
+    const std::vector<AppId>& ids) {
+  uninstall_and_replace_ = ids;
+}
+void UnittestingSystemAppDelegate::SetMinimumWindowSize(const gfx::Size& size) {
+  minimum_window_size_ = size;
+}
+void UnittestingSystemAppDelegate::SetShouldBeSingleWindow(bool value) {
+  single_window_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldIncludeLaunchDirectory(bool value) {
+  include_launch_directory_ = value;
+}
+void UnittestingSystemAppDelegate::SetEnabledOriginTrials(
+    const OriginTrialsMap& map) {
+  origin_trials_map_ = map;
+}
+void UnittestingSystemAppDelegate::SetAdditionalSearchTerms(
+    const std::vector<int>& terms) {
+  additional_search_terms_ = terms;
+}
+void UnittestingSystemAppDelegate::SetShouldShowInLauncher(bool value) {
+  show_in_launcher_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldShowInSearch(bool value) {
+  show_in_search_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldCaptureNavigations(bool value) {
+  capture_navigations_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldAllowResize(bool value) {
+  is_resizeable_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldAllowMaximize(bool value) {
+  is_maximizable_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldHaveTabStrip(bool value) {
+  has_tab_strip_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldHaveReloadButtonInMinimalUi(
+    bool value) {
+  should_have_reload_button_in_minimal_ui_ = value;
+}
+void UnittestingSystemAppDelegate::SetShouldAllowScriptsToCloseWindows(
+    bool value) {
+  allow_scripts_to_close_windows_ = value;
+}
+void UnittestingSystemAppDelegate::SetTimerInfo(
+    const SystemAppBackgroundTaskInfo& timer_info) {
+  timer_info_ = timer_info;
+}
+void UnittestingSystemAppDelegate::SetDefaultBounds(
+    base::RepeatingCallback<gfx::Rect(Browser*)> lambda) {
+  get_default_bounds_ = std::move(lambda);
+}
+
+TestSystemWebAppInstallation::TestSystemWebAppInstallation(
+    SystemAppType type,
+    std::unique_ptr<UnittestingSystemAppDelegate> delegate)
     : type_(type) {
-  if (GetWebUIType(info.install_url) == WebUIType::kChrome) {
+  if (GetWebUIType(delegate->GetInstallUrl()) == WebUIType::kChrome) {
     auto factory = std::make_unique<TestSystemWebAppWebUIControllerFactory>(
-        GetDataSourceNameFromSystemAppInstallUrl(info.install_url));
+        GetDataSourceNameFromSystemAppInstallUrl(delegate->GetInstallUrl()));
     web_ui_controller_factories_.push_back(std::move(factory));
   }
 
+  UnittestingSystemAppDelegate* delegate_ptr = delegate.get();
+  system_app_delegates_.emplace(type, std::move(delegate));
+
   test_web_app_provider_creator_ = std::make_unique<TestWebAppProviderCreator>(
       base::BindRepeating(&TestSystemWebAppInstallation::CreateWebAppProvider,
                           // base::Unretained is safe here. This callback is
@@ -97,7 +235,7 @@
                           // startup. TestSystemWebAppInstallation is intended
                           // to have the same lifecycle as the test, it won't be
                           // destroyed before the test finishes.
-                          base::Unretained(this), info));
+                          base::Unretained(this), delegate_ptr));
 }
 
 TestSystemWebAppInstallation::TestSystemWebAppInstallation() {
@@ -146,14 +284,16 @@
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpTabbedMultiWindowApp() {
-  SystemAppInfo terminal_system_app_info(
-      "Terminal", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  terminal_system_app_info.single_window = false;
-  terminal_system_app_info.has_tab_strip = true;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::TERMINAL, "Terminal",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetShouldBeSingleWindow(false);
+  delegate->SetShouldHaveTabStrip(true);
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::TERMINAL, terminal_system_app_info));
+      SystemAppType::TERMINAL, std::move(delegate)));
 }
 
 // static
@@ -161,8 +301,9 @@
 TestSystemWebAppInstallation::SetUpStandaloneSingleWindowApp() {
   return base::WrapUnique(new TestSystemWebAppInstallation(
       SystemAppType::SETTINGS,
-      SystemAppInfo(
-          "OSSettings", GURL("chrome://test-system-app/pwa.html"),
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::SETTINGS, "OSSettings",
+          GURL("chrome://test-system-app/pwa.html"),
           base::BindRepeating(&GenerateWebApplicationInfoForTestApp))));
 }
 
@@ -170,17 +311,18 @@
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppThatReceivesLaunchFiles(
     IncludeLaunchDirectory include_launch_directory) {
-  SystemAppInfo media_system_app_info(
-      "Media", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Media",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
 
-  if (include_launch_directory == IncludeLaunchDirectory::kYes)
-    media_system_app_info.include_launch_directory = true;
-  else
-    media_system_app_info.include_launch_directory = false;
+  if (include_launch_directory == IncludeLaunchDirectory::kYes) {
+    delegate->SetShouldIncludeLaunchDirectory(true);
+  }
 
   auto* installation = new TestSystemWebAppInstallation(SystemAppType::MEDIA,
-                                                        media_system_app_info);
+                                                        std::move(delegate));
   installation->RegisterAutoGrantedPermissions(
       ContentSettingsType::FILE_SYSTEM_READ_GUARD);
   installation->RegisterAutoGrantedPermissions(
@@ -193,86 +335,94 @@
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithEnabledOriginTrials(
     const OriginTrialsMap& origin_to_trials) {
-  SystemAppInfo media_system_app_info(
-      "Media", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  media_system_app_info.enabled_origin_trials = origin_to_trials;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Media",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
 
+  delegate->SetEnabledOriginTrials(origin_to_trials);
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::MEDIA, media_system_app_info));
+      SystemAppType::MEDIA, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppNotShownInLauncher() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.show_in_launcher = false;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+
+  delegate->SetShouldShowInLauncher(false);
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppNotShownInSearch() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.show_in_search = false;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetShouldShowInSearch(false);
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithAdditionalSearchTerms() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.additional_search_terms = {IDS_SETTINGS_SECURITY};
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetAdditionalSearchTerms({IDS_SETTINGS_SECURITY});
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppThatCapturesNavigation() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.capture_navigations = true;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::HELP, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetShouldCaptureNavigations(true);
 
   auto* installation = new TestSystemWebAppInstallation(SystemAppType::HELP,
-                                                        std::move(app_info));
+                                                        std::move(delegate));
 
   // Add a helper system app to test capturing links from it.
   const GURL kInitiatingAppUrl = GURL("chrome://initiating-app/pwa.html");
-  installation->extra_apps_.insert_or_assign(
+  installation->system_app_delegates_.insert_or_assign(
       SystemAppType::SETTINGS,
-      SystemAppInfo("Initiating App", kInitiatingAppUrl,
-                    base::BindLambdaForTesting([]() {
-                      auto info = std::make_unique<WebApplicationInfo>();
-                      // 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
-                      // installation modes.
-                      info->start_url =
-                          GURL("chrome://initiating-app/pwa.html");
-                      info->scope = GURL("chrome://initiating-app/");
-                      info->title = u"Test System App";
-                      info->theme_color = 0xFF00FF00;
-                      info->display_mode =
-                          blink::mojom::DisplayMode::kStandalone;
-                      info->open_as_window = true;
-                      return info;
-                    }
-
-                                               )));
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::SETTINGS, "Initiating App", kInitiatingAppUrl,
+          base::BindLambdaForTesting([]() {
+            auto info = std::make_unique<WebApplicationInfo>();
+            // 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
+            // installation modes.
+            info->start_url = GURL("chrome://initiating-app/pwa.html");
+            info->scope = GURL("chrome://initiating-app/");
+            info->title = u"Test System App";
+            info->theme_color = 0xFF00FF00;
+            info->display_mode = blink::mojom::DisplayMode::kStandalone;
+            info->open_as_window = true;
+            return info;
+          })));
   auto factory = std::make_unique<TestSystemWebAppWebUIControllerFactory>(
       kInitiatingAppUrl.host());
   installation->web_ui_controller_factories_.push_back(std::move(factory));
@@ -285,101 +435,114 @@
 TestSystemWebAppInstallation::SetUpChromeUntrustedApp() {
   return base::WrapUnique(new TestSystemWebAppInstallation(
       SystemAppType::SETTINGS,
-      SystemAppInfo("Test", GURL("chrome-untrusted://test-system-app/pwa.html"),
-                    base::BindRepeating(
-                        &GenerateWebApplicationInfoForTestAppUntrusted))));
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::SETTINGS, "Test",
+          GURL("chrome-untrusted://test-system-app/pwa.html"),
+          base::BindRepeating(
+              &GenerateWebApplicationInfoForTestAppUntrusted))));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpNonResizeableAndNonMaximizableApp() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.is_resizeable = false;
-  app_info.is_maximizable = false;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetShouldAllowResize(false);
+  delegate->SetShouldAllowMaximize(false);
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SAMPLE, std::move(app_info)));
+      SystemAppType::SAMPLE, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithBackgroundTask() {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.timer_info.emplace();
-  app_info.timer_info->open_immediately = true;
-  app_info.timer_info->period = base::TimeDelta::FromDays(1);
-  app_info.timer_info->url = GURL("chrome://test-system-app/page2.html");
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+
+  SystemAppBackgroundTaskInfo background_task(
+      base::TimeDelta::FromDays(1), GURL("chrome://test-system-app/page2.html"),
+      true);
+  delegate->SetTimerInfo(background_task);
+
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetupAppWithAllowScriptsToCloseWindows(
     bool value) {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
   /* The default value of allow_scripts_to_close_windows is false. */
-  if (value)
-    app_info.allow_scripts_to_close_windows = true;
+  if (value) {
+    delegate->SetShouldAllowScriptsToCloseWindows(value);
+  }
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SAMPLE, std::move(app_info)));
+      SystemAppType::SAMPLE, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithTabStrip(bool has_tab_strip) {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.has_tab_strip = has_tab_strip;
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetShouldHaveTabStrip(has_tab_strip);
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 // static
 std::unique_ptr<TestSystemWebAppInstallation>
 TestSystemWebAppInstallation::SetUpAppWithDefaultBounds(
     const gfx::Rect& default_bounds) {
-  SystemAppInfo app_info(
-      "Test", GURL("chrome://test-system-app/pwa.html"),
-      base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
-  app_info.get_default_bounds =
-      base::BindLambdaForTesting([&](Browser*) { return default_bounds; });
+  std::unique_ptr<UnittestingSystemAppDelegate> delegate =
+      std::make_unique<UnittestingSystemAppDelegate>(
+          SystemAppType::MEDIA, "Test",
+          GURL("chrome://test-system-app/pwa.html"),
+          base::BindRepeating(&GenerateWebApplicationInfoForTestApp));
+  delegate->SetDefaultBounds(
+      base::BindLambdaForTesting([&](Browser*) { return default_bounds; }));
 
   return base::WrapUnique(new TestSystemWebAppInstallation(
-      SystemAppType::SETTINGS, std::move(app_info)));
+      SystemAppType::SETTINGS, std::move(delegate)));
 }
 
 std::unique_ptr<KeyedService>
-TestSystemWebAppInstallation::CreateWebAppProvider(SystemAppInfo info,
-                                                   Profile* profile) {
-  DCHECK(!extra_apps_.contains(type_.value()));
-
-  base::flat_map<SystemAppType, SystemAppInfo> apps(extra_apps_);
-  apps.insert_or_assign(type_.value(), info);
-
+TestSystemWebAppInstallation::CreateWebAppProvider(
+    UnittestingSystemAppDelegate* delegate,
+    Profile* profile) {
   profile_ = profile;
-  if (GetWebUIType(info.install_url) == WebUIType::kChromeUntrusted) {
-    AddTestURLDataSource(
-        GetChromeUntrustedDataSourceNameFromInstallUrl(info.install_url),
-        profile);
+  if (GetWebUIType(delegate->GetInstallUrl()) == WebUIType::kChromeUntrusted) {
+    AddTestURLDataSource(GetChromeUntrustedDataSourceNameFromInstallUrl(
+                             delegate->GetInstallUrl()),
+                         profile);
   }
 
   auto provider = std::make_unique<TestWebAppProvider>(profile);
   auto system_web_app_manager = std::make_unique<SystemWebAppManager>(profile);
-  system_web_app_manager->SetSystemAppsForTesting(apps);
+
+  system_web_app_manager->SetSystemAppsForTesting(
+      std::move(system_app_delegates_));
   system_web_app_manager->SetUpdatePolicyForTesting(update_policy_);
   provider->SetSystemWebAppManager(std::move(system_web_app_manager));
   provider->Start();
 
-  const url::Origin app_origin = url::Origin::Create(info.install_url);
+  const url::Origin app_origin = url::Origin::Create(delegate->GetInstallUrl());
   auto* allowlist = WebUIAllowlist::GetOrCreate(profile);
   for (const auto& permission : auto_granted_permissions_)
     allowlist->RegisterAutoGrantedPermission(app_origin, permission);
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 26dc9ce..e00ac73 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
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "chrome/browser/web_applications/components/web_application_info.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_manager.h"
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_web_ui_controller_factory.h"
 #include "chrome/browser/web_applications/test/test_web_app_provider.h"
@@ -15,6 +16,76 @@
 
 namespace web_app {
 
+class UnittestingSystemAppDelegate : public SystemWebAppDelegate {
+ public:
+  UnittestingSystemAppDelegate(SystemAppType type,
+                               const std::string& name,
+                               const GURL& url,
+                               WebApplicationInfoFactory info_factory);
+  UnittestingSystemAppDelegate(const UnittestingSystemAppDelegate&) = delete;
+  UnittestingSystemAppDelegate& operator=(const UnittestingSystemAppDelegate&) =
+      delete;
+  ~UnittestingSystemAppDelegate() override;
+
+  std::unique_ptr<WebApplicationInfo> GetWebAppInfo() const override;
+
+  std::vector<AppId> GetAppIdsToUninstallAndReplace() const override;
+  gfx::Size GetMinimumWindowSize() const override;
+  bool ShouldBeSingleWindow() const override;
+  bool ShouldIncludeLaunchDirectory() const override;
+  std::vector<int> GetAdditionalSearchTerms() const override;
+  bool ShouldShowInLauncher() const override;
+  bool ShouldShowInSearch() const override;
+  bool ShouldCaptureNavigations() const override;
+  bool ShouldAllowResize() const override;
+  bool ShouldAllowMaximize() const override;
+  bool ShouldHaveTabStrip() const override;
+  bool ShouldHaveReloadButtonInMinimalUi() const override;
+  bool ShouldAllowScriptsToCloseWindows() const override;
+  absl::optional<SystemAppBackgroundTaskInfo> GetTimerInfo() const override;
+  gfx::Rect GetDefaultBounds(Browser* browser) const override;
+  bool IsAppEnabled() const override;
+
+  void SetAppIdsToUninstallAndReplace(const std::vector<AppId>&);
+  void SetMinimumWindowSize(const gfx::Size&);
+  void SetShouldBeSingleWindow(bool);
+  void SetShouldIncludeLaunchDirectory(bool);
+  void SetEnabledOriginTrials(const OriginTrialsMap&);
+  void SetAdditionalSearchTerms(const std::vector<int>&);
+  void SetShouldShowInLauncher(bool);
+  void SetShouldShowInSearch(bool);
+  void SetShouldCaptureNavigations(bool);
+  void SetShouldAllowResize(bool);
+  void SetShouldAllowMaximize(bool);
+  void SetShouldHaveTabStrip(bool);
+  void SetShouldHaveReloadButtonInMinimalUi(bool);
+  void SetShouldAllowScriptsToCloseWindows(bool);
+  void SetTimerInfo(const SystemAppBackgroundTaskInfo&);
+  void SetDefaultBounds(base::RepeatingCallback<gfx::Rect(Browser*)>);
+
+ private:
+  WebApplicationInfoFactory info_factory_;
+
+  std::vector<AppId> uninstall_and_replace_;
+  gfx::Size minimum_window_size_;
+  bool single_window_ = true;
+  bool include_launch_directory_ = false;
+  std::vector<int> additional_search_terms_;
+  bool show_in_launcher_ = true;
+  bool show_in_search_ = true;
+  bool capture_navigations_ = false;
+  bool is_resizeable_ = true;
+  bool is_maximizable_ = true;
+  bool has_tab_strip_ = false;
+  bool should_have_reload_button_in_minimal_ui_ = true;
+  bool allow_scripts_to_close_windows_ = false;
+
+  base::RepeatingCallback<gfx::Rect(Browser*)> get_default_bounds_ =
+      base::NullCallback();
+
+  absl::optional<SystemAppBackgroundTaskInfo> timer_info_;
+};
+
 // Class to setup the installation of a test System Web App.
 //
 // Use SetUp*() methods to create a instance of this class in test suite's
@@ -87,11 +158,14 @@
   }
 
  private:
-  TestSystemWebAppInstallation(SystemAppType type, SystemAppInfo info);
+  TestSystemWebAppInstallation(
+      SystemAppType type,
+      std::unique_ptr<UnittestingSystemAppDelegate> system_app_delegate);
   TestSystemWebAppInstallation();
 
-  std::unique_ptr<KeyedService> CreateWebAppProvider(SystemAppInfo info,
-                                                     Profile* profile);
+  std::unique_ptr<KeyedService> CreateWebAppProvider(
+      UnittestingSystemAppDelegate* system_app_delegate,
+      Profile* profile);
   std::unique_ptr<KeyedService> CreateWebAppProviderWithNoSystemWebApps(
       Profile* profile);
 
@@ -107,7 +181,8 @@
   std::vector<std::unique_ptr<TestSystemWebAppWebUIControllerFactory>>
       web_ui_controller_factories_;
   std::set<ContentSettingsType> auto_granted_permissions_;
-  base::flat_map<SystemAppType, SystemAppInfo> extra_apps_;
+  base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>
+      system_app_delegates_;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.cc b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.cc
index 039fddf..b16e019 100644
--- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.cc
@@ -4,14 +4,17 @@
 
 #include "chrome/browser/web_applications/system_web_apps/test/test_system_web_app_manager.h"
 
+#include <memory>
 #include <string>
 #include <utility>
+#include "chrome/browser/web_applications/system_web_apps/system_web_app_delegate.h"
 
 namespace web_app {
 
 TestSystemWebAppManager::TestSystemWebAppManager(Profile* profile)
     : SystemWebAppManager(profile) {
-  SetSystemAppsForTesting(base::flat_map<SystemAppType, SystemAppInfo>());
+  SetSystemAppsForTesting(
+      base::flat_map<SystemAppType, std::unique_ptr<SystemWebAppDelegate>>());
 }
 
 TestSystemWebAppManager::~TestSystemWebAppManager() = default;
diff --git a/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.cc b/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.cc
index d39aa94..e2ba20a2 100644
--- a/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.cc
+++ b/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.cc
@@ -15,9 +15,16 @@
 TestExternallyManagedAppManagerImpl::~TestExternallyManagedAppManagerImpl() =
     default;
 
+void TestExternallyManagedAppManagerImpl::InstallNow(
+    ExternalInstallOptions install_options,
+    OnceInstallCallback callback) {
+  Install(install_options, std::move(callback));
+}
+
 void TestExternallyManagedAppManagerImpl::Install(
     ExternalInstallOptions install_options,
     OnceInstallCallback callback) {
+  install_requests_.push_back(install_options);
   if (handle_install_request_callback_) {
     base::ThreadTaskRunnerHandle::Get()->PostTaskAndReplyWithResult(
         FROM_HERE,
@@ -25,8 +32,6 @@
         base::BindOnce(std::move(callback), install_options.install_url));
     return;
   }
-
-  install_requests_.push_back(install_options);
   ExternallyManagedAppManagerImpl::Install(install_options,
                                            std::move(callback));
 }
@@ -52,6 +57,8 @@
     std::vector<GURL> uninstall_urls,
     ExternalInstallSource install_source,
     const UninstallCallback& callback) {
+  std::copy(uninstall_urls.begin(), uninstall_urls.end(),
+            std::back_inserter(uninstall_requests_));
   if (handle_uninstall_request_callback_) {
     for (auto& app_url : uninstall_urls) {
       base::ThreadTaskRunnerHandle::Get()->PostTaskAndReplyWithResult(
@@ -62,9 +69,6 @@
     }
     return;
   }
-
-  std::copy(uninstall_urls.begin(), uninstall_urls.end(),
-            std::back_inserter(uninstall_requests_));
   ExternallyManagedAppManagerImpl::UninstallApps(uninstall_urls, install_source,
                                                  std::move(callback));
 }
diff --git a/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h b/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h
index 889e4ea..c5e635dc 100644
--- a/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h
+++ b/chrome/browser/web_applications/test/test_externally_managed_app_manager_impl.h
@@ -19,6 +19,8 @@
   explicit TestExternallyManagedAppManagerImpl(Profile* profile);
   ~TestExternallyManagedAppManagerImpl() override;
 
+  void InstallNow(ExternalInstallOptions install_options,
+                  OnceInstallCallback callback) override;
   void Install(ExternalInstallOptions install_options,
                OnceInstallCallback callback) override;
   void InstallApps(std::vector<ExternalInstallOptions> install_options_list,
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 7d4f77b..65e866ed 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -49,45 +49,6 @@
 
 namespace {
 
-// TODO(loyso): Call sites should specify Source explicitly as a part of
-// AppTraits parameter object.
-Source::Type InferSourceFromMetricsInstallSource(
-    webapps::WebappInstallSource install_source) {
-  switch (install_source) {
-    case webapps::WebappInstallSource::MENU_BROWSER_TAB:
-    case webapps::WebappInstallSource::MENU_CUSTOM_TAB:
-    case webapps::WebappInstallSource::AUTOMATIC_PROMPT_BROWSER_TAB:
-    case webapps::WebappInstallSource::AUTOMATIC_PROMPT_CUSTOM_TAB:
-    case webapps::WebappInstallSource::API_BROWSER_TAB:
-    case webapps::WebappInstallSource::API_CUSTOM_TAB:
-    case webapps::WebappInstallSource::DEVTOOLS:
-    case webapps::WebappInstallSource::MANAGEMENT_API:
-    case webapps::WebappInstallSource::AMBIENT_BADGE_BROWSER_TAB:
-    case webapps::WebappInstallSource::AMBIENT_BADGE_CUSTOM_TAB:
-    case webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON:
-    case webapps::WebappInstallSource::SYNC:
-    case webapps::WebappInstallSource::MENU_CREATE_SHORTCUT:
-      return Source::kSync;
-
-    case webapps::WebappInstallSource::INTERNAL_DEFAULT:
-    case webapps::WebappInstallSource::EXTERNAL_DEFAULT:
-      return Source::kDefault;
-
-    case webapps::WebappInstallSource::EXTERNAL_POLICY:
-      return Source::kPolicy;
-
-    case webapps::WebappInstallSource::SYSTEM_DEFAULT:
-      return Source::kSystem;
-
-    case webapps::WebappInstallSource::ARC:
-      return Source::kWebAppStore;
-
-    case webapps::WebappInstallSource::COUNT:
-      NOTREACHED();
-      return Source::kSync;
-  }
-}
-
 Source::Type InferSourceFromWebAppUninstallSource(
     webapps::WebappUninstallSource external_install_source) {
   switch (external_install_source) {
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index afa4398..b17207e 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -30,6 +30,7 @@
   "accessibilityPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
+    "platforms": ["chromeos"],
     "allowlist": [
       "0D209B5E4401BB8E7873B5AB5B1346A1CB067015",  // http://crbug.com/1039158
       "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E"
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json
index 8c1154d2..35a7bfb 100644
--- a/chrome/common/extensions/api/accessibility_private.json
+++ b/chrome/common/extensions/api/accessibility_private.json
@@ -6,9 +6,10 @@
   {
     "namespace": "accessibilityPrivate",
     "compiler_options": {
-      "implemented_in": "chrome/browser/accessibility/accessibility_extension_api.h"
+      "implemented_in": "chrome/browser/accessibility/accessibility_extension_api_chromeos.h"
     },
     "description": "none",
+    "platforms": ["chromeos"],
     "types": [
       {
         "id": "AlertInfo",
@@ -260,8 +261,7 @@
         "returns": {
           "type": "string",
           "description": "The human-readable locale string in the provided locale."
-        },
-        "platforms": ["chromeos"]
+        }
       },
       {
         "name": "getBatteryDescription",
@@ -279,8 +279,7 @@
               }
             ]
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "setNativeAccessibilityEnabled",
@@ -364,8 +363,7 @@
             "name": "shouldForward",
             "type": "boolean"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "updateSwitchAccessBubble",
@@ -395,8 +393,7 @@
             "description": "The actions to be shown in the menu.",
             "optional": true
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "setPointScanState",
@@ -408,8 +405,7 @@
             "$ref": "PointScanState",
             "description": "The point scanning state to set."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "setNativeChromeVoxArcSupportForCurrentApp",
@@ -421,8 +417,7 @@
             "type": "boolean",
             "description": "True for ChromeVox (native), false for TalkBack."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "sendSyntheticKeyEvent",
@@ -434,8 +429,7 @@
             "$ref": "SyntheticKeyboardEvent",
             "description": "The event to send."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "enableMouseEvents",
@@ -447,8 +441,7 @@
             "type": "boolean",
             "description": "True if accessibility component extensions should receive mouse events."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "sendSyntheticMouseEvent",
@@ -460,8 +453,7 @@
             "$ref": "SyntheticMouseEvent",
             "description": "The event to send."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "setSelectToSpeakState",
@@ -472,8 +464,7 @@
             "name": "state",
             "$ref": "SelectToSpeakState"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "handleScrollableBoundsForPointFound",
@@ -484,8 +475,7 @@
             "name": "rect",
             "$ref": "ScreenRect"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "moveMagnifierToRect",
@@ -497,15 +487,13 @@
             "$ref": "ScreenRect",
             "description": "Rect to ensure visible in the magnified viewport."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "toggleDictation",
         "type": "function",
         "description": "Toggles dictation between active and inactive states.",
-        "parameters": [],
-        "platforms": ["chromeos"]
+        "parameters": []
       },
       {
         "name": "setVirtualKeyboardVisible",
@@ -516,8 +504,7 @@
             "name": "isVisible",
             "type": "boolean"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "openSettingsSubpage",
@@ -528,8 +515,7 @@
             "name": "subpage",
             "type": "string"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "performAcceleratorAction",
@@ -540,8 +526,7 @@
             "name": "acceleratorAction",
             "$ref": "AcceleratorAction"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "isFeatureEnabled",
@@ -563,8 +548,7 @@
               }
             ]
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "updateSelectToSpeakPanel",
@@ -594,8 +578,7 @@
             "description": "Current reading speed (TTS speech rate).",
             "optional": true
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "showConfirmationDialog",
@@ -624,8 +607,7 @@
               }
             ]
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       }
     ],
     "events": [
@@ -669,8 +651,7 @@
         "name": "onSelectToSpeakStateChangeRequested",
         "type": "function",
         "description": "Fired when Chrome OS wants to change the Select-to-Speak state, between selecting with the mouse, speaking, and inactive.",
-        "parameters": [],
-        "platforms": ["chromeos"]
+        "parameters": []
       },
       {
         "name": "onSelectToSpeakPanelAction",
@@ -686,8 +667,7 @@
             "type": "number",
             "optional": true
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onSwitchAccessCommand",
@@ -698,8 +678,7 @@
             "name": "command",
             "$ref": "SwitchAccessCommand"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onPointScanSet",
@@ -710,8 +689,7 @@
             "name": "point",
             "$ref": "PointScanPoint"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onMagnifierCommand",
@@ -722,8 +700,7 @@
             "name": "command",
             "$ref": "MagnifierCommand"
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onAnnounceForAccessibility",
@@ -736,8 +713,7 @@
             "items": { "type": "string" },
             "description": "Text to be announced."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onScrollableBoundsForPointRequested",
@@ -754,8 +730,7 @@
             "type": "number",
             "description": "Y screen coordinate of the point."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onMagnifierBoundsChanged",
@@ -767,8 +742,7 @@
             "$ref": "ScreenRect",
             "description": "Updated bounds of magnifier viewport."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onCustomSpokenFeedbackToggled",
@@ -780,15 +754,13 @@
             "type": "boolean",
             "description": "True if the active window implements custom spoken feedback features."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       },
       {
         "name": "onShowChromeVoxTutorial",
         "type": "function",
         "description": "Fired when ChromeVox should show its tutorial.",
-        "parameters": [],
-        "platforms": ["chromeos"]
+        "parameters": []
       },
       {
         "name": "onToggleDictation",
@@ -800,8 +772,7 @@
             "type": "boolean",
             "description": "True if Dictation was activated, false if it was deactivated."
           }
-        ],
-        "platforms": ["chromeos"]
+        ]
       }
     ]
   }
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni
index 27fc40b..928dd99 100644
--- a/chrome/common/extensions/api/api_sources.gni
+++ b/chrome/common/extensions/api/api_sources.gni
@@ -10,7 +10,6 @@
 
 schema_sources_ = [
   "accessibility_features.json",
-  "accessibility_private.json",
   "activity_log_private.json",
   "autofill_private.idl",
   "autotest_private.idl",
@@ -87,6 +86,7 @@
 
 if (is_chromeos_ash) {
   schema_sources_ += [
+    "accessibility_private.json",
     "certificate_provider.idl",
     "certificate_provider_internal.idl",
     "document_scan.idl",
diff --git a/chrome/common/media/cdm_registration.cc b/chrome/common/media/cdm_registration.cc
index ea65aeca..add60275 100644
--- a/chrome/common/media/cdm_registration.cc
+++ b/chrome/common/media/cdm_registration.cc
@@ -21,12 +21,10 @@
 
 #if BUILDFLAG(ENABLE_WIDEVINE)
 #include "third_party/widevine/cdm/widevine_cdm_common.h"  // nogncheck
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || \
-    BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
 #include "base/native_library.h"
 #include "chrome/common/chrome_paths.h"
-#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) ||
-        // BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
+#endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
 #include "base/no_destructor.h"
 #include "components/cdm/common/cdm_manifest.h"
@@ -267,26 +265,28 @@
 
   cdms->push_back(content::CdmInfo(
       kWidevineKeySystem, Robustness::kHardwareSecure, std::move(capability)));
-#elif BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
-  // TODO(hmchen): Remove this after the Windows CDM is component updated.
-  base::FilePath install_dir;
-  if (!base::PathService::Get(chrome::DIR_BUNDLED_WIDEVINE_CDM, &install_dir))
-    return;
+#elif defined(OS_WIN)
+  // TODO(alstonge): Remove this after the Windows CDM is component updated.
+  if (base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) {
+    base::FilePath install_dir;
+    if (!base::PathService::Get(chrome::DIR_BUNDLED_WIDEVINE_CDM, &install_dir))
+      return;
 
-  auto widevine_cdm_path = install_dir.AppendASCII(
-      base::GetNativeLibraryName(kMediaFoundationWidevineCdmLibraryName));
-  if (!base::PathExists(widevine_cdm_path))
-    return;
+    auto widevine_cdm_path = install_dir.AppendASCII(
+        base::GetNativeLibraryName(kMediaFoundationWidevineCdmLibraryName));
+    if (!base::PathExists(widevine_cdm_path))
+      return;
 
-  // Register Widevine hardware secure support for lazy initialization.
-  // TODO(xhwang): Get the version from the DLL.
-  VLOG(1) << "Registering " << kMediaFoundationWidevineCdmDisplayName;
-  cdms->push_back(content::CdmInfo(
-      kWidevineKeySystem, Robustness::kHardwareSecure, absl::nullopt,
-      /*supports_sub_key_systems=*/false,
-      kMediaFoundationWidevineCdmDisplayName, kMediaFoundationWidevineCdmGuid,
-      base::Version(), widevine_cdm_path,
-      /*file_system_id=*/""));
+    // Register Widevine hardware secure support for lazy initialization.
+    // TODO(xhwang): Get the version from the DLL.
+    VLOG(1) << "Registering " << kMediaFoundationWidevineCdmDisplayName;
+    cdms->push_back(content::CdmInfo(
+        kWidevineKeySystem, Robustness::kHardwareSecure, absl::nullopt,
+        /*supports_sub_key_systems=*/false,
+        kMediaFoundationWidevineCdmDisplayName, kMediaFoundationWidevineCdmGuid,
+        base::Version(), widevine_cdm_path,
+        /*file_system_id=*/""));
+  }
 #endif  // BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
 }
 
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index feb45215..aa7b845 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -94,7 +94,6 @@
 #include "components/no_state_prefetch/renderer/prerender_render_frame_observer.h"
 #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
 #include "components/paint_preview/buildflags/buildflags.h"
-#include "components/pdf/renderer/pepper_pdf_host.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/safe_browsing/content/renderer/threat_dom_details.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
@@ -227,6 +226,7 @@
 
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW)
 #include "chrome/renderer/pepper/chrome_pdf_print_client.h"
+#include "components/pdf/renderer/pepper_pdf_host.h"
 #endif
 
 #if BUILDFLAG(ENABLE_PAINT_PREVIEW)
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
index baaff54..a4aa633 100644
--- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
+++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -13,7 +13,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/crash_keys.h"
 #include "chrome/grit/renderer_resources.h"
-#include "chrome/renderer/extensions/accessibility_private_hooks_delegate.h"
 #include "chrome/renderer/extensions/app_hooks_delegate.h"
 #include "chrome/renderer/extensions/extension_hooks_delegate.h"
 #include "chrome/renderer/extensions/media_galleries_custom_bindings.h"
@@ -48,6 +47,7 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "chrome/renderer/extensions/accessibility_private_hooks_delegate.h"
 #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
 #include "chrome/renderer/extensions/file_manager_private_custom_bindings.h"
 #if defined(USE_CUPS)
@@ -209,46 +209,6 @@
   source_map->RegisterSource("chromeWebViewInternal",
                              IDR_CHROME_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS);
   source_map->RegisterSource("chromeWebView", IDR_CHROME_WEB_VIEW_JS);
-
-  // Media router.
-  source_map->RegisterSource(
-      "components/media_router/common/mojom/media_controller.mojom",
-      IDR_MEDIA_CONTROLLER_MOJOM_JS);
-  source_map->RegisterSource(
-      "components/media_router/common/mojom/media_router.mojom",
-      IDR_MEDIA_ROUTER_MOJOM_JS);
-  source_map->RegisterSource(
-      "components/media_router/common/mojom/media_status.mojom",
-      IDR_MEDIA_STATUS_MOJOM_JS);
-  source_map->RegisterSource("media_router_bindings",
-                             IDR_MEDIA_ROUTER_BINDINGS_JS);
-  source_map->RegisterSource("mojo/public/mojom/base/time.mojom",
-                             IDR_MOJO_TIME_MOJOM_JS);
-  source_map->RegisterSource("mojo/public/mojom/base/unguessable_token.mojom",
-                             IDR_MOJO_UNGUESSABLE_TOKEN_MOJOM_JS);
-  source_map->RegisterSource("net/interfaces/ip_address.mojom",
-                             IDR_MOJO_IP_ADDRESS_MOJOM_JS);
-  source_map->RegisterSource("net/interfaces/ip_endpoint.mojom",
-                             IDR_MOJO_IP_ENDPOINT_MOJOM_JS);
-  source_map->RegisterSource("url/mojom/origin.mojom", IDR_ORIGIN_MOJOM_JS);
-  source_map->RegisterSource("url/mojom/url.mojom", IDR_MOJO_URL_MOJOM_JS);
-  source_map->RegisterSource("media/mojo/mojom/remoting_common.mojom",
-                             IDR_REMOTING_COMMON_JS);
-  source_map->RegisterSource(
-      "components/mirroring/mojom/mirroring_service_host.mojom",
-      IDR_MIRRORING_SERVICE_HOST_MOJOM_JS);
-  source_map->RegisterSource(
-      "components/mirroring/mojom/cast_message_channel.mojom",
-      IDR_MIRRORING_CAST_MESSAGE_CHANNEL_MOJOM_JS);
-  source_map->RegisterSource(
-      "components/mirroring/mojom/session_observer.mojom",
-      IDR_MIRRORING_SESSION_OBSERVER_MOJOM_JS);
-  source_map->RegisterSource(
-      "components/mirroring/mojom/session_parameters.mojom",
-      IDR_MIRRORING_SESSION_PARAMETERS_JS);
-  source_map->RegisterSource(
-      "third_party/blink/public/mojom/presentation/presentation.mojom",
-      IDR_PRESENTATION_JS);
 }
 
 void ChromeExtensionsDispatcherDelegate::RequireWebViewModules(
@@ -280,9 +240,11 @@
   bindings->GetHooksForAPI("tabs")->SetDelegate(
       std::make_unique<extensions::TabsHooksDelegate>(
           bindings_system->messaging_service()));
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   bindings->GetHooksForAPI("accessibilityPrivate")
       ->SetDelegate(
           std::make_unique<extensions::AccessibilityPrivateHooksDelegate>());
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #if BUILDFLAG(IS_CHROMEOS_ASH) && defined(USE_CUPS)
   bindings->GetHooksForAPI("printing")
       ->SetDelegate(std::make_unique<extensions::PrintingHooksDelegate>());
diff --git a/chrome/renderer/resources/extensions/OWNERS b/chrome/renderer/resources/extensions/OWNERS
index 10bcbf3..c21f9cc 100644
--- a/chrome/renderer/resources/extensions/OWNERS
+++ b/chrome/renderer/resources/extensions/OWNERS
@@ -10,5 +10,4 @@
 per-file file_manager_private_custom_bindings.js=file://ui/file_manager/OWNERS
 per-file image_util.js=dewittj@chromium.org
 per-file media_galleries*.js=file://chrome/browser/media_galleries/OWNERS
-per-file media_router_bindings.js=file://chrome/browser/media/router/OWNERS
 per-file notifications_*.js=dewittj@chromium.org
diff --git a/chrome/renderer/resources/extensions/media_router_bindings.js b/chrome/renderer/resources/extensions/media_router_bindings.js
deleted file mode 100644
index 6e728d2..0000000
--- a/chrome/renderer/resources/extensions/media_router_bindings.js
+++ /dev/null
@@ -1,1284 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-if ((typeof mojo === 'undefined') || !mojo.bindingsLibraryInitialized) {
-  loadScript('mojo_bindings');
-}
-mojo.config.autoLoadMojomDeps = false;
-
-loadScript('components/media_router/common/mojom/media_controller.mojom');
-loadScript('components/media_router/common/mojom/media_router.mojom');
-loadScript('components/media_router/common/mojom/media_status.mojom');
-loadScript('components/mirroring/mojom/cast_message_channel.mojom');
-loadScript('components/mirroring/mojom/mirroring_service_host.mojom');
-loadScript('components/mirroring/mojom/session_observer.mojom');
-loadScript('components/mirroring/mojom/session_parameters.mojom');
-loadScript('extensions/common/mojom/keep_alive.mojom');
-loadScript('media/mojo/mojom/remoting_common.mojom');
-loadScript('mojo/public/mojom/base/time.mojom');
-loadScript('mojo/public/mojom/base/unguessable_token.mojom');
-loadScript('net/interfaces/ip_address.mojom');
-loadScript('net/interfaces/ip_endpoint.mojom');
-loadScript('third_party/blink/public/mojom/presentation/presentation.mojom');
-loadScript('url/mojom/origin.mojom');
-loadScript('url/mojom/url.mojom');
-
-// The following adapter classes preserve backward compatibility for the media
-// router component extension.
-// TODO(crbug.com/787128): Remove these adapters.
-
-function assignFields(object, fields) {
-  for(var field in fields) {
-    if (object.hasOwnProperty(field))
-      object[field] = fields[field];
-  }
-}
-
-/**
- * Adapter for mediaRouter.mojom.DialMediaSink.
- * @constructor
- */
-function DialMediaSinkAdapter(fields) {
-  this.ip_address = null;
-  this.model_name = null;
-  this.app_url = null;
-
-  assignFields(this, fields);
-}
-
-DialMediaSinkAdapter.fromNewVersion = function(other) {
-  return new DialMediaSinkAdapter({
-    'ip_address': IPAddressAdapter.fromNewVersion(other.ipAddress),
-    'model_name': other.modelName,
-    'app_url': other.appUrl,
-  });
-};
-
-DialMediaSinkAdapter.prototype.toNewVersion = function() {
-  return new mediaRouter.mojom.DialMediaSink({
-    'ipAddress' : this.ip_address.toNewVersion(),
-    'modelName' : this.model_name,
-    'appUrl' : this.app_url,
-  });
-};
-
-/**
- * Adapter for mediaRouter.mojom.CastMediaSink.
- * @constructor
- */
-function CastMediaSinkAdapter(fields) {
-  this.ip_endpoint = null;
-  this.model_name = null;
-  this.capabilities = 0;
-  this.cast_channel_id = 0;
-
-  assignFields(this, fields);
-}
-
-CastMediaSinkAdapter.fromNewVersion = function(other) {
-  return new CastMediaSinkAdapter({
-    'ip_endpoint': IPEndpointAdapter.fromNewVersion(other.ipEndpoint),
-    'model_name': other.modelName,
-    'capabilities': other.capabilities,
-    'cast_channel_id': other.castChannelId,
-  });
-};
-
-CastMediaSinkAdapter.prototype.toNewVersion = function() {
-  return new mediaRouter.mojom.CastMediaSink({
-    'ipEndpoint': this.ip_endpoint.toNewVersion(),
-    'modelName': this.model_name,
-    'capabilities': this.capabilities,
-    'castChannelId': this.cast_channel_id,
-  });
-};
-
-/**
- * Adapter for net.interfaces.IPAddress.
- * @constructor
- */
-function IPAddressAdapter(fields) {
-  this.address_bytes = null;
-
-  assignFields(this, fields);
-}
-
-IPAddressAdapter.fromNewVersion = function(other) {
-  return new IPAddressAdapter({
-    'address_bytes': other.addressBytes,
-  });
-};
-
-IPAddressAdapter.prototype.toNewVersion = function() {
-  return new net.interfaces.IPAddress({
-    'addressBytes': this.address_bytes,
-  });
-};
-
-/**
- * Adapter for net.interfaces.IPEndpoint.
- * @constructor
- */
-function IPEndpointAdapter(fields) {
-  this.address = null;
-  this.port = 0;
-
-  assignFields(this, fields);
-}
-
-IPEndpointAdapter.fromNewVersion = function(other) {
-  return new IPEndpointAdapter({
-    'address': IPAddressAdapter.fromNewVersion(other.address),
-    'port': other.port,
-  });
-};
-
-IPEndpointAdapter.prototype.toNewVersion = function() {
-  return new net.interfaces.IPEndpoint({
-    'address': this.address.toNewVersion(),
-    'port': this.port,
-  });
-};
-
-/**
- * Adapter for mediaRouter.mojom.MediaStatus.
- * @constructor
- */
-function MediaStatusAdapter(fields) {
-  this.title = null;
-  this.secondary_title = null;
-  this.can_play_pause = false;
-  this.can_mute = false;
-  this.can_set_volume = false;
-  this.can_seek = false;
-  this.can_skip_to_next_track = false;
-  this.can_skip_to_previous_track = false;
-  this.is_muted = false;
-  this.play_state = 0;
-  this.volume = 0;
-  this.duration = null;
-  this.current_time = null;
-  this.images = null;
-
-  assignFields(this, fields);
-}
-
-MediaStatusAdapter.PlayState = mediaRouter.mojom.MediaStatus.PlayState;
-
-MediaStatusAdapter.prototype.toNewVersion = function() {
-  return new mediaRouter.mojom.MediaStatus({
-    'title': this.title,
-    'secondaryTitle': this.secondary_title || '',
-    'canPlayPause': this.can_play_pause,
-    'canMute': this.can_mute,
-    'canSetVolume': this.can_set_volume,
-    'canSeek': this.can_seek,
-    'canSkipToNextTrack': this.can_skip_to_next_track,
-    'canSkipToPreviousTrack': this.can_skip_to_previous_track,
-    'isMuted': this.is_muted,
-    'playState': this.play_state,
-    'volume': this.volume,
-    'duration': this.duration,
-    'currentTime': this.current_time,
-    'images': this.images || [],
-  });
-};
-
-/**
- * Adapter for media.mojom.RemotingSinkMetadata.
- * @constructor
- */
-function RemotingSinkMetadataAdapter(fields) {
-  this.features = null;
-  this.audio_capabilities = null;
-  this.video_capabilities = null;
-  this.friendly_name = null;
-
-  assignFields(this, fields);
-}
-
-RemotingSinkMetadataAdapter.fromNewVersion = function(other) {
-  return new RemotingSinkMetadataAdapter({
-    'features': other.features,
-    'audio_capabilities': other.audioCapabilities,
-    'video_capabilities': other.videoCapabilities,
-    'friendly_name': other.friendlyName,
-  });
-};
-
-RemotingSinkMetadataAdapter.prototype.toNewVersion = function() {
-  return new media.mojom.RemotingSinkMetadata({
-    'features': this.features,
-    'audioCapabilities': this.audio_capabilities,
-    'videoCapabilities': this.video_capabilities,
-    'friendlyName': this.friendly_name,
-  });
-};
-
-/**
- * Adapter for mediaRouter.mojom.MediaSink.
- * @constructor
- */
-function MediaSinkAdapter(fields) {
-  this.sink_id = null;
-  this.name = null;
-  this.description = null;
-  this.domain = null;
-  this.icon_type = 0;
-  this.extra_data = null;
-
-  assignFields(this, fields);
-}
-
-MediaSinkAdapter.fromNewVersion = function(other) {
-  return new MediaSinkAdapter({
-    'sink_id': other.sinkId,
-    'name': other.name,
-    'description': other.description,
-    'domain': other.domain,
-    'icon_type': other.iconType,
-    'extra_data': other.extraData &&
-        MediaSinkExtraDataAdapter.fromNewVersion(other.extraData),
-  });
-};
-
-MediaSinkAdapter.prototype.toNewVersion = function() {
-  return new mediaRouter.mojom.MediaSink({
-    'sinkId': this.sink_id,
-    'name': this.name,
-    'description': this.description,
-    'domain': this.domain,
-    'iconType': this.icon_type,
-    'extraData': this.extra_data && this.extra_data.toNewVersion(),
-  });
-};
-
-/**
- * Adapter for mediaRouter.mojom.MediaSinkExtraData.
- * @constructor
- */
-function MediaSinkExtraDataAdapter(value) {
-  this.$data = null;
-  this.$tag = undefined;
-
-  if (value === undefined) {
-    return;
-  }
-
-  var keys = Object.keys(value);
-  if (keys.length === 0) {
-    return;
-  }
-
-  if (keys.length > 1) {
-    throw new TypeError('You may set only one member on a union.');
-  }
-
-  var fields = [
-    'dial_media_sink',
-    'cast_media_sink',
-  ];
-
-  if (fields.indexOf(keys[0]) < 0) {
-    throw new ReferenceError(keys[0] +
-        ' is not a MediaSinkExtraDataAdapter member.');
-  }
-
-  this[keys[0]] = value[keys[0]];
-}
-
-MediaSinkExtraDataAdapter.Tags = {
-  dial_media_sink: 0,
-  cast_media_sink: 1,
-};
-
-Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'dial_media_sink', {
-  get: function() {
-    if (this.$tag !== MediaSinkExtraDataAdapter.Tags.dial_media_sink) {
-      throw new ReferenceError(
-          'MediaSinkExtraDataAdapter.dial_media_sink is not currently set.');
-    }
-    return this.$data;
-  },
-
-  set: function(value) {
-    this.$tag = MediaSinkExtraDataAdapter.Tags.dial_media_sink;
-    this.$data = value;
-  }
-});
-
-Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'cast_media_sink', {
-  get: function() {
-    if (this.$tag !== MediaSinkExtraDataAdapter.Tags.cast_media_sink) {
-      throw new ReferenceError(
-          'MediaSinkExtraDataAdapter.cast_media_sink is not currently set.');
-    }
-    return this.$data;
-  },
-
-  set: function(value) {
-    this.$tag = MediaSinkExtraDataAdapter.Tags.cast_media_sink;
-    this.$data = value;
-  }
-});
-
-MediaSinkExtraDataAdapter.fromNewVersion = function(other) {
-  if (other.$tag === mediaRouter.mojom.MediaSinkExtraData.Tags.dialMediaSink) {
-    return new MediaSinkExtraDataAdapter({
-      'dial_media_sink':
-          DialMediaSinkAdapter.fromNewVersion(other.dialMediaSink),
-    });
-  } else {
-    return new MediaSinkExtraDataAdapter({
-      'cast_media_sink':
-          CastMediaSinkAdapter.fromNewVersion(other.castMediaSink),
-    });
-  }
-};
-
-MediaSinkExtraDataAdapter.prototype.toNewVersion = function() {
-  if (this.$tag === MediaSinkExtraDataAdapter.Tags.dial_media_sink) {
-    return new mediaRouter.mojom.MediaSinkExtraData({
-      'dialMediaSink': this.dial_media_sink.toNewVersion(),
-    });
-  } else {
-    return new mediaRouter.mojom.MediaSinkExtraData({
-      'castMediaSink': this.cast_media_sink.toNewVersion(),
-    });
-  }
-};
-
-/**
- * Adapter for mediaRouter.mojom.MediaStatusObserver.
- * @constructor
- */
-function MediaStatusObserverPtrAdapter(handleOrPtrInfo) {
-  this.ptr = new mojo.InterfacePtrController(MediaStatusObserverAdapter,
-                                             handleOrPtrInfo);
-}
-
-MediaStatusObserverPtrAdapter.prototype =
-    Object.create(mediaRouter.mojom.MediaStatusObserverPtr.prototype);
-MediaStatusObserverPtrAdapter.prototype.constructor =
-    MediaStatusObserverPtrAdapter;
-
-MediaStatusObserverPtrAdapter.prototype.onMediaStatusUpdated =
-    function(status) {
-  return this.ptr.getProxy().onMediaStatusUpdated(status.toNewVersion());
-};
-
-/**
- * Adapter for mediaRouter.mojom.MediaStatusObserver.
- */
-var MediaStatusObserverAdapter = {
-  name: 'mediaRouter.mojom.MediaStatusObserver',
-  kVersion: 0,
-  ptrClass: MediaStatusObserverPtrAdapter,
-  proxyClass: mediaRouter.mojom.MediaStatusObserver.proxyClass,
-  stubClass: null,
-  validateRequest: mediaRouter.mojom.MediaStatusObserver.validateRequest,
-  validateResponse: null,
-};
-
-/**
- * Converts a media sink to a MediaSink Mojo object.
- * @param {!MediaSink} sink A media sink.
- * @return {!mediaRouter.mojom.MediaSink} A Mojo MediaSink object.
- */
-function sinkToMojo_(sink) {
-  return new mediaRouter.mojom.MediaSink({
-    'name': sink.friendlyName,
-    'description': sink.description,
-    'domain': sink.domain,
-    'sinkId': sink.id,
-    'iconType': sinkIconTypeToMojo(sink.iconType),
-    'providerId': mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
-  });
-}
-
-/**
- * Converts a media sink's icon type to a MediaSink.IconType Mojo object.
- * @param {!MediaSink.IconType} type A media sink's icon type.
- * @return {!mediaRouter.mojom.MediaSink.IconType} A Mojo MediaSink.IconType
- *     object.
- */
-function sinkIconTypeToMojo(type) {
-  switch (type) {
-    case 'cast':
-      return mediaRouter.mojom.SinkIconType.CAST;
-    case 'cast_audio_group':
-      return mediaRouter.mojom.SinkIconType.CAST_AUDIO_GROUP;
-    case 'cast_audio':
-      return mediaRouter.mojom.SinkIconType.CAST_AUDIO;
-    case 'generic':
-      return mediaRouter.mojom.SinkIconType.GENERIC;
-    default:
-      console.error('Unknown sink icon type : ' + type);
-      return mediaRouter.mojom.SinkIconType.GENERIC;
-  }
-}
-
-/**
- * Returns a Mojo MediaRoute object given a MediaRoute and a
- * media sink name.
- * @param {!MediaRoute} route
- * @return {!mediaRouter.mojom.MediaRoute}
- */
-function routeToMojo_(route) {
-  return new mediaRouter.mojom.MediaRoute({
-    'mediaRouteId': route.id,
-    'mediaSource': route.mediaSource,
-    'mediaSinkId': route.sinkId,
-    'description': route.description,
-    'iconUrl': route.iconUrl,
-    'isLocal': route.isLocal,
-    'forDisplay': route.forDisplay,
-    'isOffTheRecord': route.offTheRecord,
-    'isLocalPresentation': route.isOffscreenPresentation,
-    'controllerType': route.controllerType,
-    'presentationId': route.presentationId,
-    'mediaSinkName': route.sinkName,
-    // Begin newly added properties, followed by the milestone they were
-    // added.  The guard should be safe to remove N+2 milestones later.
-    'isConnecting':route.isConnecting || false  // M92
-  });
-}
-
-/**
- * Converts a route message to a RouteMessage Mojo object.
- * @param {!RouteMessage} message
- * @return {!mediaRouter.mojom.RouteMessage} A Mojo RouteMessage object.
- */
-function messageToMojo_(message) {
-  if ('string' === typeof message.message) {
-    return new mediaRouter.mojom.RouteMessage({
-      'type': mediaRouter.mojom.RouteMessage.Type.TEXT,
-      'message': message.message,
-    });
-  } else {
-    return new mediaRouter.mojom.RouteMessage({
-      'type': mediaRouter.mojom.RouteMessage.Type.BINARY,
-      'data': message.message,
-    });
-  }
-}
-
-/**
- * Converts presentation connection state to Mojo enum value.
- * @param {!string} state
- * @return {!blink.mojom.PresentationConnectionState}
- */
-function presentationConnectionStateToMojo_(state) {
-  var PresentationConnectionState =
-      blink.mojom.PresentationConnectionState;
-  switch (state) {
-    case 'connecting':
-      return PresentationConnectionState.CONNECTING;
-    case 'connected':
-      return PresentationConnectionState.CONNECTED;
-    case 'closed':
-      return PresentationConnectionState.CLOSED;
-    case 'terminated':
-      return PresentationConnectionState.TERMINATED;
-    default:
-      console.error('Unknown presentation connection state: ' + state);
-      return PresentationConnectionState.TERMINATED;
-  }
-}
-
-/**
- * Converts presentation connection close reason to Mojo enum value.
- * @param {!string} reason
- * @return {!blink.mojom.PresentationConnectionCloseReason}
- */
-function presentationConnectionCloseReasonToMojo_(reason) {
-  var PresentationConnectionCloseReason =
-      blink.mojom.PresentationConnectionCloseReason;
-  switch (reason) {
-    case 'error':
-      return PresentationConnectionCloseReason.CONNECTION_ERROR;
-    case 'closed':
-      return PresentationConnectionCloseReason.CLOSED;
-    case 'went_away':
-      return PresentationConnectionCloseReason.WENT_AWAY;
-    default:
-      console.error('Unknown presentation connection close reason : ' +
-          reason);
-      return PresentationConnectionCloseReason.CONNECTION_ERROR;
-  }
-}
-
-/**
- * Converts string to Mojo origin.
- * @param {string|!url.mojom.Origin} origin
- * @return {!url.mojom.Origin}
- */
-function stringToMojoOrigin_(origin) {
-  if (origin instanceof url.mojom.Origin) {
-    return origin;
-  }
-  var originUrl = new URL(origin);
-  var mojoOrigin = {};
-  mojoOrigin.scheme = originUrl.protocol.replace(':', '');
-  mojoOrigin.host = originUrl.hostname;
-  var port = originUrl.port ? Number.parseInt(originUrl.port) : 0;
-  switch (mojoOrigin.scheme) {
-    case 'http':
-      mojoOrigin.port = port || 80;
-      break;
-    case 'https':
-      mojoOrigin.port = port || 443;
-      break;
-    default:
-      throw new Error('Scheme must be http or https');
-  }
-  mojoOrigin.suborigin = '';
-  return new url.mojom.Origin(mojoOrigin);
-}
-
-/**
- * Parses the given route request Error object and converts it to the
- * corresponding result code.
- * @param {!Error} error
- * @return {!mediaRouter.mojom.RouteRequestResultCode}
- */
-function getRouteRequestResultCode_(error) {
-  return error.errorCode ? error.errorCode :
-    mediaRouter.mojom.RouteRequestResultCode.UNKNOWN_ERROR;
-}
-
-/**
- * Creates and returns a successful route response from given route.
- * @param {!MediaRoute} route
- * @return {!Object}
- */
-function toSuccessRouteResponse_(route) {
-  return {
-      route: routeToMojo_(route),
-      resultCode: mediaRouter.mojom.RouteRequestResultCode.OK
-  };
-}
-
-/**
- * Creates and returns a error route response from given Error object.
- * @param {!Error} error
- * @return {!Object}
- */
-function toErrorRouteResponse_(error) {
-  return {
-      errorText: error.message,
-      resultCode: getRouteRequestResultCode_(error)
-  };
-}
-
-/**
- * Creates a new MediaRouter.
- * Converts a route struct to its Mojo form.
- * @param {!mediaRouter.mojom.MediaRouterPtr} service
- * @constructor
- */
-function MediaRouter(service) {
-  /**
-   * The Mojo service proxy. Allows extension code to call methods that reside
-   * in the browser.
-   * @type {!mediaRouter.mojom.MediaRouterPtr}
-   */
-  this.service_ = service;
-
-  /**
-   * The provider manager service delegate. Its methods are called by the
-   * browser-resident Mojo service.
-   * @type {!MediaRouter}
-   */
-  this.mrpm_ = new MediaRouteProvider(this);
-
-  /**
-   * Handle to a KeepAlive service object, which prevents the extension from
-   * being suspended as long as it remains in scope.
-   * @type {boolean}
-   */
-  this.keepAlive_ = null;
-
-  /**
-   * The bindings to bind the service delegate to the Mojo interface.
-   * Object must remain in scope for the lifetime of the connection to
-   * prevent the connection from closing automatically.
-   * @type {!mojo.Binding}
-   */
-  this.mediaRouteProviderBinding_ = new mojo.Binding(
-      mediaRouter.mojom.MediaRouteProvider, this.mrpm_);
-}
-
-/**
- * Returns definitions of Mojo core and generated Mojom classes that can be
- * used directly by the component.
- * @return {!Object}
- * TODO(imcheng): We should export these along with MediaRouter. This requires
- * us to modify the component to handle multiple exports. When that logic is
- * baked in for a couple of milestones, we should be able to remove this
- * method.
- * TODO(imcheng): We should stop exporting mojo bindings classes that the
- * Media Router extension doesn't directly use, such as
- * mojo.AssociatedInterfacePtrInfo, mojo.InterfacePtrController and
- * mojo.interfaceControl.
- */
-MediaRouter.prototype.getMojoExports = function() {
-  return {
-    AssociatedInterfacePtrInfo: mojo.AssociatedInterfacePtrInfo,
-    Binding: mojo.Binding,
-    DialMediaSink: DialMediaSinkAdapter,
-    CastMediaSink: CastMediaSinkAdapter,
-    IPAddress: IPAddressAdapter,
-    IPEndpoint: IPEndpointAdapter,
-    InterfacePtrController: mojo.InterfacePtrController,
-    InterfacePtrInfo: mojo.InterfacePtrInfo,
-    InterfaceRequest: mojo.InterfaceRequest,
-    MediaController: mediaRouter.mojom.MediaController,
-    MediaStatus: MediaStatusAdapter,
-    MediaStatusObserverPtr: mediaRouter.mojom.MediaStatusObserverPtr,
-    MirroringCastMessage: mirroring.mojom.CastMessage,
-    MirroringCastMessageChannel: mirroring.mojom.CastMessageChannel,
-    MirroringCastMessageChannelPtr: mirroring.mojom.CastMessageChannelPtr,
-    MirroringServiceHostPtr: mirroring.mojom.MirroringServiceHostPtr,
-    MirroringSessionError: mirroring.mojom.SessionError,
-    MirroringSessionObserver: mirroring.mojom.SessionObserver,
-    MirroringSessionObserverPtr: mirroring.mojom.SessionObserverPtr,
-    MirroringSessionParameters: mirroring.mojom.SessionParameters,
-    MirroringSessionType: mirroring.mojom.SessionType,
-    MirroringRemotingNamespace: mirroring.mojom.REMOTING_NAMESPACE,
-    MirroringWebRtcNamespace: mirroring.mojom.WEB_RTC_NAMESPACE,
-    RemotingStopReason: media.mojom.RemotingStopReason,
-    RemotingStartFailReason: media.mojom.RemotingStartFailReason,
-    RemotingSinkFeature: media.mojom.RemotingSinkFeature,
-    RemotingSinkAudioCapability:
-        media.mojom.RemotingSinkAudioCapability,
-    RemotingSinkVideoCapability:
-        media.mojom.RemotingSinkVideoCapability,
-    RemotingSinkMetadata: RemotingSinkMetadataAdapter,
-    RouteControllerType: mediaRouter.mojom.RouteControllerType,
-    Origin: url.mojom.Origin,
-    Sink: MediaSinkAdapter,
-    SinkExtraData: MediaSinkExtraDataAdapter,
-    TimeDelta: mojoBase.mojom.TimeDelta,
-    Url: url.mojom.Url,
-    interfaceControl: mojo.interfaceControl,
-    makeRequest: mojo.makeRequest,
-  };
-};
-
-/**
- * Registers the Media Router Provider Manager with the Media Router.
- * @return {!Promise<Object>} Instance ID and config for the Media Router.
- */
-MediaRouter.prototype.start = function() {
-  return this.service_.registerMediaRouteProvider(
-      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
-      this.mediaRouteProviderBinding_.createInterfacePtrAndBind()).then(
-          function(response) {
-            return {
-              'instance_id': response.instanceId,
-              'config': {
-                'enable_dial_discovery': response.config.enableDialDiscovery,
-                'enable_cast_discovery': response.config.enableCastDiscovery,
-                'enable_dial_sink_query': response.config.enableDialSinkQuery,
-                'enable_cast_sink_query': response.config.enableCastSinkQuery,
-                'use_mirroring_service': response.config.useMirroringService,
-              }
-            };
-          });
-}
-
-/**
- * Sets the service delegate methods.
- * @param {Object} handlers
- */
-MediaRouter.prototype.setHandlers = function(handlers) {
-  this.mrpm_.setHandlers(handlers);
-}
-
-/**
- * The keep alive status.
- * @return {boolean}
- */
-MediaRouter.prototype.getKeepAlive = function() {
-  return this.keepAlive_ != null;
-};
-
-/**
- * Called by the provider manager when a sink list for a given source is
- * updated.
- * @param {!string} sourceUrn
- * @param {!Array<!MediaSink>} sinks
- * @param {!Array<string|!url.mojom.Origin>} origins
- */
-MediaRouter.prototype.onSinksReceived = function(sourceUrn, sinks, origins) {
-  // |origins| is a string array if the Media Router component extension version
-  // is 59 or older. Without the stringToMojoOrigin_() conversion, clients using
-  // those extension versions would see a crash shown in
-  // https://crbug.com/787427.
-  this.service_.onSinksReceived(
-      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, sourceUrn,
-      sinks.map(sinkToMojo_), origins.map(stringToMojoOrigin_));
-};
-
-/**
- * Called by the provider manager to keep the extension from suspending
- * if it enters a state where suspension is undesirable (e.g. there is an
- * active MediaRoute.)
- * If keepAlive is true, the extension is kept alive.
- * If keepAlive is false, the extension is allowed to suspend.
- * @param {boolean} keepAlive
- */
-MediaRouter.prototype.setKeepAlive = function(keepAlive) {
-  if (keepAlive === false && this.keepAlive_) {
-    this.keepAlive_.ptr.reset();
-    this.keepAlive_ = null;
-  } else if (keepAlive === true && !this.keepAlive_) {
-    this.keepAlive_ = new extensions.KeepAlivePtr;
-    Mojo.bindInterface(
-        extensions.KeepAlive.name, mojo.makeRequest(this.keepAlive_).handle);
-  }
-};
-
-/**
- * Called by the provider manager to send an issue from a media route
- * provider to the Media Router, to show the user.
- * @param {!Object} issue The issue object.
- */
-MediaRouter.prototype.onIssue = function(issue) {
-  function issueSeverityToMojo_(severity) {
-    switch (severity) {
-      case 'fatal':
-        return mediaRouter.mojom.Issue.Severity.FATAL;
-      case 'warning':
-        return mediaRouter.mojom.Issue.Severity.WARNING;
-      case 'notification':
-        return mediaRouter.mojom.Issue.Severity.NOTIFICATION;
-      default:
-        console.error('Unknown issue severity: ' + severity);
-        return mediaRouter.mojom.Issue.Severity.NOTIFICATION;
-    }
-  }
-
-  function issueActionToMojo_(action) {
-    switch (action) {
-      case 'dismiss':
-        return mediaRouter.mojom.Issue.ActionType.DISMISS;
-      case 'learn_more':
-        return mediaRouter.mojom.Issue.ActionType.LEARN_MORE;
-      default:
-        console.error('Unknown issue action type : ' + action);
-        return mediaRouter.mojom.Issue.ActionType.OK;
-    }
-  }
-
-  var secondaryActions = (issue.secondaryActions || []).map(issueActionToMojo_);
-  this.service_.onIssue(new mediaRouter.mojom.Issue({
-    'routeId': issue.routeId || '',
-    'severity': issueSeverityToMojo_(issue.severity),
-    'title': issue.title,
-    'message': issue.message || '',
-    'defaultAction': issueActionToMojo_(issue.defaultAction),
-    'secondaryActions': secondaryActions,
-    'helpPageId': issue.helpPageId,
-    'isBlocking': issue.isBlocking,
-    'sinkId': issue.sinkId || ''
-  }));
-};
-
-/**
- * Called by the provider manager when the set of active routes
- * has been updated.
- * @param {!Array<MediaRoute>} routes The active set of media routes.
- * @param {string=} sourceUrn The sourceUrn associated with this route
- *     query.
- * @param {Array<string>=} joinableRouteIds The active set of joinable
- *     media routes.
- */
-MediaRouter.prototype.onRoutesUpdated = function(
-    routes, sourceUrn = '', joinableRouteIds = []) {
-  this.service_.onRoutesUpdated(
-      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION,
-      routes.map(routeToMojo_), sourceUrn, joinableRouteIds);
-};
-
-/**
- * Called by the provider manager when sink availability has been updated.
- * @param {!mediaRouter.mojom.MediaRouter.SinkAvailability} availability
- *     The new sink availability.
- */
-MediaRouter.prototype.onSinkAvailabilityUpdated = function(availability) {
-  this.service_.onSinkAvailabilityUpdated(
-      mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, availability);
-};
-
-/**
- * Called by the provider manager when the state of a presentation connected
- * to a route has changed.
- * @param {string} routeId
- * @param {string} state
- */
-MediaRouter.prototype.onPresentationConnectionStateChanged =
-    function(routeId, state) {
-  this.service_.onPresentationConnectionStateChanged(
-      routeId, presentationConnectionStateToMojo_(state));
-};
-
-/**
- * Called by the provider manager when the state of a presentation connected
- * to a route has closed.
- * @param {string} routeId
- * @param {string} reason
- * @param {string} message
- */
-MediaRouter.prototype.onPresentationConnectionClosed =
-    function(routeId, reason, message) {
-  this.service_.onPresentationConnectionClosed(
-      routeId, presentationConnectionCloseReasonToMojo_(reason), message);
-};
-
-/**
- * @param {string} routeId
- * @param {!Array<!RouteMessage>} mesages
- */
-MediaRouter.prototype.onRouteMessagesReceived = function(routeId, messages) {
-  this.service_.onRouteMessagesReceived(
-      routeId, messages.map(messageToMojo_));
-};
-
-/**
- * Returns current status of media sink service in JSON format.
- * @return {!Promise<!{status: string}>}
- */
-MediaRouter.prototype.getMediaSinkServiceStatus = function() {
-  return this.service_.getMediaSinkServiceStatus();
-}
-
-/**
- * @return {!Promise<!{status: string}>}
- */
-MediaRouter.prototype.getLogsAsString = function() {
-  return this.service_.getLogsAsString();
-}
-
-/**
- * @param {int32} target_tab_id
- * @param {!mojo.InterfaceRequest} request
- */
-MediaRouter.prototype.getMirroringServiceHostForTab = function(
-    target_tab_id, request) {
-  this.service_.getMirroringServiceHostForTab(target_tab_id, request);
-}
-
-/**
- * @param {int32} initiator_tab_id
- * @param {!string} desktop_stream_id
- * @param {!mojo.InterfaceRequest} request
- */
-MediaRouter.prototype.getMirroringServiceHostForDesktop = function(
-    initiator_tab_id, desktop_stream_id, request) {
-  this.service_.getMirroringServiceHostForDesktop(initiator_tab_id,
-      desktop_stream_id, request);
-}
-
-/**
- * @param {!url.mojom.Url} presentation_url
- * @param {!string} presentation_id
- * @param {!mojo.InterfaceRequest} request
- */
-MediaRouter.prototype.getMirroringServiceHostForOffscreenTab = function(
-    presentation_url, presentation_id, request) {
-  this.service_.getMirroringServiceHostForOffscreenTab(presentation_url,
-      presentation_id, request);
-}
-
-/**
- * Object containing callbacks set by the provider manager.
- *
- * @constructor
- * @struct
- */
-function MediaRouterHandlers() {
-  /**
-   * @type {function(!string, !string, !string, !string, !number)}
-   */
-  this.createRoute = null;
-
-  /**
-   * @type {function(!string, !string, !string, !number)}
-   */
-  this.joinRoute = null;
-
-  /**
-   * @type {function(string): Promise}
-   */
-  this.terminateRoute = null;
-
-  /**
-   * @type {function(string)}
-   */
-  this.startObservingMediaSinks = null;
-
-  /**
-   * @type {function(string)}
-   */
-  this.stopObservingMediaSinks = null;
-
-  /**
-   * @type {function(string, string): Promise}
-   */
-  this.sendRouteMessage = null;
-
-  /**
-   * @type {function(string, Uint8Array): Promise}
-   */
-  this.sendRouteBinaryMessage = null;
-
-  /**
-   * @type {function(string)}
-   */
-  this.startListeningForRouteMessages = null;
-
-  /**
-   * @type {function(string)}
-   */
-  this.stopListeningForRouteMessages = null;
-
-  /**
-   * @type {function(string)}
-   */
-  this.detachRoute = null;
-
-  /**
-   * @type {function()}
-   */
-  this.startObservingMediaRoutes = null;
-
-  /**
-   * @type {function()}
-   */
-  this.stopObservingMediaRoutes = null;
-
-  /**
-   * @type {function()}
-   */
-  this.connectRouteByRouteId = null;
-
-  /**
-   * @type {function()}
-   */
-  this.enableMdnsDiscovery = null;
-
-  /**
-   * @type {function()}
-   */
-  this.updateMediaSinks = null;
-
-  /**
-   * @type {function(string, !mojo.InterfaceRequest,
-   *            !mediaRouter.mojom.MediaStatusObserverPtr): !Promise<void>}
-   */
-  this.createMediaRouteController = null;
-};
-
-/**
- * Routes calls from Media Router to the provider manager extension.
- * Registered with the MediaRouter stub.
- * @param {!MediaRouter} MediaRouter proxy to call into the
- * Media Router mojo interface.
- * @constructor
- */
-function MediaRouteProvider(mediaRouter) {
-  /**
-   * Object containing JS callbacks into Provider Manager code.
-   * @type {!MediaRouterHandlers}
-   */
-  this.handlers_ = new MediaRouterHandlers();
-
-  /**
-   * Proxy class to the browser's Media Router Mojo service.
-   * @type {!MediaRouter}
-   */
-  this.mediaRouter_ = mediaRouter;
-}
-
-/*
- * Sets the callback handler used to invoke methods in the provider manager.
- *
- * @param {!MediaRouterHandlers} handlers
- */
-MediaRouteProvider.prototype.setHandlers = function(handlers) {
-  this.handlers_ = handlers;
-  var requiredHandlers = [
-    'stopObservingMediaRoutes',
-    'startObservingMediaRoutes',
-    'sendRouteMessage',
-    'sendRouteBinaryMessage',
-    'startListeningForRouteMessages',
-    'stopListeningForRouteMessages',
-    'detachRoute',
-    'terminateRoute',
-    'joinRoute',
-    'createRoute',
-    'stopObservingMediaSinks',
-    'startObservingMediaRoutes',
-    'connectRouteByRouteId',
-    'enableMdnsDiscovery',
-    'updateMediaSinks',
-    'createMediaRouteController',
-    'onBeforeInvokeHandler'
-  ];
-  requiredHandlers.forEach(function(nextHandler) {
-    if (handlers[nextHandler] === undefined) {
-      console.error(nextHandler + ' handler not registered.');
-    }
-  });
-}
-
-/**
- * Starts querying for sinks capable of displaying the media source
- * designated by |sourceUrn|.  Results are returned by calling
- * OnSinksReceived.
- * @param {!string} sourceUrn
- */
-MediaRouteProvider.prototype.startObservingMediaSinks =
-    function(sourceUrn) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.startObservingMediaSinks(sourceUrn);
-};
-
-/**
- * Stops querying for sinks capable of displaying |sourceUrn|.
- * @param {!string} sourceUrn
- */
-MediaRouteProvider.prototype.stopObservingMediaSinks =
-    function(sourceUrn) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.stopObservingMediaSinks(sourceUrn);
-};
-
-/**
- * Requests that |sinkId| render the media referenced by |sourceUrn|. If the
- * request is from the Presentation API, then origin and tabId will
- * be populated.
- * @param {!string} sourceUrn Media source to render.
- * @param {!string} sinkId Media sink ID.
- * @param {!string} presentationId Presentation ID from the site
- *     requesting presentation. TODO(mfoltz): Remove.
- * @param {!url.mojom.Origin} origin Origin of site requesting presentation.
- * @param {!number} tabId ID of tab requesting presentation.
- * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
- *     duration for the request. Otherwise, the default duration will be used.
- * @param {!boolean} off_the_record If true, the route is being requested by
- *     an off_the_record profile.
- * @return {!Promise.<!Object>} A Promise resolving to an object describing
- *     the newly created media route, or rejecting with an error message on
- *     failure.
- */
-MediaRouteProvider.prototype.createRoute =
-    function(sourceUrn, sinkId, presentationId, origin, tabId,
-             timeout, off_the_record) {
-  this.handlers_.onBeforeInvokeHandler();
-  return this.handlers_.createRoute(
-      sourceUrn, sinkId, presentationId, origin, tabId,
-      Math.floor(timeout.microseconds / 1000), off_the_record)
-      .then(function(route) {
-        return toSuccessRouteResponse_(route);
-      },
-      function(err) {
-        return toErrorRouteResponse_(err);
-      });
-};
-
-/**
- * Handles a request via the Presentation API to join an existing route given
- * by |sourceUrn| and |presentationId|. |origin| and |tabId| are used for
- * validating same-origin/tab scope.
- * @param {!string} sourceUrn Media source to render.
- * @param {!string} presentationId Presentation ID to join.
- * @param {!url.mojom.Origin} origin Origin of site requesting join.
- * @param {!number} tabId ID of tab requesting join.
- * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
- *     duration for the request. Otherwise, the default duration will be used.
- * @param {!boolean} off_the_record If true, the route is being requested by
- *     an off_the_record profile.
- * @return {!Promise.<!Object>} A Promise resolving to an object describing
- *     the newly created media route, or rejecting with an error message on
- *     failure.
- */
-MediaRouteProvider.prototype.joinRoute =
-    function(sourceUrn, presentationId, origin, tabId, timeout,
-             off_the_record) {
-  this.handlers_.onBeforeInvokeHandler();
-  return this.handlers_.joinRoute(
-      sourceUrn, presentationId, origin, tabId,
-      Math.floor(timeout.microseconds / 1000), off_the_record)
-      .then(function(route) {
-        return toSuccessRouteResponse_(route);
-      },
-      function(err) {
-        return toErrorRouteResponse_(err);
-      });
-};
-
-/**
- * Handles a request via the Presentation API to join an existing route given
- * by |sourceUrn| and |routeId|. |origin| and |tabId| are used for
- * validating same-origin/tab scope.
- * @param {!string} sourceUrn Media source to render.
- * @param {!string} routeId Route ID to join.
- * @param {!string} presentationId Presentation ID to join.
- * @param {!url.mojom.Origin} origin Origin of site requesting join.
- * @param {!number} tabId ID of tab requesting join.
- * @param {!mojo_base.mojom.TimeDelta} timeout If positive, the timeout
- *     duration for the request. Otherwise, the default duration will be used.
- * @param {!boolean} off_the_record If true, the route is being requested by
- *     an off_the_record profile.
- * @return {!Promise.<!Object>} A Promise resolving to an object describing
- *     the newly created media route, or rejecting with an error message on
- *     failure.
- */
-MediaRouteProvider.prototype.connectRouteByRouteId =
-    function(sourceUrn, routeId, presentationId, origin, tabId,
-             timeout, off_the_record) {
-  this.handlers_.onBeforeInvokeHandler();
-  return this.handlers_.connectRouteByRouteId(
-      sourceUrn, routeId, presentationId, origin, tabId,
-      Math.floor(timeout.microseconds / 1000), off_the_record)
-      .then(function(route) {
-        return toSuccessRouteResponse_(route);
-      },
-      function(err) {
-        return toErrorRouteResponse_(err);
-      });
-};
-
-/**
- * Terminates the route specified by |routeId|.
- * @param {!string} routeId
- * @return {!Promise<!Object>} A Promise resolving to an object describing
- *    the result of the terminate operation, or rejecting with an error
- *    message and code if the operation failed.
- */
-MediaRouteProvider.prototype.terminateRoute = function(routeId) {
-  this.handlers_.onBeforeInvokeHandler();
-  return this.handlers_.terminateRoute(routeId).then(
-      () => ({resultCode: mediaRouter.mojom.RouteRequestResultCode.OK}),
-      (err) => toErrorRouteResponse_(err));
-};
-
-/**
- * Posts a message to the route designated by |routeId|.
- * @param {!string} routeId
- * @param {!string} message
- */
-MediaRouteProvider.prototype.sendRouteMessage = function(
-  routeId, message) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.sendRouteMessage(routeId, message);
-};
-
-/**
- * Sends a binary message to the route designated by |routeId|.
- * @param {!string} routeId
- * @param {!Array<number>} data
- */
-MediaRouteProvider.prototype.sendRouteBinaryMessage = function(
-  routeId, data) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data));
-};
-
-/**
- * Listen for messages from a route.
- * @param {!string} routeId
- */
-MediaRouteProvider.prototype.startListeningForRouteMessages = function(
-    routeId) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.startListeningForRouteMessages(routeId);
-};
-
-/**
- * @param {!string} routeId
- */
-MediaRouteProvider.prototype.stopListeningForRouteMessages = function(
-    routeId) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.stopListeningForRouteMessages(routeId);
-};
-
-/**
- * Indicates that the presentation connection that was connected to |routeId|
- * is no longer connected to it.
- * @param {!string} routeId
- */
-MediaRouteProvider.prototype.detachRoute = function(
-    routeId) {
-  this.handlers_.detachRoute(routeId);
-};
-
-/**
- * Requests that the provider manager start sending information about active
- * media routes to the Media Router.
- * @param {!string} sourceUrn
- */
-MediaRouteProvider.prototype.startObservingMediaRoutes = function(sourceUrn) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.startObservingMediaRoutes(sourceUrn);
-};
-
-/**
- * Requests that the provider manager stop sending information about active
- * media routes to the Media Router.
- * @param {!string} sourceUrn
- */
-MediaRouteProvider.prototype.stopObservingMediaRoutes = function(sourceUrn) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.stopObservingMediaRoutes(sourceUrn);
-};
-
-/**
- * Enables mDNS device discovery.
- */
-MediaRouteProvider.prototype.enableMdnsDiscovery = function() {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.enableMdnsDiscovery();
-};
-
-/**
- * Requests that the provider manager update media sinks.
- * @param {!string} sourceUrn
- */
-MediaRouteProvider.prototype.updateMediaSinks = function(sourceUrn) {
-  this.handlers_.onBeforeInvokeHandler();
-  this.handlers_.updateMediaSinks(sourceUrn);
-};
-
-/**
- * Creates a controller for the given route and binds the given
- * InterfaceRequest to it, and registers an observer for media status updates
- * for the route.
- * @param {string} routeId
- * @param {!mojo.InterfaceRequest} controllerRequest
- * @param {!mediaRouter.mojom.MediaStatusObserverPtr} observer
- * @return {!Promise<!{success: boolean}>} Resolves to true if a controller
- *     is created. Resolves to false if a controller cannot be created, or if
- *     the controller is already bound.
- */
-MediaRouteProvider.prototype.createMediaRouteController = function(
-    routeId, controllerRequest, observer) {
-  this.handlers_.onBeforeInvokeHandler();
-  return this.handlers_.createMediaRouteController(
-      routeId, controllerRequest,
-      new MediaStatusObserverPtrAdapter(observer.ptr.passInterface())).then(
-          () => ({success: true}), e => ({success: false}));
-};
-
-var ptr = new mediaRouter.mojom.MediaRouterPtr;
-Mojo.bindInterface(
-    mediaRouter.mojom.MediaRouter.name, mojo.makeRequest(ptr).handle);
-exports.$set('returnValue', new MediaRouter(ptr));
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index 1f625c8..81fb416 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -79,23 +79,6 @@
           <include name="IDR_GOOGLE_TTS_STREAM_BINDINGS_JS" file="extensions\chromeos_google_tts_stream_bindings.js" type="BINDATA" />
           <include name="IDR_GOOGLE_TTS_STREAM_MOJOM_JS" file="${mojom_root}\chromeos\services\tts\public\mojom\tts_service.mojom.js" use_base_dir="false" type="BINDATA" />
         </if>
-        <!-- Media Router Mojo service and bindings. -->
-        <include name="IDR_MEDIA_CONTROLLER_MOJOM_JS" file="${mojom_root}\components\media_router\common\mojom\media_controller.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MEDIA_ROUTER_MOJOM_JS" file="${mojom_root}\components\media_router\common\mojom\media_router.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MEDIA_ROUTER_BINDINGS_JS" file="extensions\media_router_bindings.js" type="BINDATA" />
-        <include name="IDR_MEDIA_STATUS_MOJOM_JS" file="${mojom_root}\components\media_router\common\mojom\media_status.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MIRRORING_SERVICE_HOST_MOJOM_JS" file="${mojom_root}\components\mirroring\mojom\mirroring_service_host.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MIRRORING_CAST_MESSAGE_CHANNEL_MOJOM_JS" file="${mojom_root}\components\mirroring\mojom\cast_message_channel.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MIRRORING_SESSION_OBSERVER_MOJOM_JS" file="${mojom_root}\components\mirroring\mojom\session_observer.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MIRRORING_SESSION_PARAMETERS_JS" file="${mojom_root}\components\mirroring\mojom\session_parameters.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_TIME_MOJOM_JS" file="${mojom_root}\mojo\public\mojom\base\time.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_UNGUESSABLE_TOKEN_MOJOM_JS" file="${mojom_root}\mojo\public\mojom\base\unguessable_token.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_IP_ADDRESS_MOJOM_JS" file="${mojom_root}\services\network\public\mojom\ip_address.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_IP_ENDPOINT_MOJOM_JS" file="${mojom_root}\services\network\public\mojom\ip_endpoint.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_ORIGIN_MOJOM_JS" file="${mojom_root}\url\mojom\origin.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_MOJO_URL_MOJOM_JS" file="${mojom_root}\url\mojom\url.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_REMOTING_COMMON_JS" file="${mojom_root}\media\mojo\mojom\remoting_common.mojom.js" use_base_dir="false" type="BINDATA" />
-        <include name="IDR_PRESENTATION_JS" file="${mojom_root}\third_party\blink\public\mojom\presentation\presentation.mojom.js" use_base_dir="false" type="BINDATA" />
       </if>
     </includes>
   </release>
diff --git a/chrome/services/printing/BUILD.gn b/chrome/services/printing/BUILD.gn
index bf979ae..d8b4d5d1 100644
--- a/chrome/services/printing/BUILD.gn
+++ b/chrome/services/printing/BUILD.gn
@@ -78,7 +78,10 @@
       "//mojo/public/cpp/bindings",
     ]
 
-    deps += [ "//chrome/common/printing" ]
+    deps += [
+      "//chrome/common/printing",
+      "//components/crash/core/common",
+    ]
   }
 }
 
diff --git a/chrome/services/printing/DEPS b/chrome/services/printing/DEPS
index 6d3ada73..c62b45f 100644
--- a/chrome/services/printing/DEPS
+++ b/chrome/services/printing/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+components/crash/core/common/crash_key.h",
+  "+components/crash/core/common/crash_keys.h",
   "+components/pwg_encoder",
   "+pdf/pdf.h",
 ]
diff --git a/chrome/services/printing/print_backend_service_impl.cc b/chrome/services/printing/print_backend_service_impl.cc
index d2a85b9..b827c6e 100644
--- a/chrome/services/printing/print_backend_service_impl.cc
+++ b/chrome/services/printing/print_backend_service_impl.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/services/printing/print_backend_service_impl.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -11,6 +12,7 @@
 #include "base/notreached.h"
 #include "build/build_config.h"
 #include "chrome/services/printing/public/mojom/print_backend_service.mojom.h"
+#include "components/crash/core/common/crash_keys.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "printing/backend/print_backend.h"
 #include "printing/mojom/print.mojom.h"
@@ -86,6 +88,9 @@
     return;
   }
 
+  crash_keys_ = std::make_unique<crash_keys::ScopedPrinterInfo>(
+      print_backend_->GetPrinterDriverInfo(printer_name));
+
   PrinterSemanticCapsAndDefaults printer_caps;
   const mojom::ResultCode result =
       print_backend_->GetPrinterSemanticCapsAndDefaults(printer_name,
@@ -111,6 +116,9 @@
     return;
   }
 
+  crash_keys_ = std::make_unique<crash_keys::ScopedPrinterInfo>(
+      print_backend_->GetPrinterDriverInfo(printer_name));
+
   PrinterSemanticCapsAndDefaults::Papers user_defined_papers;
 #if defined(OS_MAC)
   {
diff --git a/chrome/services/printing/print_backend_service_impl.h b/chrome/services/printing/print_backend_service_impl.h
index b62d98bc..4332469 100644
--- a/chrome/services/printing/print_backend_service_impl.h
+++ b/chrome/services/printing/print_backend_service_impl.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_SERVICES_PRINTING_PRINT_BACKEND_SERVICE_IMPL_H_
 #define CHROME_SERVICES_PRINTING_PRINT_BACKEND_SERVICE_IMPL_H_
 
+#include <memory>
 #include <string>
 
 #include "base/callback.h"
@@ -15,6 +16,10 @@
 #include "printing/backend/print_backend.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace crash_keys {
+class ScopedPrinterInfo;
+}
+
 namespace printing {
 
 class PrintBackendServiceImpl : public mojom::PrintBackendService {
@@ -43,6 +48,11 @@
       const std::string& printer_name,
       mojom::PrintBackendService::FetchCapabilitiesCallback callback) override;
 
+  // Crash key is kept at class level so that we can obtain printer driver
+  // information for a prior call should the process be terminated by the
+  // remote.  This can happen in the case of Mojo message validation.
+  std::unique_ptr<crash_keys::ScopedPrinterInfo> crash_keys_;
+
   scoped_refptr<PrintBackend> print_backend_;
 
   mojo::Receiver<mojom::PrintBackendService> receiver_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8aee0e34..8c4d79c 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3379,6 +3379,7 @@
         "../browser/ui/ash/chrome_new_window_client_browsertest.cc",
         "../browser/ui/ash/chrome_screenshot_grabber_browsertest.cc",
         "../browser/ui/ash/clipboard_history_browsertest.cc",
+        "../browser/ui/ash/desks_client_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_controller_browsertest.cc",
         "../browser/ui/ash/keyboard/keyboard_end_to_end_browsertest.cc",
         "../browser/ui/ash/multi_user/test_multi_user_window_manager.cc",
@@ -6571,7 +6572,6 @@
       "../common/extensions/permissions/permissions_data_unittest.cc",
       "../common/extensions/permissions/settings_override_permission_unittest.cc",
       "../common/extensions/sync_type_unittest.cc",
-      "../renderer/extensions/accessibility_private_hooks_delegate_unittest.cc",
       "../renderer/extensions/chrome_native_extension_bindings_system_unittest.cc",
       "../renderer/extensions/custom_types_unittest.cc",
       "../renderer/extensions/extension_hooks_delegate_unittest.cc",
@@ -6597,6 +6597,7 @@
         "../browser/extensions/external_provider_impl_chromeos_unittest.cc",
         "../browser/extensions/system_display/display_info_provider_chromeos_unittest.cc",
         "../browser/extensions/system_display/system_display_serialization_unittest.cc",
+        "../renderer/extensions/accessibility_private_hooks_delegate_unittest.cc",
       ]
     }
 
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index ae4a2e1..4a7b67a 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -280,6 +280,7 @@
     "//chrome/browser/ui/android/favicon:java",
     "//chrome/browser/ui/android/layouts:java",
     "//chrome/browser/ui/android/layouts/third_party/float_property:java",
+    "//chrome/browser/ui/android/omnibox:java",
     "//chrome/browser/ui/android/theme:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
index 68f4a4b..cde1fc2 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/browser/tab/TabTestUtils.java
@@ -14,6 +14,8 @@
 import org.chromium.content_public.common.ResourceRequestBody;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /**
  * Exposes helper functions to be used in tests to instrument tab interaction.
  */
@@ -170,4 +172,29 @@
     public static void setIsShowingErrorPage(Tab tab, boolean isShowingErrorPage) {
         ((TabImpl) tab).setIsShowingErrorPage(isShowingErrorPage);
     }
+
+    /**
+     * Acquire copy of byte array from a ByteBuffer.
+     * @param buffer {@link ByteBuffer} copy of backing byte array will be acquired from.
+     */
+    public static byte[] toByteArray(ByteBuffer buffer) {
+        if (buffer == null) {
+            return null;
+        }
+        if (buffer.hasArray() && buffer.arrayOffset() == 0) {
+            return buffer.array();
+        }
+        byte[] bytes = new byte[buffer.limit()];
+        buffer.rewind();
+        buffer.get(bytes);
+        return bytes;
+    }
+
+    /**
+     * Create ByteBuffer backed by a byte array.
+     * @param bytes byte array to create ByteBuffer from.
+     */
+    public static ByteBuffer toByteBuffer(byte[] bytes) {
+        return ByteBuffer.wrap(bytes);
+    }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabCreator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabCreator.java
index a0d817f..5d2edad4 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabCreator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabCreator.java
@@ -22,6 +22,8 @@
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.url.GURL;
 
+import java.nio.ByteBuffer;
+
 /** MockTabCreator for use in tests. */
 public class MockTabCreator extends TabCreator {
     public final SparseArray<TabState> created;
@@ -58,7 +60,7 @@
     }
 
     @Override
-    public Tab createFrozenTab(TabState state, byte[] criticalPersistedTabData, int id,
+    public Tab createFrozenTab(TabState state, ByteBuffer criticalPersistedTabData, int id,
             boolean isIncognito, int index) {
         Tab tab = new MockTab(id, state.isIncognito(), TabLaunchType.FROM_RESTORE);
         tab.getUserDataHost().setUserData(MockTabAttributes.class, new MockTabAttributes(true));
diff --git a/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java b/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
index 17d2d24..6a8c3b8 100644
--- a/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
+++ b/chrome/test/android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java
@@ -114,6 +114,7 @@
         private final long mOnHasEnrolledInstrumentReturnedPtr;
         private final long mOnAppListReadyPtr;
         private final long mSetAppDescriptionsPtr;
+        private final long mOnErrorDisplayedPtr;
         private final long mOnNotSupportedErrorPtr;
         private final long mOnConnectionTerminatedPtr;
         private final long mOnAbortCalledPtr;
@@ -123,7 +124,7 @@
         PaymentRequestNativeObserverBridgeToNativeForTest(long onCanMakePaymentCalledPtr,
                 long onCanMakePaymentReturnedPtr, long onHasEnrolledInstrumentCalledPtr,
                 long onHasEnrolledInstrumentReturnedPtr, long onAppListReadyPtr,
-                long setAppDescriptionPtr, long onNotSupportedErrorPtr,
+                long setAppDescriptionPtr, long onErrorDisplayedPtr, long onNotSupportedErrorPtr,
                 long onConnectionTerminatedPtr, long onAbortCalledPtr, long onCompleteHandledPtr,
                 long onMinimalUIReadyPtr) {
             mOnCanMakePaymentCalledPtr = onCanMakePaymentCalledPtr;
@@ -132,6 +133,7 @@
             mOnHasEnrolledInstrumentReturnedPtr = onHasEnrolledInstrumentReturnedPtr;
             mOnAppListReadyPtr = onAppListReadyPtr;
             mSetAppDescriptionsPtr = setAppDescriptionPtr;
+            mOnErrorDisplayedPtr = onErrorDisplayedPtr;
             mOnNotSupportedErrorPtr = onNotSupportedErrorPtr;
             mOnConnectionTerminatedPtr = onConnectionTerminatedPtr;
             mOnAbortCalledPtr = onAbortCalledPtr;
@@ -188,6 +190,11 @@
             nativeResolvePaymentRequestObserverCallback(mOnAppListReadyPtr);
         }
 
+        @Override
+        public void onErrorDisplayed() {
+            nativeResolvePaymentRequestObserverCallback(mOnErrorDisplayedPtr);
+        }
+
         private static String ensureNotNull(@Nullable String value) {
             return value == null ? "" : value;
         }
@@ -233,14 +240,15 @@
     private static void setUseNativeObserverForTest(long onCanMakePaymentCalledPtr,
             long onCanMakePaymentReturnedPtr, long onHasEnrolledInstrumentCalledPtr,
             long onHasEnrolledInstrumentReturnedPtr, long onAppListReadyPtr,
-            long setAppDescriptionPtr, long onNotSupportedErrorPtr, long onConnectionTerminatedPtr,
-            long onAbortCalledPtr, long onCompleteCalledPtr, long onMinimalUIReadyPtr) {
+            long setAppDescriptionPtr, long onErrorDisplayedPtr, long onNotSupportedErrorPtr,
+            long onConnectionTerminatedPtr, long onAbortCalledPtr, long onCompleteCalledPtr,
+            long onMinimalUIReadyPtr) {
         PaymentRequestService.setNativeObserverForTest(
                 new PaymentRequestNativeObserverBridgeToNativeForTest(onCanMakePaymentCalledPtr,
                         onCanMakePaymentReturnedPtr, onHasEnrolledInstrumentCalledPtr,
                         onHasEnrolledInstrumentReturnedPtr, onAppListReadyPtr, setAppDescriptionPtr,
-                        onNotSupportedErrorPtr, onConnectionTerminatedPtr, onAbortCalledPtr,
-                        onCompleteCalledPtr, onMinimalUIReadyPtr));
+                        onErrorDisplayedPtr, onNotSupportedErrorPtr, onConnectionTerminatedPtr,
+                        onAbortCalledPtr, onCompleteCalledPtr, onMinimalUIReadyPtr));
     }
 
     @CalledByNative
@@ -259,6 +267,11 @@
     }
 
     @CalledByNative
+    private static boolean closeDialogForTest() {
+        return sUiService == null || sUiService.closeDialogForTest();
+    }
+
+    @CalledByNative
     private static boolean confirmMinimalUIForTest() {
         return sUiService.confirmMinimalUIForTest();
     }
diff --git a/chrome/test/data/media/picture-in-picture/pixel_expected_pause_control.png b/chrome/test/data/media/picture-in-picture/pixel_expected_pause_control.png
index 45f3e44..d6cae8e 100644
--- a/chrome/test/data/media/picture-in-picture/pixel_expected_pause_control.png
+++ b/chrome/test/data/media/picture-in-picture/pixel_expected_pause_control.png
Binary files differ
diff --git a/chrome/test/data/media/picture-in-picture/pixel_expected_play_control.png b/chrome/test/data/media/picture-in-picture/pixel_expected_play_control.png
index 45a6e1c4..93da40a 100644
--- a/chrome/test/data/media/picture-in-picture/pixel_expected_play_control.png
+++ b/chrome/test/data/media/picture-in-picture/pixel_expected_play_control.png
Binary files differ
diff --git a/chrome/test/data/webui/tab_search/tab_search_app_test.js b/chrome/test/data/webui/tab_search/tab_search_app_test.js
index e1e5d2e..1d32dc18 100644
--- a/chrome/test/data/webui/tab_search/tab_search_app_test.js
+++ b/chrome/test/data/webui/tab_search/tab_search_app_test.js
@@ -42,6 +42,8 @@
    * @param {Object=} loadTimeOverriddenData
    */
   async function setupTest(sampleData, loadTimeOverriddenData) {
+    // TODO(romanarora): Leverage ProfileDataSpec to initialize undefined
+    // array fields in sampleData to empty arrays.
     testProxy = new TestTabSearchApiProxy();
     testProxy.setProfileData(sampleData);
     TabSearchApiProxyImpl.instance_ = testProxy;
@@ -66,6 +68,7 @@
       windows: SAMPLE_WINDOW_DATA,
       recentlyClosedTabs: SAMPLE_RECENTLY_CLOSED_DATA,
       tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
     tabSearchApp.shadowRoot.querySelector('#tabsList')
         .ensureAllDomItemsAvailable();
@@ -84,6 +87,7 @@
           recentlyClosedTabs: generateSampleTabsFromSiteNames(
               ['RecentlyClosedTab1', 'RecentlyClosedTab2'], false),
           tabGroups: [],
+          recentlyClosedTabGroups: [],
         },
         {recentlyClosedDefaultItemDisplayCount: 1});
 
@@ -101,6 +105,7 @@
       windows: SAMPLE_WINDOW_DATA,
       recentlyClosedTabs: SAMPLE_RECENTLY_CLOSED_DATA,
       tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
     const searchField = /** @type {!TabSearchSearchField} */
         (tabSearchApp.shadowRoot.querySelector('#searchField'));
@@ -135,7 +140,8 @@
     await setupTest({
       windows: [{active: true, tabs: [tabData]}],
       recentlyClosedTabs: [],
-      tabGroups: []
+      tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
 
     const tabSearchItem = /** @type {!HTMLElement} */
@@ -177,13 +183,14 @@
       }],
       recentlyClosedTabs: [tabData],
       tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
 
     let tabSearchItem = /** @type {!HTMLElement} */
         (tabSearchApp.shadowRoot.querySelector('#tabsList')
              .querySelector('tab-search-item[id="100"]'));
     tabSearchItem.click();
-    const tabId = await testProxy.whenCalled('openRecentlyClosedTab');
+    const tabId = await testProxy.whenCalled('openRecentlyClosedEntry');
     assertEquals(tabData.tabId, tabId);
   });
 
@@ -191,7 +198,8 @@
     await setupTest({
       windows: [{active: true, tabs: []}],
       recentlyClosedTabs: [],
-      tabGroups: []
+      tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
 
     const searchField = /** @type {!TabSearchSearchField} */
@@ -274,8 +282,12 @@
   test('refresh on tabs changed', async () => {
     await setupTest(sampleData());
     verifyTabIds(queryRows(), [1, 5, 6, 2, 3, 4]);
-    testProxy.getCallbackRouterRemote().tabsChanged(
-        {windows: [], recentlyClosedTabs: [], tabGroups: []});
+    testProxy.getCallbackRouterRemote().tabsChanged({
+      windows: [],
+      recentlyClosedTabs: [],
+      tabGroups: [],
+      recentlyClosedTabGroups: []
+    });
     await flushTasks();
     verifyTabIds(queryRows(), []);
     assertEquals(-1, tabSearchApp.getSelectedIndex());
@@ -293,7 +305,8 @@
     testProxy.getCallbackRouterRemote().tabsChanged({
       windows: [testData.windows[0]],
       recentlyClosedTabs: [],
-      tabGroups: []
+      tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
     await flushTasks();
     assertEquals(1, tabSearchApp.getSelectedIndex());
@@ -302,6 +315,7 @@
       windows: [{active: true, tabs: [testData.windows[0].tabs[0]]}],
       recentlyClosedTabs: [],
       tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
     await flushTasks();
     assertEquals(0, tabSearchApp.getSelectedIndex());
@@ -511,6 +525,7 @@
       windows: [{active: true, height: SAMPLE_WINDOW_HEIGHT, tabs}],
       recentlyClosedTabs: [],
       tabGroups: [],
+      recentlyClosedTabGroups: [],
     });
     verifyTabIds(queryRows(), [3, 1, 2]);
 
@@ -519,6 +534,7 @@
           windows: [{active: true, height: SAMPLE_WINDOW_HEIGHT, tabs}],
           recentlyClosedTabs: [],
           tabGroups: [],
+          recentlyClosedTabGroups: [],
         },
         {'moveActiveTabToBottom': false});
     verifyTabIds(queryRows(), [2, 3, 1]);
@@ -564,6 +580,7 @@
       windows: [{active: true, height: SAMPLE_WINDOW_HEIGHT, tabs}],
       recentlyClosedTabs: [],
       tabGroups: [tabGroup],
+      recentlyClosedTabGroups: [],
     });
 
     let tabSearchItem = /** @type {!HTMLElement} */ (
diff --git a/chrome/test/data/webui/tab_search/tab_search_test_data.js b/chrome/test/data/webui/tab_search/tab_search_test_data.js
index a277789a..c5f525a9 100644
--- a/chrome/test/data/webui/tab_search/tab_search_test_data.js
+++ b/chrome/test/data/webui/tab_search/tab_search_test_data.js
@@ -91,7 +91,12 @@
 
 /** @return {!Array} */
 export function sampleData() {
-  return {windows: SAMPLE_WINDOW_DATA, recentlyClosedTabs: [], tabGroups: []};
+  return {
+    windows: SAMPLE_WINDOW_DATA,
+    recentlyClosedTabs: [],
+    tabGroups: [],
+    recentlyClosedTabGroups: [],
+  };
 }
 
 /**
@@ -140,6 +145,7 @@
     }],
     recentlyClosedTabs: [],
     tabGroups: [],
+    recentlyClosedTabGroups: [],
   };
 }
 
diff --git a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.js b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.js
index 604f11aa..2da5067 100644
--- a/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.js
+++ b/chrome/test/data/webui/tab_search/test_tab_search_api_proxy.js
@@ -12,7 +12,7 @@
     super([
       'closeTab',
       'getProfileData',
-      'openRecentlyClosedTab',
+      'openRecentlyClosedEntry',
       'switchToTab',
       'showUI',
       'closeUI',
@@ -41,8 +41,8 @@
   }
 
   /** @override */
-  openRecentlyClosedTab(tabId) {
-    this.methodCalled('openRecentlyClosedTab', tabId);
+  openRecentlyClosedEntry(id) {
+    this.methodCalled('openRecentlyClosedEntry', id);
   }
 
   /** @override */
diff --git a/chrome/test/payments/android/payment_request_test_bridge.cc b/chrome/test/payments/android/payment_request_test_bridge.cc
index a0d2f16..7a0e4bd 100644
--- a/chrome/test/payments/android/payment_request_test_bridge.cc
+++ b/chrome/test/payments/android/payment_request_test_bridge.cc
@@ -48,6 +48,11 @@
       env);
 }
 
+bool CloseDialogForTest() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  return Java_PaymentRequestTestBridge_closeDialogForTest(env);
+}
+
 bool ConfirmMinimalUIForTest() {
   return Java_PaymentRequestTestBridge_confirmMinimalUIForTest(
       base::android::AttachCurrentThread());
@@ -70,6 +75,7 @@
   base::RepeatingClosure on_has_enrolled_instrument_returned;
   base::RepeatingClosure on_show_instruments_ready;
   SetAppDescriptionsCallback set_app_descriptions;
+  base::RepeatingClosure on_error_displayed;
   base::RepeatingClosure on_not_supported_error;
   base::RepeatingClosure on_connection_terminated;
   base::RepeatingClosure on_abort_called;
@@ -89,6 +95,7 @@
     base::RepeatingClosure on_has_enrolled_instrument_returned,
     base::RepeatingClosure on_show_instruments_ready,
     SetAppDescriptionsCallback set_app_descriptions,
+    base::RepeatingClosure on_error_displayed,
     base::RepeatingClosure on_not_supported_error,
     base::RepeatingClosure on_connection_terminated,
     base::RepeatingClosure on_abort_called,
@@ -107,6 +114,7 @@
       std::move(on_has_enrolled_instrument_returned);
   callbacks.on_show_instruments_ready = std::move(on_show_instruments_ready);
   callbacks.set_app_descriptions = std::move(set_app_descriptions);
+  callbacks.on_error_displayed = std::move(on_error_displayed);
   callbacks.on_not_supported_error = std::move(on_not_supported_error);
   callbacks.on_connection_terminated = std::move(on_connection_terminated);
   callbacks.on_abort_called = std::move(on_abort_called);
@@ -120,6 +128,7 @@
       reinterpret_cast<jlong>(&callbacks.on_has_enrolled_instrument_returned),
       reinterpret_cast<jlong>(&callbacks.on_show_instruments_ready),
       reinterpret_cast<jlong>(&callbacks.set_app_descriptions),
+      reinterpret_cast<jlong>(&callbacks.on_error_displayed),
       reinterpret_cast<jlong>(&callbacks.on_not_supported_error),
       reinterpret_cast<jlong>(&callbacks.on_connection_terminated),
       reinterpret_cast<jlong>(&callbacks.on_abort_called),
diff --git a/chrome/test/payments/android/payment_request_test_bridge.h b/chrome/test/payments/android/payment_request_test_bridge.h
index 0d7cc86b..100b771 100644
--- a/chrome/test/payments/android/payment_request_test_bridge.h
+++ b/chrome/test/payments/android/payment_request_test_bridge.h
@@ -41,6 +41,9 @@
 // Click the close button on the Payment Handler UI. Returns true on success.
 bool ClickPaymentHandlerCloseButtonForTest();
 
+// Closes the payment dialog, if any. Returns true on success.
+bool CloseDialogForTest();
+
 // Confirms payment in minimal UI. Returns true on success.
 bool ConfirmMinimalUIForTest();
 
@@ -59,6 +62,7 @@
     base::RepeatingClosure on_has_enrolled_instrument_returned,
     base::RepeatingClosure on_show_instruments_ready,
     SetAppDescriptionsCallback set_app_descriptions,
+    base::RepeatingClosure on_error_displayed,
     base::RepeatingClosure on_not_supported_error,
     base::RepeatingClosure on_connection_terminated,
     base::RepeatingClosure on_abort_called,
diff --git a/chrome/test/payments/payment_request_platform_browsertest_base.cc b/chrome/test/payments/payment_request_platform_browsertest_base.cc
index 41ced3f..56274ed7 100644
--- a/chrome/test/payments/payment_request_platform_browsertest_base.cc
+++ b/chrome/test/payments/payment_request_platform_browsertest_base.cc
@@ -138,6 +138,10 @@
   if (event_waiter_)
     event_waiter_->OnEvent(TestEvent::kAppListReady);
 }
+void PaymentRequestPlatformBrowserTestBase::OnErrorDisplayed() {
+  if (event_waiter_)
+    event_waiter_->OnEvent(TestEvent::kErrorDisplayed);
+}
 void PaymentRequestPlatformBrowserTestBase::OnCompleteCalled() {
   if (event_waiter_)
     event_waiter_->OnEvent(TestEvent::kPaymentCompleted);
diff --git a/chrome/test/payments/payment_request_platform_browsertest_base.h b/chrome/test/payments/payment_request_platform_browsertest_base.h
index 8e49d57..a3de1698f 100644
--- a/chrome/test/payments/payment_request_platform_browsertest_base.h
+++ b/chrome/test/payments/payment_request_platform_browsertest_base.h
@@ -82,6 +82,7 @@
   void OnNotSupportedError() override;
   void OnAbortCalled() override;
   void OnAppListReady() override;
+  void OnErrorDisplayed() override;
   void OnCompleteCalled() override;
   void OnMinimalUIReady() override;
   void OnUIDisplayed() override;
diff --git a/chrome/test/payments/payment_request_test_controller.h b/chrome/test/payments/payment_request_test_controller.h
index 6888b926..2f77c78 100644
--- a/chrome/test/payments/payment_request_test_controller.h
+++ b/chrome/test/payments/payment_request_test_controller.h
@@ -41,6 +41,7 @@
   virtual void OnHasEnrolledInstrumentCalled() {}
   virtual void OnHasEnrolledInstrumentReturned() {}
   virtual void OnAppListReady() {}
+  virtual void OnErrorDisplayed() {}
   virtual void OnNotSupportedError() {}
   virtual void OnConnectionTerminated() {}
   virtual void OnAbortCalled() {}
@@ -89,6 +90,9 @@
   // Return whether it's succeeded.
   bool ClickPaymentHandlerCloseButton();
 
+  // Closes the dialog.
+  bool CloseDialog();
+
   // Confirms payment in a browser payment sheet, be it either PAYMENT_REQUEST
   // or SECURE_PAYMENT_CONFIRMATION type. Returns true if the dialog was
   // available.
@@ -123,6 +127,7 @@
   void OnHasEnrolledInstrumentCalled();
   void OnHasEnrolledInstrumentReturned();
   void OnAppListReady();
+  void OnErrorDisplayed();
   void OnNotSupportedError();
   void OnConnectionTerminated();
   void OnAbortCalled();
diff --git a/chrome/test/payments/payment_request_test_controller_android.cc b/chrome/test/payments/payment_request_test_controller_android.cc
index 3635981..7fe5165 100644
--- a/chrome/test/payments/payment_request_test_controller_android.cc
+++ b/chrome/test/payments/payment_request_test_controller_android.cc
@@ -28,6 +28,10 @@
   return ClickPaymentHandlerCloseButtonForTest();
 }
 
+bool PaymentRequestTestController::CloseDialog() {
+  return CloseDialogForTest();
+}
+
 bool PaymentRequestTestController::ConfirmPayment() {
   NOTIMPLEMENTED();
   return false;
@@ -66,6 +70,8 @@
                           base::Unretained(this)),
       base::BindRepeating(&PaymentRequestTestController::set_app_descriptions,
                           base::Unretained(this)),
+      base::BindRepeating(&PaymentRequestTestController::OnErrorDisplayed,
+                          base::Unretained(this)),
       base::BindRepeating(&PaymentRequestTestController::OnNotSupportedError,
                           base::Unretained(this)),
       base::BindRepeating(&PaymentRequestTestController::OnConnectionTerminated,
@@ -159,6 +165,10 @@
   if (observer_)
     observer_->OnAppListReady();
 }
+void PaymentRequestTestController::OnErrorDisplayed() {
+  if (observer_)
+    observer_->OnErrorDisplayed();
+}
 void PaymentRequestTestController::OnNotSupportedError() {
   if (observer_)
     observer_->OnNotSupportedError();
diff --git a/chrome/test/payments/payment_request_test_controller_desktop.cc b/chrome/test/payments/payment_request_test_controller_desktop.cc
index aaca9a04..d0770e83 100644
--- a/chrome/test/payments/payment_request_test_controller_desktop.cc
+++ b/chrome/test/payments/payment_request_test_controller_desktop.cc
@@ -137,6 +137,7 @@
 
     controller_->OnAppListReady();
   }
+  void OnErrorDisplayed() override { controller_->OnErrorDisplayed(); }
   void OnNotSupportedError() override { controller_->OnNotSupportedError(); }
   void OnConnectionTerminated() override {
     controller_->OnConnectionTerminated();
@@ -176,6 +177,10 @@
 }
 
 bool PaymentRequestTestController::ClickPaymentHandlerCloseButton() {
+  return CloseDialog();
+}
+
+bool PaymentRequestTestController::CloseDialog() {
   if (!delegate_)
     return false;
 
@@ -308,6 +313,11 @@
     observer_->OnAppListReady();
 }
 
+void PaymentRequestTestController::OnErrorDisplayed() {
+  if (observer_)
+    observer_->OnErrorDisplayed();
+}
+
 void PaymentRequestTestController::OnCompleteCalled() {
   if (observer_) {
     observer_->OnCompleteCalled();
diff --git a/chrome/test/payments/test_event_waiter.cc b/chrome/test/payments/test_event_waiter.cc
index c3de7609..20d1fe0c 100644
--- a/chrome/test/payments/test_event_waiter.cc
+++ b/chrome/test/payments/test_event_waiter.cc
@@ -34,6 +34,9 @@
     case TestEvent::kAppListReady:
       out << "AppListReady";
       break;
+    case TestEvent::kErrorDisplayed:
+      out << "ErrorDisplayed";
+      break;
     case TestEvent::kPaymentCompleted:
       out << "PaymentCompleted";
       break;
diff --git a/chrome/test/payments/test_event_waiter.h b/chrome/test/payments/test_event_waiter.h
index 29cbe1cb..36b98a84 100644
--- a/chrome/test/payments/test_event_waiter.h
+++ b/chrome/test/payments/test_event_waiter.h
@@ -25,6 +25,7 @@
   // Received when the list of available apps is created and .show() is called.
   // Note that this does not wait for the payment sheet UI to be actually shown.
   kAppListReady,
+  kErrorDisplayed,
   kPaymentCompleted,
   kMinimalUIReady,
   kUIDisplayed,
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index ffb2604..11bd602 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -72,6 +72,18 @@
       "crash_reporter.cc",
       "crash_reporter.h",
       "crx_downloader_factory.h",
+      "device_management/cloud_policy_util.cc",
+      "device_management/cloud_policy_util.h",
+      "device_management/dm_cached_policy_info.cc",
+      "device_management/dm_cached_policy_info.h",
+      "device_management/dm_client.cc",
+      "device_management/dm_client.h",
+      "device_management/dm_message.cc",
+      "device_management/dm_message.h",
+      "device_management/dm_response_validator.cc",
+      "device_management/dm_response_validator.h",
+      "device_management/dm_storage.cc",
+      "device_management/dm_storage.h",
       "enum_traits.h",
       "external_constants.cc",
       "external_constants.h",
@@ -135,6 +147,7 @@
       "//components/update_client:in_process_patcher",
       "//components/update_client:in_process_unzipper",
       "//components/version_info",
+      "//crypto",
       "//third_party/boringssl",
       "//third_party/crashpad/crashpad/client",
       "//third_party/crashpad/crashpad/handler",
@@ -154,6 +167,7 @@
         "app/server/mac/service_protocol.mm",
         "app/server/mac/update_service_wrappers.h",
         "app/server/mac/update_service_wrappers.mm",
+        "device_management/dm_storage_mac.mm",
         "installer_mac.cc",
         "launchd_util.cc",
         "launchd_util.h",
@@ -193,6 +207,7 @@
         "CoreServices.framework",
         "Foundation.framework",
         "ServiceManagement.framework",
+        "SystemConfiguration.framework",
       ]
     }
 
@@ -212,6 +227,7 @@
         "app/server/win/server.h",
         "app/server/win/service_main.cc",
         "app/server/win/service_main.h",
+        "device_management/dm_storage_win.cc",
         "lib_util_win.cc",
         "policy/win/group_policy_manager.cc",
         "policy/win/group_policy_manager.h",
@@ -389,6 +405,12 @@
     testonly = true
     sources = [
       "app/app_server_unittest.cc",
+      "device_management/dm_client_unittest.cc",
+      "device_management/dm_message_unittest.cc",
+      "device_management/dm_policy_builder_for_testing.cc",
+      "device_management/dm_policy_builder_for_testing.h",
+      "device_management/dm_response_validator_unittest.cc",
+      "device_management/dm_storage_unittest.cc",
       "enum_traits_unittest.cc",
       "external_constants_builder_unittest.cc",
       "external_constants_override_unittest.cc",
@@ -423,7 +445,6 @@
       "//base",
       "//base/test:test_support",
       "//chrome/common:constants",
-      "//chrome/updater/device_management:unittest",
       "//chrome/updater/protos:omaha_proto",
       "//chrome/updater/test/test_app:constants",
       "//chrome/updater/test/test_app:version_header",
diff --git a/chrome/updater/device_management/BUILD.gn b/chrome/updater/device_management/BUILD.gn
deleted file mode 100644
index 949ba3c..0000000
--- a/chrome/updater/device_management/BUILD.gn
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2020 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("//build/config/chrome_build.gni")
-import("//build/config/sanitizers/sanitizers.gni")
-import("//build/util/process_version.gni")
-import("//chrome/updater/branding.gni")
-import("//testing/test.gni")
-
-source_set("device_management") {
-  sources = [
-    "cloud_policy_util.cc",
-    "cloud_policy_util.h",
-    "dm_cached_policy_info.cc",
-    "dm_cached_policy_info.h",
-    "dm_client.cc",
-    "dm_client.h",
-    "dm_message.cc",
-    "dm_message.h",
-    "dm_response_validator.cc",
-    "dm_response_validator.h",
-    "dm_storage.cc",
-    "dm_storage.h",
-  ]
-
-  deps = [
-    "//base",
-    "//chrome/updater:base",
-    "//chrome/updater:branding_header",
-    "//chrome/updater:version_header",
-    "//chrome/updater/protos:omaha_proto",
-    "//components/update_client",
-    "//components/version_info",
-    "//crypto",
-    "//third_party/boringssl",
-    "//url",
-  ]
-  public_deps = [ "//components/policy/proto" ]
-
-  if (is_mac) {
-    sources += [ "dm_storage_mac.mm" ]
-  }
-  if (is_win) {
-    sources += [ "dm_storage_win.cc" ]
-  }
-
-  if (is_mac) {
-    frameworks = [ "SystemConfiguration.framework" ]
-  }
-}
-
-source_set("unittest") {
-  testonly = true
-
-  sources = [
-    "dm_client_unittest.cc",
-    "dm_message_unittest.cc",
-    "dm_policy_builder_for_testing.cc",
-    "dm_policy_builder_for_testing.h",
-    "dm_response_validator_unittest.cc",
-    "dm_storage_unittest.cc",
-  ]
-
-  deps = [
-    ":device_management",
-    "//base",
-    "//base/test:test_support",
-    "//chrome/updater:base",
-    "//chrome/updater:updater_tests_support",
-    "//chrome/updater/protos:omaha_proto",
-    "//components/update_client:update_client",
-    "//net:test_support",
-    "//testing/gtest",
-    "//url",
-  ]
-}
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index c5519d0..456de86b 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14029.0.0
\ No newline at end of file
+14031.0.0
\ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/js/views/camera/mode/photo.js b/chromeos/components/camera_app_ui/resources/js/views/camera/mode/photo.js
index 0fd5093a..02343b1 100644
--- a/chromeos/components/camera_app_ui/resources/js/views/camera/mode/photo.js
+++ b/chromeos/components/camera_app_ui/resources/js/views/camera/mode/photo.js
@@ -107,15 +107,6 @@
   }
 
   /**
-   * @return {boolean}
-   */
-  supportPTZ_() {
-    const {pan, tilt, zoom} =
-        this.stream_.getVideoTracks()[0].getCapabilities();
-    return pan !== undefined || tilt !== undefined || zoom !== undefined;
-  }
-
-  /**
    * @override
    */
   async start_() {
@@ -156,7 +147,7 @@
    * @return {!Promise<!Blob>}
    */
   async takePhoto_() {
-    if (this.supportPTZ_()) {
+    if (state.get(state.State.ENABLE_PTZ)) {
       // Workaround for b/184089334 on PTZ camera to use preview frame as
       // photo result.
       return this.handler_.getPreviewFrame();
diff --git a/chromeos/components/quick_answers/understanding/intent_generator.cc b/chromeos/components/quick_answers/understanding/intent_generator.cc
index b83d1e7c..08221d9 100644
--- a/chromeos/components/quick_answers/understanding/intent_generator.cc
+++ b/chromeos/components/quick_answers/understanding/intent_generator.cc
@@ -7,6 +7,7 @@
 #include <map>
 
 #include "ash/constants/ash_features.h"
+#include "ash/public/cpp/quick_answers/quick_answers_state.h"
 #include "base/i18n/case_conversion.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_split.h"
@@ -193,6 +194,17 @@
     auto intent_type_map = GetIntentTypeMap();
     auto it = intent_type_map.find(type);
     if (it != intent_type_map.end()) {
+      if (features::IsQuickAnswersV2Enabled()) {
+        // Skip the entity if the corresponding intent type is disabled.
+        if ((it->second == IntentType::kDictionary &&
+             !ash::QuickAnswersState::Get()->definition_enabled()) ||
+            (it->second == IntentType::kUnit &&
+             !ash::QuickAnswersState::Get()->unit_conversion_enabled())) {
+          // Fallback to language detection for generating translation intent.
+          MaybeGenerateTranslationIntent(request);
+          return;
+        }
+      }
       // Skip the entity for definition annonation.
       if (it->second == IntentType::kDictionary &&
           ShouldSkipDefinition(request.selected_text)) {
@@ -214,6 +226,13 @@
     const QuickAnswersRequest& request) {
   DCHECK(complete_callback_);
 
+  if (features::IsQuickAnswersV2Enabled() &&
+      !ash::QuickAnswersState::Get()->translation_enabled()) {
+    std::move(complete_callback_)
+        .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
+    return;
+  }
+
   if (!features::IsQuickAnswersTranslationEnabled()) {
     std::move(complete_callback_)
         .Run(IntentInfo(request.selected_text, IntentType::kUnknown));
diff --git a/chromeos/components/quick_pair/BUILD.gn b/chromeos/components/quick_pair/BUILD.gn
index 38f278f..031f177 100644
--- a/chromeos/components/quick_pair/BUILD.gn
+++ b/chromeos/components/quick_pair/BUILD.gn
@@ -10,6 +10,7 @@
   deps = [
     "//base/test:test_support",
     "//chromeos/components/quick_pair/common:unit_tests",
+    "//chromeos/components/quick_pair/feature_status_tracker:unit_tests",
     "//testing/gtest",
   ]
 }
diff --git a/chromeos/components/quick_pair/feature_status_tracker/BUILD.gn b/chromeos/components/quick_pair/feature_status_tracker/BUILD.gn
new file mode 100644
index 0000000..6acba82d
--- /dev/null
+++ b/chromeos/components/quick_pair/feature_status_tracker/BUILD.gn
@@ -0,0 +1,25 @@
+# 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.
+
+assert(is_chromeos, "Quick Pair protocols (e.g. Fast Pair) are CrOS only")
+
+static_library("feature_status_tracker") {
+  sources = [
+    "base_enabled_provider.cc",
+    "base_enabled_provider.h",
+  ]
+
+  deps = [ "//base" ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "base_enabled_provider_unittest.cc" ]
+
+  deps = [
+    ":feature_status_tracker",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.cc b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.cc
new file mode 100644
index 0000000..62c99f1c
--- /dev/null
+++ b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.cc
@@ -0,0 +1,37 @@
+// 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 "chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+
+namespace chromeos {
+namespace quick_pair {
+
+BaseEnabledProvider::BaseEnabledProvider() = default;
+
+BaseEnabledProvider::~BaseEnabledProvider() = default;
+
+bool BaseEnabledProvider::is_enabled() {
+  return is_enabled_;
+}
+
+void BaseEnabledProvider::SetCallback(
+    base::RepeatingCallback<void(bool)> callback) {
+  callback_ = std::move(callback);
+}
+
+void BaseEnabledProvider::SetEnabledAndInvokeCallback(bool new_value) {
+  if (is_enabled_ == new_value)
+    return;
+
+  is_enabled_ = new_value;
+
+  if (callback_)
+    callback_.Run(new_value);
+}
+
+}  // namespace quick_pair
+}  // namespace chromeos
diff --git a/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.h b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.h
new file mode 100644
index 0000000..10aaf17
--- /dev/null
+++ b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.h
@@ -0,0 +1,43 @@
+// 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 CHROMEOS_COMPONENTS_QUICK_PAIR_FEATURE_STATUS_TRACKER_BASE_ENABLED_PROVIDER_H_
+#define CHROMEOS_COMPONENTS_QUICK_PAIR_FEATURE_STATUS_TRACKER_BASE_ENABLED_PROVIDER_H_
+
+#include "base/callback.h"
+
+namespace chromeos {
+namespace quick_pair {
+
+// Common Base class to expose whether or not a feature is enabled.
+// Provides a |is_enabled()| method and a callback pattern to observe changes.
+//
+// Subclasses can focus on implementing the logic to determine the state of
+// |is_enabled()|, and this base class provides common functionality for
+// querying and observing that state.
+//
+// Example subclass: BluetoothEnabledProvider - Changes |is_enabled()| based on
+// the Bluetooth state on the device.
+class BaseEnabledProvider {
+ public:
+  BaseEnabledProvider();
+  BaseEnabledProvider(const BaseEnabledProvider&) = delete;
+  BaseEnabledProvider& operator=(const BaseEnabledProvider&) = delete;
+  virtual ~BaseEnabledProvider();
+
+  virtual bool is_enabled();
+  void SetCallback(base::RepeatingCallback<void(bool)> callback);
+
+ protected:
+  void SetEnabledAndInvokeCallback(bool new_value);
+
+ private:
+  bool is_enabled_;
+  base::RepeatingCallback<void(bool)> callback_;
+};
+
+}  // namespace quick_pair
+}  // namespace chromeos
+
+#endif  // CHROMEOS_COMPONENTS_QUICK_PAIR_FEATURE_STATUS_TRACKER_BASE_ENABLED_PROVIDER_H_
diff --git a/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider_unittest.cc b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider_unittest.cc
new file mode 100644
index 0000000..f163003
--- /dev/null
+++ b/chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider_unittest.cc
@@ -0,0 +1,82 @@
+// 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 "chromeos/components/quick_pair/feature_status_tracker/base_enabled_provider.h"
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/test/mock_callback.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class TestEnabledProvider : public chromeos::quick_pair::BaseEnabledProvider {
+ public:
+  using BaseEnabledProvider::SetEnabledAndInvokeCallback;
+};
+
+}  // namespace
+
+namespace chromeos {
+namespace quick_pair {
+
+class BaseEnabledProviderTest : public testing::Test {
+  void SetUp() override { provider_ = std::make_unique<TestEnabledProvider>(); }
+
+ protected:
+  std::unique_ptr<TestEnabledProvider> provider_;
+};
+
+TEST_F(BaseEnabledProviderTest, IsInitiallyDisabled) {
+  EXPECT_FALSE(provider_->is_enabled());
+}
+
+TEST_F(BaseEnabledProviderTest, CanSetEnabledWithoutACallback) {
+  provider_->SetEnabledAndInvokeCallback(true);
+  EXPECT_TRUE(provider_->is_enabled());
+}
+
+TEST_F(BaseEnabledProviderTest, CallbackInvoked) {
+  base::MockCallback<base::RepeatingCallback<void(bool)>> callback;
+  EXPECT_CALL(callback, Run(true));
+
+  provider_->SetCallback(callback.Get());
+  provider_->SetEnabledAndInvokeCallback(true);
+}
+
+TEST_F(BaseEnabledProviderTest, CallbackInvokedMultipleTimes) {
+  base::MockCallback<base::RepeatingCallback<void(bool)>> callback;
+  EXPECT_CALL(callback, Run(true)).Times(2);
+  EXPECT_CALL(callback, Run(false));
+
+  provider_->SetCallback(callback.Get());
+  provider_->SetEnabledAndInvokeCallback(true);
+  provider_->SetEnabledAndInvokeCallback(false);
+  provider_->SetEnabledAndInvokeCallback(true);
+}
+
+TEST_F(BaseEnabledProviderTest, CallbackNotInvokedForSameValue) {
+  base::MockCallback<base::RepeatingCallback<void(bool)>> callback;
+  EXPECT_CALL(callback, Run).Times(0);
+
+  provider_->SetCallback(callback.Get());
+  provider_->SetEnabledAndInvokeCallback(false);
+}
+
+TEST_F(BaseEnabledProviderTest, ReplacesCallback) {
+  base::MockCallback<base::RepeatingCallback<void(bool)>> callback;
+  EXPECT_CALL(callback, Run(true));
+
+  provider_->SetCallback(callback.Get());
+  provider_->SetEnabledAndInvokeCallback(true);
+
+  provider_->SetCallback(base::DoNothing());
+  EXPECT_CALL(callback, Run).Times(0);
+  provider_->SetEnabledAndInvokeCallback(false);
+}
+
+}  // namespace quick_pair
+}  // namespace chromeos
diff --git a/chromeos/crosapi/mojom/app_service.mojom b/chromeos/crosapi/mojom/app_service.mojom
index 371354f..bd50565 100644
--- a/chromeos/crosapi/mojom/app_service.mojom
+++ b/chromeos/crosapi/mojom/app_service.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Next MinVersion: 4
+// Next MinVersion: 5
 
 module crosapi.mojom;
 
@@ -60,4 +60,10 @@
   // the next time.
   [MinVersion=3]
   UnpauseApp@3(string app_id);
+
+  // Returns the context menu items for an app with |app_id| to show in app
+  // list and shelf. This interface only returns menu items that needs to be
+  // populated in lacros-chrome (e.g. app-specific shortcuts).
+  [MinVersion=4]
+  GetMenuModel@4(string app_id) => (MenuItems menu_items);
 };
diff --git a/chromeos/crosapi/mojom/app_service_types.mojom b/chromeos/crosapi/mojom/app_service_types.mojom
index d04c461d..90ebe01 100644
--- a/chromeos/crosapi/mojom/app_service_types.mojom
+++ b/chromeos/crosapi/mojom/app_service_types.mojom
@@ -240,3 +240,17 @@
   // Whether this icon data is a placeholder icon.
   bool is_placeholder_icon;
 };
+
+// MenuItems are used to populate context menus.
+[Stable]
+struct MenuItems {
+  array<MenuItem> items@0;
+};
+
+// The context menu model for each app. For web apps currently it's the info
+// for shortcut items.
+[Stable]
+struct MenuItem {
+  string label@0;                      // The string label, may be empty.
+  gfx.mojom.ImageSkia? image@1;        // The image icon, may be null.
+};
diff --git a/chromeos/services/assistant/public/cpp/features.cc b/chromeos/services/assistant/public/cpp/features.cc
index 252349b9..9324cb0 100644
--- a/chromeos/services/assistant/public/cpp/features.cc
+++ b/chromeos/services/assistant/public/cpp/features.cc
@@ -55,7 +55,7 @@
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kEnableLibAssistantSandbox{
-    "LibAssistantSandbox", base::FEATURE_ENABLED_BY_DEFAULT};
+    "LibAssistantSandbox", base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool IsAppSupportEnabled() {
   return base::FeatureList::IsEnabled(
diff --git a/components/arc/compat_mode/resize_util.cc b/components/arc/compat_mode/resize_util.cc
index c672ed5..1ce1a20 100644
--- a/components/arc/compat_mode/resize_util.cc
+++ b/components/arc/compat_mode/resize_util.cc
@@ -6,13 +6,17 @@
 
 #include <memory>
 
+#include "ash/public/cpp/toast_data.h"
+#include "ash/public/cpp/toast_manager.h"
 #include "ash/public/cpp/window_properties.h"
 #include "base/callback_forward.h"
 #include "base/callback_helpers.h"
 #include "base/stl_util.h"
 #include "components/arc/compat_mode/arc_resize_lock_pref_delegate.h"
 #include "components/arc/compat_mode/resize_confirmation_dialog_view.h"
+#include "components/strings/grit/components_strings.h"
 #include "ui/aura/window.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/views/widget/widget.h"
 
 namespace arc {
@@ -50,13 +54,41 @@
   }
 }
 
+void TurnOffResizeLock(views::Widget* target_widget,
+                       ArcResizeLockPrefDelegate* pref_delegate) {
+  const auto app_id = GetAppId(target_widget);
+  if (!app_id || pref_delegate->GetResizeLockState(*app_id) ==
+                     mojom::ArcResizeLockState::OFF) {
+    return;
+  }
+
+  pref_delegate->SetResizeLockState(*app_id, mojom::ArcResizeLockState::OFF);
+
+  auto* const toast_manager = ash::ToastManager::Get();
+  // |toast_manager| can be null in some unittests.
+  if (!toast_manager)
+    return;
+
+  constexpr char kTurnOffResizeLockToastId[] =
+      "arc.compat_mode.turn_off_resize_lock";
+  constexpr int kToastDurationMs = 3500;
+  toast_manager->Cancel(kTurnOffResizeLockToastId);
+  ash::ToastData toast(
+      kTurnOffResizeLockToastId,
+      l10n_util::GetStringUTF16(IDS_ARC_COMPAT_MODE_DISABLE_RESIZE_LOCK_TOAST),
+      kToastDurationMs,
+      /*dismiss_text=*/absl::nullopt,
+      /*visible_on_lock_screen=*/false);
+  toast_manager->Show(toast);
+}
+
 void TurnOffResizeLockWithConfirmationIfNeeded(
     views::Widget* target_widget,
     ArcResizeLockPrefDelegate* pref_delegate) {
   const auto app_id = GetAppId(target_widget);
   if (app_id && !pref_delegate->GetResizeLockNeedsConfirmation(*app_id)) {
     // The user has already agreed not to show the dialog again.
-    pref_delegate->SetResizeLockState(*app_id, mojom::ArcResizeLockState::OFF);
+    TurnOffResizeLock(target_widget, pref_delegate);
     return;
   }
 
@@ -72,8 +104,7 @@
               if (do_not_ask_again && app_id)
                 delegate->SetResizeLockNeedsConfirmation(*app_id, false);
 
-              delegate->SetResizeLockState(*app_id,
-                                           mojom::ArcResizeLockState::OFF);
+              TurnOffResizeLock(widget, delegate);
             }
           },
           base::Unretained(target_widget), base::Unretained(pref_delegate)));
diff --git a/components/arc/compat_mode/resize_util_unittest.cc b/components/arc/compat_mode/resize_util_unittest.cc
index f999a7cc..c51ff25 100644
--- a/components/arc/compat_mode/resize_util_unittest.cc
+++ b/components/arc/compat_mode/resize_util_unittest.cc
@@ -8,6 +8,7 @@
 #include <set>
 #include <string>
 
+#include "ash/public/cpp/toast_manager.h"
 #include "ash/public/cpp/window_properties.h"
 #include "base/containers/contains.h"
 #include "base/containers/flat_map.h"
@@ -68,6 +69,22 @@
   int show_count_ = kMaxNumSplashScreen;
 };
 
+class FakeToastManager : public ash::ToastManager {
+ public:
+  ~FakeToastManager() override = default;
+
+  // ToastManager overrides:
+  void Show(const ash::ToastData& data) override { called_show_ = true; }
+  void Cancel(const std::string& id) override { called_cancel_ = true; }
+
+  bool called_show() { return called_show_; }
+  bool called_cancel() { return called_cancel_; }
+
+ private:
+  bool called_show_{false};
+  bool called_cancel_{false};
+};
+
 }  // namespace
 
 class ResizeUtilTest : public exo::test::ExoTestBaseViews {
@@ -123,12 +140,16 @@
 // Test that enabling resizing works properly in both needs-confirmation and no
 // needs-conirmation case.
 TEST_F(ResizeUtilTest, TestEnableResizing) {
+  FakeToastManager fake_toast_manager;
+
   // Test the state is NOT changed immediately if the confirmation dialog is
   // needed.
   pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
   EnableResizingWithConfirmationIfNeeded(widget(), pref_delegate());
   EXPECT_NE(pref_delegate()->GetResizeLockState(kTestAppId),
             mojom::ArcResizeLockState::OFF);
+  EXPECT_FALSE(fake_toast_manager.called_cancel());
+  EXPECT_FALSE(fake_toast_manager.called_show());
 
   // Test the state is changed without confirmation.
   pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false);
@@ -137,6 +158,8 @@
             mojom::ArcResizeLockState::OFF);
   EXPECT_EQ(PredictCurrentMode(widget(), pref_delegate()),
             ResizeCompatMode::kResizable);
+  EXPECT_TRUE(fake_toast_manager.called_cancel());
+  EXPECT_TRUE(fake_toast_manager.called_show());
 }
 
 // Test that should show dialog screen dialog caps at a preset limit
diff --git a/components/arc/mojom/webapk.mojom b/components/arc/mojom/webapk.mojom
index dd57559..54a2c87 100644
--- a/components/arc/mojom/webapk.mojom
+++ b/components/arc/mojom/webapk.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 2
+// Next MinVersion: 3
 
 module arc.mojom;
 
@@ -27,8 +27,39 @@
   [MinVersion=1] kErrorInstallError = 13,
 };
 
+struct WebShareTargetInfo {
+  string? action;
+  string? method;
+  string? enctype;
+
+  string? param_title;
+  string? param_text;
+  string? param_url;
+
+  array<string> file_names;
+  array<array<string>> file_accepts;
+};
+
+// Information which can be read from the APK.
+struct WebApkInfo {
+  string package_name;
+  // The version of the currently installed APK, as generated by the minter.
+  string apk_version;
+  // The version of the common shell apk used to provide a template.
+  string shell_apk_version;
+
+  // Core metadata used to generate the APK:
+  string manifest_url;
+  string name;
+  string start_url;
+  string scope;
+  string icon_hash;
+
+  WebShareTargetInfo? share_info;
+};
+
 // Allows Chrome to install and manage WebAPKs inside ARC.
-// Next method ID: 1
+// Next method ID: 2
 interface WebApkInstance {
 
   // Install or update a WebAPK with the given |package_name|.
@@ -37,4 +68,8 @@
                   string app_name,
                   string token) =>
                       (WebApkInstallResult result);
+
+  // Gets the metadata stored within a WebAPK, defined by |pacakge_name|.
+  // Result is empty if no web apk was found with that |package name|.
+  [MinVersion=2] GetWebApkInfo@1(string package_name) => (WebApkInfo? result);
 };
diff --git a/components/arc/test/fake_webapk_instance.cc b/components/arc/test/fake_webapk_instance.cc
index 34e23b0..8c5fb94 100644
--- a/components/arc/test/fake_webapk_instance.cc
+++ b/components/arc/test/fake_webapk_instance.cc
@@ -18,4 +18,11 @@
   handled_packages_.push_back(package_name);
   std::move(callback).Run(install_result_);
 }
+
+void FakeWebApkInstance::GetWebApkInfo(const std::string& package_name,
+                                       GetWebApkInfoCallback callback) {
+  // TODO(crbug.com/1214695): Add WebAPK update tests.
+  NOTIMPLEMENTED();
+}
+
 }  // namespace arc
diff --git a/components/arc/test/fake_webapk_instance.h b/components/arc/test/fake_webapk_instance.h
index e3303241..91858a62 100644
--- a/components/arc/test/fake_webapk_instance.h
+++ b/components/arc/test/fake_webapk_instance.h
@@ -24,6 +24,9 @@
                      const std::string& token,
                      InstallWebApkCallback callback) override;
 
+  void GetWebApkInfo(const std::string& package_name,
+                     GetWebApkInfoCallback callback) override;
+
   const std::vector<std::string>& handled_packages() {
     return handled_packages_;
   }
diff --git a/components/arc_strings.grdp b/components/arc_strings.grdp
index 4a4dfe2..cc28316 100644
--- a/components/arc_strings.grdp
+++ b/components/arc_strings.grdp
@@ -40,6 +40,9 @@
   <message name="IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK" desc="Text of link to app settings.">
     Settings
   </message>
+  <message name="IDS_ARC_COMPAT_MODE_DISABLE_RESIZE_LOCK_TOAST" desc="Toast message shown to the user when the user makes the app resizable.">
+    You can now drag and resize this app
+  </message>
 
   <!-- ARC ghost window -->
   <message name="IDS_ARC_GHOST_WINDOW_APP_LAUNCHING_ICON" desc="The icon of launching app.">
diff --git a/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_DISABLE_RESIZE_LOCK_TOAST.png.sha1 b/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_DISABLE_RESIZE_LOCK_TOAST.png.sha1
new file mode 100644
index 0000000..e56cb44
--- /dev/null
+++ b/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_DISABLE_RESIZE_LOCK_TOAST.png.sha1
@@ -0,0 +1 @@
+f27d91df0758a83837e774305c15ff97f75574c6
\ No newline at end of file
diff --git a/components/content_creation/notes/core/BUILD.gn b/components/content_creation/notes/core/BUILD.gn
index 95869d5..c660060 100644
--- a/components/content_creation/notes/core/BUILD.gn
+++ b/components/content_creation/notes/core/BUILD.gn
@@ -39,6 +39,7 @@
     ":features",
     "//base",
     "//base/test:test_support",
+    "//components/content_creation/notes/core/server",
     "//components/content_creation/notes/core/templates",
     "//components/content_creation/notes/core/test:test_support",
     "//testing/gmock",
diff --git a/components/content_creation/notes/core/note_service.cc b/components/content_creation/notes/core/note_service.cc
index ba7ccf2..7367634 100644
--- a/components/content_creation/notes/core/note_service.cc
+++ b/components/content_creation/notes/core/note_service.cc
@@ -6,11 +6,14 @@
 
 #include "base/callback.h"
 #include "components/content_creation/notes/core/note_features.h"
+#include "components/content_creation/notes/core/server/notes_repository.h"
 
 namespace content_creation {
 
-NoteService::NoteService(std::unique_ptr<TemplateStore> template_store)
-    : template_store_(std::move(template_store)) {}
+NoteService::NoteService(std::unique_ptr<TemplateStore> template_store,
+                         std::unique_ptr<NotesRepository> notes_repository)
+    : template_store_(std::move(template_store)),
+      notes_repository_(std::move(notes_repository)) {}
 
 NoteService::~NoteService() = default;
 
@@ -19,4 +22,10 @@
   template_store_->GetTemplates(std::move(callback));
 }
 
+void NoteService::PublishNote(
+    const NoteData& note_data,
+    base::OnceCallback<void(SaveNoteResponse)> callback) {
+  notes_repository_->PublishNote(note_data, std::move(callback));
+}
+
 }  // namespace content_creation
\ No newline at end of file
diff --git a/components/content_creation/notes/core/note_service.h b/components/content_creation/notes/core/note_service.h
index 6fb6aaf..ee823f6 100644
--- a/components/content_creation/notes/core/note_service.h
+++ b/components/content_creation/notes/core/note_service.h
@@ -8,16 +8,23 @@
 #include <memory>
 
 #include "base/supports_user_data.h"
+#include "components/content_creation/notes/core/server/note_data.h"
+#include "components/content_creation/notes/core/server/save_note_response.h"
 #include "components/content_creation/notes/core/templates/template_store.h"
 #include "components/keyed_service/core/keyed_service.h"
 
 namespace content_creation {
 
+using PublishNoteCallback = base::OnceCallback<void(SaveNoteResponse)>;
+
+class NotesRepository;
+
 // Keyed service to be used by user-facing surfaces to retrieve templating
 // information for generating stylized notes.
 class NoteService : public KeyedService, public base::SupportsUserData {
  public:
-  explicit NoteService(std::unique_ptr<TemplateStore> template_store);
+  explicit NoteService(std::unique_ptr<TemplateStore> template_store,
+                       std::unique_ptr<NotesRepository> notes_repository);
   ~NoteService() override;
 
   // Not copyable or movable.
@@ -28,8 +35,14 @@
   // invoke |callback| with the results.
   void GetTemplates(GetTemplatesCallback callback);
 
+  // Saves and publishes the |note| to the server. Will invoke |callback| with
+  // results and URL to access the published note.
+  void PublishNote(const NoteData& note_data, PublishNoteCallback callback);
+
  private:
   std::unique_ptr<TemplateStore> template_store_;
+
+  std::unique_ptr<NotesRepository> notes_repository_;
 };
 
 }  // namespace content_creation
diff --git a/components/content_creation/notes/core/note_service_unittest.cc b/components/content_creation/notes/core/note_service_unittest.cc
index 744c655..c410f89 100644
--- a/components/content_creation/notes/core/note_service_unittest.cc
+++ b/components/content_creation/notes/core/note_service_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "components/content_creation/notes/core/note_features.h"
+#include "components/content_creation/notes/core/server/save_note_response.h"
 #include "components/content_creation/notes/core/templates/note_template.h"
 #include "components/content_creation/notes/core/test/mocks.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -27,8 +28,11 @@
     auto mock_template_store = std::make_unique<test::MockTemplateStore>();
     mock_template_store_ = mock_template_store.get();
 
-    note_service_ =
-        std::make_unique<NoteService>(std::move(mock_template_store));
+    auto mock_notes_repository = std::make_unique<test::MockNotesRepository>();
+    mock_notes_repository_ = mock_notes_repository.get();
+
+    note_service_ = std::make_unique<NoteService>(
+        std::move(mock_template_store), std::move(mock_notes_repository));
   }
 
  protected:
@@ -40,6 +44,7 @@
   base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<NoteService> note_service_;
   test::MockTemplateStore* mock_template_store_;
+  test::MockNotesRepository* mock_notes_repository_;
 };
 
 TEST_F(NoteServiceTest, GetTemplatesSuccess_Empty) {
@@ -49,4 +54,13 @@
       [](std::vector<NoteTemplate> templates) { /* No-op */ }));
 }
 
+TEST_F(NoteServiceTest, PublishNoteSuccess_Empty) {
+  EXPECT_CALL(*mock_notes_repository_, PublishNote(_, _)).Times(1);
+
+  NoteData data("", "", GURL(), "");
+  note_service_->PublishNote(
+      data, base::BindLambdaForTesting(
+                [](SaveNoteResponse response) { /* No-op */ }));
+}
+
 }  // namespace content_creation
diff --git a/components/content_creation/notes/core/server/BUILD.gn b/components/content_creation/notes/core/server/BUILD.gn
index e16136f..81995b1 100644
--- a/components/content_creation/notes/core/server/BUILD.gn
+++ b/components/content_creation/notes/core/server/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "note_data.cc",
     "note_data.h",
+    "notes_repository.cc",
+    "notes_repository.h",
     "notes_server_base.cc",
     "notes_server_base.h",
     "notes_server_saver.cc",
diff --git a/components/content_creation/notes/core/server/notes_repository.cc b/components/content_creation/notes/core/server/notes_repository.cc
new file mode 100644
index 0000000..7d0601a
--- /dev/null
+++ b/components/content_creation/notes/core/server/notes_repository.cc
@@ -0,0 +1,41 @@
+// 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 "components/content_creation/notes/core/server/notes_repository.h"
+
+#include "components/content_creation/notes/core/server/notes_server_saver.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace content_creation {
+
+NotesRepository::NotesRepository(
+    signin::IdentityManager* identity_manager,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+    : identity_manager_(identity_manager),
+      url_loader_factory_(url_loader_factory) {}
+
+NotesRepository::~NotesRepository() = default;
+
+void NotesRepository::PublishNote(const NoteData& note_data,
+                                  PublishNoteCallback callback) {
+  notes_saver_ = std::make_unique<NotesServerSaver>(
+      url_loader_factory_, identity_manager_, note_data,
+      base::BindOnce(&NotesRepository::OnNotePublished,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+
+  notes_saver_->Start();
+}
+
+// Used for tests.
+NotesRepository::NotesRepository() = default;
+
+void NotesRepository::OnNotePublished(PublishNoteCallback callback,
+                                      SaveNoteResponse save_response) {
+  notes_saver_.reset();
+
+  NOTIMPLEMENTED();
+}
+
+}  // namespace content_creation
diff --git a/components/content_creation/notes/core/server/notes_repository.h b/components/content_creation/notes/core/server/notes_repository.h
new file mode 100644
index 0000000..51ca68e
--- /dev/null
+++ b/components/content_creation/notes/core/server/notes_repository.h
@@ -0,0 +1,62 @@
+// 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 COMPONENTS_CONTENT_CREATION_NOTES_CORE_SERVER_NOTES_REPOSITORY_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_SERVER_NOTES_REPOSITORY_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/content_creation/notes/core/server/note_data.h"
+#include "components/content_creation/notes/core/server/save_note_response.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}  // namespace network
+namespace signin {
+class IdentityManager;
+}  // namespace signin
+
+namespace content_creation {
+
+using PublishNoteCallback = base::OnceCallback<void(SaveNoteResponse)>;
+
+class NotesServerSaver;
+
+// Instance in charge of saving and publishing the notes to the server.
+class NotesRepository {
+ public:
+  explicit NotesRepository(
+      signin::IdentityManager* identity_manager,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+  virtual ~NotesRepository();
+
+  // Not copyable or movable.
+  NotesRepository(const NotesRepository&) = delete;
+  NotesRepository& operator=(const NotesRepository&) = delete;
+
+  // Saves and publishes the |note| to the server. Will invoke |callback| with
+  // results and URL to access the published note.
+  virtual void PublishNote(const NoteData& note_data,
+                           PublishNoteCallback callback);
+
+ protected:
+  // Used for tests.
+  NotesRepository();
+
+  virtual void OnNotePublished(PublishNoteCallback callback,
+                               SaveNoteResponse save_response);
+
+ private:
+  signin::IdentityManager* identity_manager_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  std::unique_ptr<NotesServerSaver> notes_saver_;
+
+  base::WeakPtrFactory<NotesRepository> weak_ptr_factory_{this};
+};
+
+}  // namespace content_creation
+
+#endif  // COMPONENTS_CONTENT_CREATION_NOTES_CORE_SERVER_NOTES_REPOSITORY_H_
\ No newline at end of file
diff --git a/components/content_creation/notes/core/test/BUILD.gn b/components/content_creation/notes/core/test/BUILD.gn
index d990ddcb..710378d 100644
--- a/components/content_creation/notes/core/test/BUILD.gn
+++ b/components/content_creation/notes/core/test/BUILD.gn
@@ -10,6 +10,7 @@
   ]
   deps = [
     "//base",
+    "//components/content_creation/notes/core/server",
     "//components/content_creation/notes/core/templates",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/content_creation/notes/core/test/mocks.cc b/components/content_creation/notes/core/test/mocks.cc
index 29d3e84..179bd52 100644
--- a/components/content_creation/notes/core/test/mocks.cc
+++ b/components/content_creation/notes/core/test/mocks.cc
@@ -10,5 +10,8 @@
 MockTemplateStore::MockTemplateStore() = default;
 MockTemplateStore::~MockTemplateStore() = default;
 
+MockNotesRepository::MockNotesRepository() = default;
+MockNotesRepository::~MockNotesRepository() = default;
+
 }  // namespace test
 }  // namespace content_creation
\ No newline at end of file
diff --git a/components/content_creation/notes/core/test/mocks.h b/components/content_creation/notes/core/test/mocks.h
index e159fad..627361e 100644
--- a/components/content_creation/notes/core/test/mocks.h
+++ b/components/content_creation/notes/core/test/mocks.h
@@ -6,6 +6,8 @@
 #define COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEST_MOCKS_H_
 
 #include "base/callback.h"
+#include "components/content_creation/notes/core/server/note_data.h"
+#include "components/content_creation/notes/core/server/notes_repository.h"
 #include "components/content_creation/notes/core/templates/note_template.h"
 #include "components/content_creation/notes/core/templates/template_store.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -21,6 +23,14 @@
   MOCK_METHOD1(GetTemplates, void(GetTemplatesCallback));
 };
 
+class MockNotesRepository : public NotesRepository {
+ public:
+  explicit MockNotesRepository();
+  ~MockNotesRepository() override;
+
+  MOCK_METHOD2(PublishNote, void(const NoteData&, PublishNoteCallback));
+};
+
 }  // namespace test
 }  // namespace content_creation
 
diff --git a/components/exo/shell_surface_util.cc b/components/exo/shell_surface_util.cc
index c667098..d1ee475 100644
--- a/components/exo/shell_surface_util.cc
+++ b/components/exo/shell_surface_util.cc
@@ -288,6 +288,13 @@
       new Permission(Permission::Capability::kActivate, timeout));
 }
 
+void GrantPermissionToActivateIndefinitely(aura::Window* window) {
+  // Activation is the only permission, so just set the property. The window
+  // owns the Permission object.
+  window->SetProperty(kPermissionKey,
+                      new Permission(Permission::Capability::kActivate));
+}
+
 void RevokePermissionToActivate(aura::Window* window) {
   // Activation is the only permission, so just clear the property.
   window->ClearProperty(kPermissionKey);
diff --git a/components/exo/shell_surface_util.h b/components/exo/shell_surface_util.h
index 52fb80b..d0b57a07 100644
--- a/components/exo/shell_surface_util.h
+++ b/components/exo/shell_surface_util.h
@@ -26,7 +26,7 @@
 namespace ui {
 class LocatedEvent;
 class KeyEvent;
-}
+}  // namespace ui
 
 namespace exo {
 
@@ -95,6 +95,10 @@
 // any existing permission.
 void GrantPermissionToActivate(aura::Window* window, base::TimeDelta timeout);
 
+// Allows the |window| to activate itself indefinitely. Revokes any existing
+// permission.
+void GrantPermissionToActivateIndefinitely(aura::Window* window);
+
 // Revokes the permission for |window| to activate itself.
 void RevokePermissionToActivate(aura::Window* window);
 
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc
index 187b034..1d4b5e09 100644
--- a/components/favicon/content/content_favicon_driver.cc
+++ b/components/favicon/content/content_favicon_driver.cc
@@ -103,7 +103,11 @@
 
 void ContentFaviconDriver::DownloadManifest(const GURL& url,
                                             ManifestDownloadCallback callback) {
-  web_contents()->GetManifest(
+  // TODO(crbug.com/1201237): This appears to be reachable from pages other
+  // than the primary page. This code should likely be refactored so that either
+  // this is unreachable from other pages, or the correct page is plumbed in
+  // here.
+  web_contents()->GetMainFrame()->GetPage().GetManifest(
       base::BindOnce(&ContentFaviconDriver::OnDidDownloadManifest,
                      base::Unretained(this), std::move(callback)));
 }
diff --git a/components/favicon/content/content_favicon_driver.h b/components/favicon/content/content_favicon_driver.h
index 6ba904d..db3e1c8b 100644
--- a/components/favicon/content/content_favicon_driver.h
+++ b/components/favicon/content/content_favicon_driver.h
@@ -18,6 +18,10 @@
 #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
 #include "url/gurl.h"
 
+namespace blink {
+struct Manifest;
+}  // namespace blink
+
 namespace favicon {
 
 class CoreFaviconService;
diff --git a/components/full_restore/full_restore_save_handler.cc b/components/full_restore/full_restore_save_handler.cc
index 519aee5..cd52e07 100644
--- a/components/full_restore/full_restore_save_handler.cc
+++ b/components/full_restore/full_restore_save_handler.cc
@@ -362,6 +362,14 @@
   return arc_save_handler_->GetArcSessionId();
 }
 
+const RestoreData* FullRestoreSaveHandler::GetRestoreData(
+    const base::FilePath& profile_path) {
+  auto it = profile_path_to_restore_data_.find(profile_path);
+  if (it == profile_path_to_restore_data_.end())
+    return nullptr;
+  return &(profile_path_to_restore_data_[profile_path]);
+}
+
 void FullRestoreSaveHandler::ClearForTesting() {
   profile_path_to_file_handler_.clear();
   profile_path_to_restore_data_.clear();
diff --git a/components/full_restore/full_restore_save_handler.h b/components/full_restore/full_restore_save_handler.h
index 3c59cb2..0d01c77 100644
--- a/components/full_restore/full_restore_save_handler.h
+++ b/components/full_restore/full_restore_save_handler.h
@@ -25,7 +25,7 @@
 namespace base {
 class FilePath;
 class SequencedTaskRunner;
-}
+}  // namespace base
 
 namespace full_restore {
 
@@ -134,6 +134,10 @@
   // Generates the ARC session id (0 - 1,000,000,000) for ARC apps.
   int32_t GetArcSessionId();
 
+  // Returns the RestoreData that associates with |profile_path|. Returns
+  // nullptr if there is no such RestoreData.
+  const RestoreData* GetRestoreData(const base::FilePath& profile_path);
+
   base::OneShotTimer* GetTimerForTesting() { return &save_timer_; }
 
   // Since this is a singleton, tests may need to clear it between tests.
diff --git a/components/full_restore/restore_data.cc b/components/full_restore/restore_data.cc
index 51a7be9..ff897c8 100644
--- a/components/full_restore/restore_data.cc
+++ b/components/full_restore/restore_data.cc
@@ -116,7 +116,7 @@
 void RestoreData::ModifyWindowInfo(const std::string& app_id,
                                    int32_t window_id,
                                    const WindowInfo& window_info) {
-  auto* app_restore_data = GetAppRestoreData(app_id, window_id);
+  auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
   if (app_restore_data)
     app_restore_data->ModifyWindowInfo(window_info);
 }
@@ -125,7 +125,7 @@
                                    int32_t window_id,
                                    uint32_t primary_color,
                                    uint32_t status_bar_color) {
-  auto* app_restore_data = GetAppRestoreData(app_id, window_id);
+  auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
   if (app_restore_data)
     app_restore_data->ModifyThemeColor(primary_color, status_bar_color);
 }
@@ -158,7 +158,7 @@
 }
 
 void RestoreData::RemoveWindowInfo(const std::string& app_id, int window_id) {
-  auto* app_restore_data = GetAppRestoreData(app_id, window_id);
+  auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
   if (app_restore_data)
     app_restore_data->ClearWindowInfo();
 }
@@ -208,8 +208,8 @@
   return window_id;
 }
 
-AppRestoreData* RestoreData::GetAppRestoreData(const std::string& app_id,
-                                               int window_id) {
+const AppRestoreData* RestoreData::GetAppRestoreData(const std::string& app_id,
+                                                     int window_id) const {
   auto it = app_id_to_launch_list_.find(app_id);
   if (it == app_id_to_launch_list_.end())
     return nullptr;
@@ -221,4 +221,9 @@
   return data_it->second.get();
 }
 
+AppRestoreData* RestoreData::GetAppRestoreDataMutable(const std::string& app_id,
+                                                      int window_id) {
+  return const_cast<AppRestoreData*>(GetAppRestoreData(app_id, window_id));
+}
+
 }  // namespace full_restore
diff --git a/components/full_restore/restore_data.h b/components/full_restore/restore_data.h
index 453bade..da1c28de 100644
--- a/components/full_restore/restore_data.h
+++ b/components/full_restore/restore_data.h
@@ -167,6 +167,9 @@
   // FetchRestoreWindowId('bb') return 0.
   int32_t FetchRestoreWindowId(const std::string& app_id);
 
+  const AppRestoreData* GetAppRestoreData(const std::string& app_id,
+                                          int window_id) const;
+
   const AppIdToLaunchList& app_id_to_launch_list() const {
     return app_id_to_launch_list_;
   }
@@ -174,7 +177,8 @@
  private:
   // Returns the pointer to AppRestoreData for the given |app_id| and
   // |window_id|. Returns null if there is no AppRestoreData.
-  AppRestoreData* GetAppRestoreData(const std::string& app_id, int window_id);
+  AppRestoreData* GetAppRestoreDataMutable(const std::string& app_id,
+                                           int window_id);
 
   AppIdToLaunchList app_id_to_launch_list_;
 
diff --git a/components/metrics/content/subprocess_metrics_provider.cc b/components/metrics/content/subprocess_metrics_provider.cc
index 8cfba201..2531fc6 100644
--- a/components/metrics/content/subprocess_metrics_provider.cc
+++ b/components/metrics/content/subprocess_metrics_provider.cc
@@ -122,7 +122,7 @@
   }
 }
 
-void SubprocessMetricsProvider::BrowserChildProcessHostConnected(
+void SubprocessMetricsProvider::BrowserChildProcessLaunchedAndConnected(
     const content::ChildProcessData& data) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
diff --git a/components/metrics/content/subprocess_metrics_provider.h b/components/metrics/content/subprocess_metrics_provider.h
index d6bb943..199e2961 100644
--- a/components/metrics/content/subprocess_metrics_provider.h
+++ b/components/metrics/content/subprocess_metrics_provider.h
@@ -74,7 +74,7 @@
   void MergeHistogramDeltas() override;
 
   // content::BrowserChildProcessObserver:
-  void BrowserChildProcessHostConnected(
+  void BrowserChildProcessLaunchedAndConnected(
       const content::ChildProcessData& data) override;
   void BrowserChildProcessHostDisconnected(
       const content::ChildProcessData& data) override;
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
index 0f06d32..1f13bed2 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -164,6 +164,7 @@
         void onHasEnrolledInstrumentCalled();
         void onHasEnrolledInstrumentReturned();
         void onAppListReady(@Nullable List<PaymentApp> paymentApps, PaymentItem total);
+        void onErrorDisplayed();
         void onNotSupportedError();
         void onConnectionTerminated();
         void onAbortCalled();
@@ -1740,5 +1741,6 @@
         if (mBrowserPaymentRequest == null) return;
         mBrowserPaymentRequest.onInstrumentDetailsError(errorMessage);
         PaymentDetailsUpdateServiceHelper.getInstance().reset();
+        if (sNativeObserverForTest != null) sNativeObserverForTest.onErrorDisplayed();
     }
 }
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentUiServiceTestInterface.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentUiServiceTestInterface.java
index 4f73c97..ac57b51 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentUiServiceTestInterface.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentUiServiceTestInterface.java
@@ -31,6 +31,13 @@
     boolean clickPaymentHandlerCloseButtonForTest();
 
     /**
+     * Closes the payment UI.
+     *
+     * @return Whether the closing was successful.
+     */
+    boolean closeDialogForTest();
+
+    /**
      * Confirms payment in minimal UI.
      *
      * @return Whether the payment was confirmed successfully.
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc
index 5509338..979b918 100644
--- a/components/payments/content/payment_request.cc
+++ b/components/payments/content/payment_request.cc
@@ -994,6 +994,8 @@
     // Will invoke OnUserCancelled() asynchronously when the user closes the
     // error message UI.
     delegate_->ShowErrorMessage();
+    if (observer_for_testing_)
+      observer_for_testing_->OnErrorDisplayed();
   } else {
     // Only app store billing apps do not display any browser payment UI.
     DCHECK(spec_->IsAppStoreBillingAlsoRequested());
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h
index 06c849a..43576a0 100644
--- a/components/payments/content/payment_request.h
+++ b/components/payments/content/payment_request.h
@@ -55,6 +55,7 @@
     virtual void OnHasEnrolledInstrumentReturned() = 0;
     virtual void OnAppListReady(base::WeakPtr<PaymentRequest> payment_request) {
     }
+    virtual void OnErrorDisplayed() {}
     virtual void OnNotSupportedError() = 0;
     virtual void OnConnectionTerminated() = 0;
     virtual void OnAbortCalled() = 0;
@@ -108,13 +109,13 @@
   // TerminateConnection).
   void OnUserCancelled();
 
-  // Called when the main frame attached to this PaymentRequest is navigating to
-  // another document, but before the PaymentRequest is destroyed.
+  // Called when the main frame attached to this PaymentRequest is navigating
+  // to another document, but before the PaymentRequest is destroyed.
   void DidStartMainFrameNavigationToDifferentDocument(bool is_user_initiated);
 
   // Called when the frame attached to this PaymentRequest is about to be
-  // destroyed. This is used to clean up before the RenderFrameHost is actually
-  // destroyed because some objects held by the PaymentRequest (e.g.
+  // destroyed. This is used to clean up before the RenderFrameHost is
+  // actually destroyed because some objects held by the PaymentRequest (e.g.
   // InternalAuthenticator) must be out-lived by the RenderFrameHost.
   void RenderFrameDeleted(content::RenderFrameHost* render_frame_host);
 
@@ -132,7 +133,8 @@
 
   bool IsOffTheRecord() const;
 
-  // Called when the payment handler requests to open a payment handler window.
+  // Called when the payment handler requests to open a payment handler
+  // window.
   void OnPaymentHandlerOpenWindowCalled();
 
   content::WebContents* web_contents();
@@ -158,13 +160,13 @@
   // InitializationTask::Observer.
   void OnInitialized(InitializationTask* initialization_task) override;
 
-  // Returns true after init() has been called and the mojo connection has been
-  // established. If the mojo connection gets later disconnected, this will
-  // returns false.
+  // Returns true after init() has been called and the mojo connection has
+  // been established. If the mojo connection gets later disconnected, this
+  // will returns false.
   bool IsInitialized() const;
 
-  // Returns true after show() has been called and the payment sheet is showing.
-  // If the payment sheet is later hidden, this will return false.
+  // Returns true after show() has been called and the payment sheet is
+  // showing. If the payment sheet is later hidden, this will return false.
   bool IsThisPaymentRequestShowing() const;
 
   // Returns true when there is exactly one available payment app which can
@@ -177,9 +179,9 @@
   // information.
   bool SatisfiesSkipUIConstraints();
 
-  // Only records the abort reason if it's the first completion for this Payment
-  // Request. This is necessary since the aborts cascade into one another with
-  // the first one being the most precise.
+  // Only records the abort reason if it's the first completion for this
+  // Payment Request. This is necessary since the aborts cascade into one
+  // another with the first one being the most precise.
   void RecordFirstAbortReason(JourneyLogger::AbortReason completion_status);
 
   // The callback for PaymentRequestState::CanMakePayment.
@@ -229,17 +231,17 @@
 
   // The scheme, host, and port of the top level frame that has invoked
   // PaymentRequest API as formatted by
-  // url_formatter::FormatUrlForSecurityDisplay(). This is what the user sees in
-  // the address bar.
+  // url_formatter::FormatUrlForSecurityDisplay(). This is what the user sees
+  // in the address bar.
   const GURL top_level_origin_;
 
-  // The scheme, host, and port of the frame that has invoked PaymentRequest API
-  // as formatted by url_formatter::FormatUrlForSecurityDisplay(). This can be
-  // either the main frame or an iframe.
+  // The scheme, host, and port of the frame that has invoked PaymentRequest
+  // API as formatted by url_formatter::FormatUrlForSecurityDisplay(). This
+  // can be either the main frame or an iframe.
   const GURL frame_origin_;
 
-  // The security origin of the frame that has invoked PaymentRequest API. This
-  // can be opaque. Used by security features like 'Sec-Fetch-Site' and
+  // The security origin of the frame that has invoked PaymentRequest API.
+  // This can be opaque. Used by security features like 'Sec-Fetch-Site' and
   // 'Cross-Origin-Resource-Policy'.
   const url::Origin frame_security_origin_;
 
diff --git a/components/payments/content/secure_payment_confirmation_app.cc b/components/payments/content/secure_payment_confirmation_app.cc
index 6fb886a..03d1e2d 100644
--- a/components/payments/content/secure_payment_confirmation_app.cc
+++ b/components/payments/content/secure_payment_confirmation_app.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/base64.h"
+#include "base/base64url.h"
 #include "base/check.h"
 #include "base/containers/flat_tree.h"
 #include "base/feature_list.h"
@@ -36,6 +37,19 @@
 
 static constexpr int kDefaultTimeoutMinutes = 3;
 
+std::string EncodeSecurePaymentConfirmationString(
+    const std::vector<uint8_t>& vector_to_encode) {
+  if (base::FeatureList::IsEnabled(features::kSecurePaymentConfirmationAPIV2)) {
+    std::string encoded_string;
+    base::Base64UrlEncode(
+        std::string(vector_to_encode.begin(), vector_to_encode.end()),
+        base::Base64UrlEncodePolicy::OMIT_PADDING, &encoded_string);
+    return encoded_string;
+  } else {
+    return base::Base64Encode(vector_to_encode);
+  }
+}
+
 // Creates a SHA-256 hash over the Secure Payment Confirmation bundle, which is
 // a JSON string (without whitespace) with the following structure:
 //   {
@@ -66,14 +80,17 @@
   merchant_data.SetKey("total", std::move(total));
 
   base::Value transaction_data(base::Value::Type::DICTIONARY);
+
   // `challenge` is a renaming of `networkData` used if the
   // SecurePaymentConfirmationAPIV2 flag is enabled.
   if (base::FeatureList::IsEnabled(features::kSecurePaymentConfirmationAPIV2)) {
-    transaction_data.SetKey("challenge",
-                            base::Value(base::Base64Encode(network_data)));
+    transaction_data.SetKey(
+        "challenge",
+        base::Value(EncodeSecurePaymentConfirmationString(network_data)));
   } else {
-    transaction_data.SetKey("networkData",
-                            base::Value(base::Base64Encode(network_data)));
+    transaction_data.SetKey(
+        "networkData",
+        base::Value(EncodeSecurePaymentConfirmationString(network_data)));
   }
   transaction_data.SetKey("merchantData", std::move(merchant_data));
 
@@ -113,7 +130,8 @@
       icon_(std::move(icon)),
       label_(label),
       credential_id_(std::move(credential_id)),
-      encoded_credential_id_(base::Base64Encode(credential_id_)),
+      encoded_credential_id_(
+          EncodeSecurePaymentConfirmationString(credential_id_)),
       merchant_origin_(merchant_origin),
       spec_(spec),
       request_(std::move(request)),
@@ -307,30 +325,33 @@
   if (response->info) {
     info_json->SetString("id", response->info->id);
     info_json->SetString("client_data_json",
-                         base::Base64Encode(response->info->client_data_json));
-    info_json->SetString(
-        "authenticator_data",
-        base::Base64Encode(response->info->authenticator_data));
+                         EncodeSecurePaymentConfirmationString(
+                             response->info->client_data_json));
+    info_json->SetString("authenticator_data",
+                         EncodeSecurePaymentConfirmationString(
+                             response->info->authenticator_data));
   }
 
   auto prf_results_json = std::make_unique<base::DictionaryValue>();
   if (response->prf_results) {
     DCHECK(!response->prf_results->id.has_value());
-    prf_results_json->SetString(
-        "first", base::Base64Encode(response->prf_results->first));
+    prf_results_json->SetString("first", EncodeSecurePaymentConfirmationString(
+                                             response->prf_results->first));
     if (response->prf_results->second) {
-      prf_results_json->SetString(
-          "second", base::Base64Encode(*response->prf_results->second));
+      prf_results_json->SetString("second",
+                                  EncodeSecurePaymentConfirmationString(
+                                      *response->prf_results->second));
     }
   }
 
   base::DictionaryValue json;
   json.Set("info", std::move(info_json));
   json.SetString("challenge", challenge_);
-  json.SetString("signature", base::Base64Encode(response->signature));
+  json.SetString("signature",
+                 EncodeSecurePaymentConfirmationString(response->signature));
   if (response->user_handle.has_value()) {
-    json.SetString("user_handle",
-                   base::Base64Encode(response->user_handle.value()));
+    json.SetString("user_handle", EncodeSecurePaymentConfirmationString(
+                                      response->user_handle.value()));
   }
   json.SetBoolean("echo_appid_extension", response->echo_appid_extension);
   json.SetBoolean("appid_extension", response->appid_extension);
diff --git a/components/pdf/renderer/BUILD.gn b/components/pdf/renderer/BUILD.gn
index 5e9da19..0cdb846 100644
--- a/components/pdf/renderer/BUILD.gn
+++ b/components/pdf/renderer/BUILD.gn
@@ -26,6 +26,7 @@
     "//content/public/common",
     "//gin",
     "//ipc",
+    "//pdf:buildflags",
     "//pdf:features",
     "//ppapi/host",
     "//ppapi/proxy",
diff --git a/components/pdf/renderer/DEPS b/components/pdf/renderer/DEPS
index a9f723b..243de0d 100644
--- a/components/pdf/renderer/DEPS
+++ b/components/pdf/renderer/DEPS
@@ -3,6 +3,7 @@
   "+content/public/test",
   "+components/strings/grit/components_strings.h",
   "+mojo/public/cpp/bindings",
+  "+pdf/buildflags.h",
   "+pdf/pdf_features.h",
   "+ppapi",
   "+skia/ext",
diff --git a/components/pdf/renderer/pepper_pdf_host.h b/components/pdf/renderer/pepper_pdf_host.h
index 4b95e39..2be32c3 100644
--- a/components/pdf/renderer/pepper_pdf_host.h
+++ b/components/pdf/renderer/pepper_pdf_host.h
@@ -17,12 +17,17 @@
 #include "ipc/ipc_platform_file.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
+#include "pdf/buildflags.h"
 #include "ppapi/c/ppb_image_data.h"
 #include "ppapi/c/private/ppb_pdf.h"
 #include "ppapi/host/resource_host.h"
 #include "ppapi/proxy/serialized_structs.h"
 #include "ppapi/shared_impl/pdf_accessibility_shared.h"
 
+#if !BUILDFLAG(ENABLE_PDF)
+#error "PDF must be enabled"
+#endif
+
 namespace blink {
 class WebLocalFrame;
 }
diff --git a/components/safe_browsing/content/browser/client_side_detection_host.cc b/components/safe_browsing/content/browser/client_side_detection_host.cc
index 4dcde9fc..eaa10dc 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.cc
+++ b/components/safe_browsing/content/browser/client_side_detection_host.cc
@@ -366,6 +366,13 @@
   // be null if safe browsing service is not available in the embedder.
   ui_manager_ = delegate_->GetSafeBrowsingUIManager();
   database_manager_ = delegate_->GetSafeBrowsingDBManager();
+
+  // We want to accurately track all active RenderFrameHosts, so make sure we
+  // know about any pre-existings ones.
+  for (content::RenderFrameHost* frame : web_contents()->GetAllFrames()) {
+    if (frame->IsRenderFrameCreated())
+      RenderFrameCreated(frame);
+  }
 }
 
 ClientSideDetectionHost::~ClientSideDetectionHost() {
@@ -413,16 +420,17 @@
   classification_request_->Start();
 }
 
-void ClientSideDetectionHost::SetPhishingModel() {
+void ClientSideDetectionHost::SetPhishingModel(
+    const mojo::Remote<mojom::PhishingDetector>& phishing_detector) {
   switch (csd_service_->GetModelType()) {
     case CSDModelType::kNone:
     case CSDModelType::kProtobuf:
-      phishing_detector_->SetPhishingModel(
+      phishing_detector->SetPhishingModel(
           csd_service_->GetModelStr(),
           csd_service_->GetVisualTfLiteModel().Duplicate());
       return;
     case CSDModelType::kFlatbuffer:
-      phishing_detector_->SetPhishingFlatBufferModel(
+      phishing_detector->SetPhishingFlatBufferModel(
           csd_service_->GetModelSharedMemoryRegion(),
           csd_service_->GetVisualTfLiteModel().Duplicate());
       return;
@@ -434,14 +442,8 @@
   if (!web_contents() || web_contents() != tab_ || !csd_service_)
     return;
 
-  for (content::RenderFrameHost* frame : web_contents()->GetAllFrames()) {
-    if (!frame->IsRenderFrameCreated())
-      continue;  // We'd send to this frame on RenderFrameCreated().
-    if (phishing_detector_)
-      phishing_detector_.reset();
-    frame->GetRemoteInterfaces()->GetInterface(
-        phishing_detector_.BindNewPipeAndPassReceiver());
-    SetPhishingModel();
+  for (const auto& frame_and_remote : phishing_detectors_) {
+    SetPhishingModel(frame_and_remote.second);
   }
 }
 
@@ -456,11 +458,19 @@
 
 void ClientSideDetectionHost::RenderFrameCreated(
     content::RenderFrameHost* render_frame_host) {
-  if (phishing_detector_)
-    phishing_detector_.reset();
+  mojo::Remote<mojom::PhishingDetector> new_detector;
   render_frame_host->GetRemoteInterfaces()->GetInterface(
-      phishing_detector_.BindNewPipeAndPassReceiver());
-  SetPhishingModel();
+      new_detector.BindNewPipeAndPassReceiver());
+  new_detector.set_disconnect_handler(
+      base::BindOnce(&ClientSideDetectionHost::RenderFrameDeleted,
+                     weak_factory_.GetWeakPtr(), render_frame_host));
+  phishing_detectors_[render_frame_host] = std::move(new_detector);
+  SetPhishingModel(phishing_detectors_[render_frame_host]);
+}
+
+void ClientSideDetectionHost::RenderFrameDeleted(
+    content::RenderFrameHost* render_frame_host) {
+  phishing_detectors_.erase(render_frame_host);
 }
 
 void ClientSideDetectionHost::OnPhishingPreClassificationDone(
@@ -468,14 +478,24 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (should_classify) {
     content::RenderFrameHost* rfh = web_contents()->GetMainFrame();
-    phishing_detector_.reset();
-    rfh->GetRemoteInterfaces()->GetInterface(
-        phishing_detector_.BindNewPipeAndPassReceiver());
-    phishing_detection_start_time_ = tick_clock_->NowTicks();
-    phishing_detector_->StartPhishingDetection(
-        current_url_,
-        base::BindOnce(&ClientSideDetectionHost::PhishingDetectionDone,
-                       weak_factory_.GetWeakPtr()));
+    auto it = phishing_detectors_.find(rfh);
+    bool remote_valid =
+        (it != phishing_detectors_.end() && it->second.is_connected());
+
+    base::UmaHistogramBoolean("SBClientPhishing.MainFrameRemoteExists",
+                              it != phishing_detectors_.end());
+    if (it != phishing_detectors_.end()) {
+      base::UmaHistogramBoolean("SBClientPhishing.MainFrameRemoteConnected",
+                                it->second.is_connected());
+    }
+
+    if (remote_valid) {
+      phishing_detection_start_time_ = tick_clock_->NowTicks();
+      it->second->StartPhishingDetection(
+          current_url_,
+          base::BindOnce(&ClientSideDetectionHost::PhishingDetectionDone,
+                         weak_factory_.GetWeakPtr()));
+    }
   }
 }
 
diff --git a/components/safe_browsing/content/browser/client_side_detection_host.h b/components/safe_browsing/content/browser/client_side_detection_host.h
index a30ade82..83d92537 100644
--- a/components/safe_browsing/content/browser/client_side_detection_host.h
+++ b/components/safe_browsing/content/browser/client_side_detection_host.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <string>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/safe_browsing/content/browser/base_ui_manager.h"
@@ -100,6 +101,7 @@
   // From content::WebContentsObserver.
   void WebContentsDestroyed() override;
   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
 
   // Used for testing.
   void set_ui_manager(BaseUIManager* ui_manager);
@@ -116,8 +118,8 @@
   // classifiers.
   void OnPhishingPreClassificationDone(bool should_classify);
 
-  // |verdict| is an encoded ClientPhishingRequest protocol message, |result| is
-  // the outcome of the renderer classification.
+  // |verdict| is an encoded ClientPhishingRequest protocol message, |result|
+  // is the outcome of the renderer classification.
   void PhishingDetectionDone(mojom::PhishingDetectorResult result,
                              const std::string& verdict);
 
@@ -156,12 +158,13 @@
     account_signed_in_callback_ = account_signed_in_callback;
   }
 
-  // Check if CSD can get an access Token. Should be enabled only for ESB users,
-  // who are signed in and not in incognito mode.
+  // Check if CSD can get an access Token. Should be enabled only for ESB
+  // users, who are signed in and not in incognito mode.
   bool CanGetAccessToken();
 
   // Set phishing model in PhishingDetector in renderers.
-  void SetPhishingModel();
+  void SetPhishingModel(
+      const mojo::Remote<mojom::PhishingDetector>& phishing_detector);
 
   // Send the client report to CSD server.
   void SendRequest(std::unique_ptr<ClientPhishingRequest> verdict,
@@ -171,7 +174,8 @@
   void OnGotAccessToken(std::unique_ptr<ClientPhishingRequest> verdict,
                         const std::string& access_token);
 
-  // This pointer may be nullptr if client-side phishing detection is disabled.
+  // This pointer may be nullptr if client-side phishing detection is
+  // disabled.
   ClientSideDetectionService* csd_service_;
   // The WebContents that the class is observing.
   content::WebContents* tab_;
@@ -183,8 +187,12 @@
   scoped_refptr<ShouldClassifyUrlRequest> classification_request_;
   // The current URL
   GURL current_url_;
-  // The currently active message pipe to the renderer PhishingDetector.
-  mojo::Remote<mojom::PhishingDetector> phishing_detector_;
+  // A map from the live RenderFrameHosts to their PhishingDetector. These
+  // correspond to the `phishing_detector_receiver_` in the
+  // PhishingClassifierDelegate.
+  base::flat_map<content::RenderFrameHost*,
+                 mojo::Remote<mojom::PhishingDetector>>
+      phishing_detectors_;
 
   // Records the start time of when phishing detection started.
   base::TimeTicks phishing_detection_start_time_;
diff --git a/components/segmentation_platform/components_unittests.filter b/components/segmentation_platform/components_unittests.filter
index b37c36a1..93dad74 100644
--- a/components/segmentation_platform/components_unittests.filter
+++ b/components/segmentation_platform/components_unittests.filter
@@ -1,4 +1,5 @@
 DummyModelExecutionManagerTest.*
+HistogramSignalHandlerTest.*
 MetadataUtilsTest.*
 ModelExecutionManagerFactoryTest.*
 ModelExecutionManagerTest.*
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn
index d4582903..1c7c07f5 100644
--- a/components/segmentation_platform/internal/BUILD.gn
+++ b/components/segmentation_platform/internal/BUILD.gn
@@ -26,7 +26,6 @@
     "database/signal_key.h",
     "database/signal_key_internal.cc",
     "database/signal_key_internal.h",
-    "database/user_action_database.h",
     "execution/dummy_model_execution_manager.cc",
     "execution/dummy_model_execution_manager.h",
     "execution/model_execution_manager.h",
@@ -43,6 +42,8 @@
     "selection/segment_selector_impl.h",
     "selection/segmentation_result_prefs.cc",
     "selection/segmentation_result_prefs.h",
+    "signals/histogram_signal_handler.cc",
+    "signals/histogram_signal_handler.h",
     "signals/signal_filter_processor.cc",
     "signals/signal_filter_processor.h",
     "signals/user_action_signal_handler.cc",
@@ -88,6 +89,8 @@
   # tests in //components/segmentation_platform/components_unittests.filter
   sources = [
     "database/metadata_utils_unittest.cc",
+    "database/mock_signal_database.cc",
+    "database/mock_signal_database.h",
     "database/segment_info_database_unittest.cc",
     "database/signal_database_impl_unittest.cc",
     "database/signal_key_internal_unittest.cc",
@@ -99,6 +102,7 @@
     "scheduler/model_execution_scheduler_unittest.cc",
     "segmentation_platform_service_impl_unittest.cc",
     "selection/segment_selector_unittest.cc",
+    "signals/histogram_signal_handler_unittest.cc",
     "signals/signal_filter_processor_unittest.cc",
     "signals/user_action_signal_handler_unittest.cc",
   ]
diff --git a/components/segmentation_platform/internal/database/mock_signal_database.cc b/components/segmentation_platform/internal/database/mock_signal_database.cc
new file mode 100644
index 0000000..d0091cf
--- /dev/null
+++ b/components/segmentation_platform/internal/database/mock_signal_database.cc
@@ -0,0 +1,13 @@
+// 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 "components/segmentation_platform/internal/database/mock_signal_database.h"
+
+namespace segmentation_platform {
+
+MockSignalDatabase::MockSignalDatabase() = default;
+
+MockSignalDatabase::~MockSignalDatabase() = default;
+
+}  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/database/mock_signal_database.h b/components/segmentation_platform/internal/database/mock_signal_database.h
new file mode 100644
index 0000000..77d2dde9
--- /dev/null
+++ b/components/segmentation_platform/internal/database/mock_signal_database.h
@@ -0,0 +1,51 @@
+// 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 COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
+
+#include "base/callback.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace segmentation_platform {
+
+// A mock of the SignalDatabase.
+class MockSignalDatabase : public SignalDatabase {
+ public:
+  MockSignalDatabase();
+  ~MockSignalDatabase();
+
+  MOCK_METHOD(void, Initialize, (SignalDatabase::SuccessCallback), (override));
+  MOCK_METHOD(void,
+              WriteSample,
+              (SignalType,
+               uint64_t,
+               absl::optional<int32_t>,
+               base::Time,
+               SignalDatabase::SuccessCallback),
+              (override));
+  MOCK_METHOD(void,
+              GetSamples,
+              (SignalType,
+               uint64_t,
+               base::Time,
+               base::Time,
+               SignalDatabase::SampleCallback),
+              (override));
+  MOCK_METHOD(
+      void,
+      DeleteSamples,
+      (SignalType, uint64_t, base::Time, SignalDatabase::SuccessCallback),
+      (override));
+  MOCK_METHOD(
+      void,
+      CompactSamplesForDay,
+      (SignalType, uint64_t, base::Time, SignalDatabase::SuccessCallback),
+      (override));
+};
+
+}  // namespace segmentation_platform
+
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
diff --git a/components/segmentation_platform/internal/database/test_segment_info_database.cc b/components/segmentation_platform/internal/database/test_segment_info_database.cc
index 9e00bf967..c33d7a7 100644
--- a/components/segmentation_platform/internal/database/test_segment_info_database.cc
+++ b/components/segmentation_platform/internal/database/test_segment_info_database.cc
@@ -90,6 +90,18 @@
   feature->set_aggregation(aggregation);
 }
 
+void TestSegmentInfoDatabase::AddHistogramValueFeature(
+    OptimizationTarget segment_id,
+    const std::string& histogram_name) {
+  proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+  proto::SegmentationModelMetadata* metadata = info->mutable_model_metadata();
+  proto::Feature* feature = metadata->add_features();
+  proto::HistogramValueFeature* histogram_value =
+      feature->mutable_histogram_value();
+  histogram_value->set_name(histogram_name);
+  histogram_value->set_name_hash(base::HashMetricName(histogram_name));
+}
+
 void TestSegmentInfoDatabase::AddPredictionResult(OptimizationTarget segment_id,
                                                   float score,
                                                   base::Time timestamp) {
diff --git a/components/segmentation_platform/internal/database/test_segment_info_database.h b/components/segmentation_platform/internal/database/test_segment_info_database.h
index 8578dea..4fc8edd 100644
--- a/components/segmentation_platform/internal/database/test_segment_info_database.h
+++ b/components/segmentation_platform/internal/database/test_segment_info_database.h
@@ -40,6 +40,8 @@
                             const std::string& user_action,
                             int64_t length,
                             proto::Aggregation aggregation);
+  void AddHistogramValueFeature(OptimizationTarget segment_id,
+                                const std::string& histogram);
   void AddPredictionResult(OptimizationTarget segment_id,
                            float score,
                            base::Time timestamp);
diff --git a/components/segmentation_platform/internal/database/user_action_database.h b/components/segmentation_platform/internal/database/user_action_database.h
deleted file mode 100644
index cbeda9c3..0000000
--- a/components/segmentation_platform/internal/database/user_action_database.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_USER_ACTION_DATABASE_H_
-#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_USER_ACTION_DATABASE_H_
-
-#include "base/time/time.h"
-
-namespace segmentation_platform {
-
-// Responsible for storing user action events in a database.
-class UserActionDatabase {
- public:
-  // Called to write user actions to the database. This is a non-blocking write.
-  virtual void WriteUserAction(uint64_t user_action_hash,
-                               base::TimeTicks timestamp) = 0;
-
-  virtual ~UserActionDatabase() = default;
-};
-
-}  // namespace segmentation_platform
-
-#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_USER_ACTION_DATABASE_H_
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
index 14ce24e..bdcfa3d 100644
--- a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
+++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
@@ -14,7 +14,6 @@
 #include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
 #include "components/optimization_guide/proto/models.pb.h"
 #include "components/segmentation_platform/internal/database/test_segment_info_database.h"
-#include "components/segmentation_platform/internal/database/user_action_database.h"
 #include "components/segmentation_platform/internal/execution/model_execution_status.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/segmentation_platform/internal/signals/histogram_signal_handler.cc b/components/segmentation_platform/internal/signals/histogram_signal_handler.cc
new file mode 100644
index 0000000..1cb21bb
--- /dev/null
+++ b/components/segmentation_platform/internal/signals/histogram_signal_handler.cc
@@ -0,0 +1,53 @@
+// 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 "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/time/clock.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+
+namespace segmentation_platform {
+
+HistogramSignalHandler::HistogramSignalHandler(SignalDatabase* signal_database,
+                                               base::Clock* clock)
+    : db_(signal_database), clock_(clock), metrics_enabled_(false) {}
+
+HistogramSignalHandler::~HistogramSignalHandler() = default;
+
+void HistogramSignalHandler::SetRelevantHistograms(
+    const std::set<std::pair<std::string, SignalType>>& histograms) {
+  histogram_observers_.clear();
+  for (const auto& pair : histograms) {
+    const auto& histogram_name = pair.first;
+    SignalType signal_type = pair.second;
+    auto histogram_observer = std::make_unique<
+        base::StatisticsRecorder::ScopedHistogramSampleObserver>(
+        histogram_name,
+        base::BindRepeating(&HistogramSignalHandler::OnHistogramSample,
+                            weak_ptr_factory_.GetWeakPtr(), signal_type));
+    histogram_observers_[histogram_name] = std::move(histogram_observer);
+  }
+}
+
+void HistogramSignalHandler::EnableMetrics(bool enable_metrics) {
+  if (metrics_enabled_ == enable_metrics)
+    return;
+
+  metrics_enabled_ = enable_metrics;
+}
+
+void HistogramSignalHandler::OnHistogramSample(
+    SignalType signal_type,
+    const char* histogram_name,
+    uint64_t name_hash,
+    base::HistogramBase::Sample sample) {
+  if (!metrics_enabled_)
+    return;
+
+  db_->WriteSample(signal_type, name_hash, sample, clock_->Now(),
+                   base::DoNothing());
+}
+
+}  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/histogram_signal_handler.h b/components/segmentation_platform/internal/signals/histogram_signal_handler.h
new file mode 100644
index 0000000..65847bd5
--- /dev/null
+++ b/components/segmentation_platform/internal/signals/histogram_signal_handler.h
@@ -0,0 +1,74 @@
+// 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 COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/statistics_recorder.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+
+namespace base {
+class Clock;
+}  // namespace base
+
+namespace segmentation_platform {
+
+class SignalDatabase;
+
+// Responsible for listening to histogram sample collection events and
+// persisting them to the internal database for future processing.
+class HistogramSignalHandler {
+ public:
+  HistogramSignalHandler(SignalDatabase* signal_database, base::Clock* clock);
+  virtual ~HistogramSignalHandler();
+
+  // Disallow copy/assign.
+  HistogramSignalHandler(const HistogramSignalHandler&) = delete;
+  HistogramSignalHandler& operator=(const HistogramSignalHandler&) = delete;
+
+  // Called to notify about a set of histograms which the segmentation models
+  // care about.
+  virtual void SetRelevantHistograms(
+      const std::set<std::pair<std::string, SignalType>>& histograms);
+
+  // Called to enable or disable metrics collection for segmentation platform.
+  virtual void EnableMetrics(bool enable_metrics);
+
+ private:
+  void OnHistogramSample(SignalType signal_type,
+                         const char* histogram_name,
+                         uint64_t name_hash,
+                         base::HistogramBase::Sample sample);
+
+  // The database storing relevant histogram samples.
+  SignalDatabase* db_;
+
+  // Used for getting current time.
+  base::Clock* clock_;
+
+  // Whether or not the segmentation platform should record metrics events.
+  bool metrics_enabled_;
+
+  // Tracks the histogram names we are currently listening to along with their
+  // corresponding observers.
+  std::map<
+      std::string,
+      std::unique_ptr<base::StatisticsRecorder::ScopedHistogramSampleObserver>>
+      histogram_observers_;
+
+  base::WeakPtrFactory<HistogramSignalHandler> weak_ptr_factory_{this};
+};
+
+}  // namespace segmentation_platform
+
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
diff --git a/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc b/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc
new file mode 100644
index 0000000..3a46fd90
--- /dev/null
+++ b/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc
@@ -0,0 +1,110 @@
+// 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 "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/metrics_hashes.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Eq;
+
+namespace segmentation_platform {
+
+namespace {
+
+constexpr char kExpectedHistogram[] = "some_histogram";
+const uint64_t kExpectedHash = base::HashMetricName(kExpectedHistogram);
+
+}  // namespace
+
+class HistogramSignalHandlerTest : public testing::Test {
+ public:
+  HistogramSignalHandlerTest() = default;
+  ~HistogramSignalHandlerTest() override = default;
+
+  void SetUp() override {
+    signal_database_ = std::make_unique<MockSignalDatabase>();
+    histogram_signal_handler_ = std::make_unique<HistogramSignalHandler>(
+        signal_database_.get(), &test_clock_);
+    test_clock_.SetNow(base::Time::UnixEpoch() + base::TimeDelta::FromHours(8));
+  }
+
+  void SetupHistograms() {
+    std::set<std::pair<std::string, SignalType>> histograms;
+    histograms.insert(
+        std::make_pair(kExpectedHistogram, SignalType::HISTOGRAM_ENUM));
+    histogram_signal_handler_->SetRelevantHistograms(histograms);
+  }
+
+  base::test::TaskEnvironment task_environment_;
+  base::SimpleTestClock test_clock_;
+  std::unique_ptr<MockSignalDatabase> signal_database_;
+  std::unique_ptr<HistogramSignalHandler> histogram_signal_handler_;
+};
+
+TEST_F(HistogramSignalHandlerTest, HistogramsAreRecorded) {
+  // Initialize and register the list of histograms we are listening to.
+  histogram_signal_handler_->EnableMetrics(true);
+  SetupHistograms();
+
+  // Record a registered histogram sample. It should be recorded.
+  EXPECT_CALL(*signal_database_, WriteSample(SignalType::HISTOGRAM_ENUM,
+                                             kExpectedHash, Eq(1), _, _));
+
+  UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+  task_environment_.RunUntilIdle();
+
+  // Record an unrelated histogram sample. It should be ignored.
+  std::string kUnrelatedHistogram = "unrelated_histogram";
+  EXPECT_CALL(
+      *signal_database_,
+      WriteSample(_, base::HashMetricName(kUnrelatedHistogram), _, _, _))
+      .Times(0);
+  UMA_HISTOGRAM_BOOLEAN(kUnrelatedHistogram, true);
+  task_environment_.RunUntilIdle();
+}
+
+TEST_F(HistogramSignalHandlerTest, DisableMetrics) {
+  SetupHistograms();
+
+  // Metrics is disabled on startup.
+  EXPECT_CALL(*signal_database_, WriteSample(SignalType::HISTOGRAM_ENUM,
+                                             kExpectedHash, Eq(1), _, _))
+      .Times(0);
+
+  UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+  task_environment_.RunUntilIdle();
+
+  // Enable metrics.
+  histogram_signal_handler_->EnableMetrics(true);
+  EXPECT_CALL(*signal_database_, WriteSample(SignalType::HISTOGRAM_ENUM,
+                                             kExpectedHash, Eq(1), _, _))
+      .Times(1);
+  UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+  task_environment_.RunUntilIdle();
+
+  // Disable metrics again.
+  histogram_signal_handler_->EnableMetrics(false);
+  EXPECT_CALL(*signal_database_, WriteSample(SignalType::HISTOGRAM_ENUM,
+                                             kExpectedHash, Eq(1), _, _))
+      .Times(0);
+  UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+  task_environment_.RunUntilIdle();
+
+  // Enable metrics again.
+  histogram_signal_handler_->EnableMetrics(true);
+  EXPECT_CALL(*signal_database_, WriteSample(SignalType::HISTOGRAM_ENUM,
+                                             kExpectedHash, Eq(1), _, _))
+      .Times(1);
+  UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+  task_environment_.RunUntilIdle();
+}
+
+}  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.cc b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
index 8c3e61b..4fbd205 100644
--- a/components/segmentation_platform/internal/signals/signal_filter_processor.cc
+++ b/components/segmentation_platform/internal/signals/signal_filter_processor.cc
@@ -7,16 +7,20 @@
 #include <set>
 
 #include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
 #include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
 #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
 
 namespace segmentation_platform {
 
 SignalFilterProcessor::SignalFilterProcessor(
     SegmentInfoDatabase* segment_database,
-    UserActionSignalHandler* user_action_signal_handler)
+    UserActionSignalHandler* user_action_signal_handler,
+    HistogramSignalHandler* histogram_signal_handler)
     : segment_database_(segment_database),
-      user_action_signal_handler_(user_action_signal_handler) {}
+      user_action_signal_handler_(user_action_signal_handler),
+      histogram_signal_handler_(histogram_signal_handler) {}
 
 SignalFilterProcessor::~SignalFilterProcessor() = default;
 
@@ -29,6 +33,7 @@
     std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
         segment_infos) {
   std::set<uint64_t> user_actions;
+  std::set<std::pair<std::string, SignalType>> histograms;
   for (const auto& pair : segment_infos) {
     const proto::SegmentInfo& segment_info = pair.second;
     const auto& metadata = segment_info.model_metadata();
@@ -37,16 +42,33 @@
       if (feature.has_user_action() &&
           feature.user_action().has_user_action_hash()) {
         user_actions.insert(feature.user_action().user_action_hash());
+        continue;
       }
-      // TODO(shaktisahu): Do the same for enum and value histograms.
+
+      if (feature.has_histogram_value() &&
+          feature.histogram_value().has_name()) {
+        histograms.insert(std::make_pair(feature.histogram_value().name(),
+                                         SignalType::HISTOGRAM_VALUE));
+        continue;
+      }
+
+      if (feature.has_histogram_enum() && feature.histogram_enum().has_name()) {
+        histograms.insert(std::make_pair(feature.histogram_enum().name(),
+                                         SignalType::HISTOGRAM_ENUM));
+      }
+
+      // TODO(shaktisahu): We can filter out enum values as an optimization
+      // before storing in DB.
     }
   }
 
-  user_action_signal_handler_->SetRelevantUserActions(user_actions);
+  user_action_signal_handler_->SetRelevantUserActions(std::move(user_actions));
+  histogram_signal_handler_->SetRelevantHistograms(histograms);
 }
 
 void SignalFilterProcessor::EnableMetrics(bool enable_metrics) {
   user_action_signal_handler_->EnableMetrics(enable_metrics);
+  histogram_signal_handler_->EnableMetrics(enable_metrics);
 }
 
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor.h b/components/segmentation_platform/internal/signals/signal_filter_processor.h
index 0aad88b..50c3086 100644
--- a/components/segmentation_platform/internal/signals/signal_filter_processor.h
+++ b/components/segmentation_platform/internal/signals/signal_filter_processor.h
@@ -16,6 +16,7 @@
 class SegmentInfo;
 }  // namespace proto
 
+class HistogramSignalHandler;
 class SegmentInfoDatabase;
 class UserActionSignalHandler;
 
@@ -25,7 +26,8 @@
 class SignalFilterProcessor {
  public:
   SignalFilterProcessor(SegmentInfoDatabase* segment_database,
-                        UserActionSignalHandler* user_action_signal_handler);
+                        UserActionSignalHandler* user_action_signal_handler,
+                        HistogramSignalHandler* histogram_signal_handler);
   ~SignalFilterProcessor();
 
   // Disallow copy/assign.
@@ -48,6 +50,7 @@
 
   SegmentInfoDatabase* segment_database_;
   UserActionSignalHandler* user_action_signal_handler_;
+  HistogramSignalHandler* histogram_signal_handler_;
 
   base::WeakPtrFactory<SignalFilterProcessor> weak_ptr_factory_{this};
 };
diff --git a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
index b4ca71e..0623ccbb 100644
--- a/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
+++ b/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
@@ -8,8 +8,10 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
 #include "components/segmentation_platform/internal/database/test_segment_info_database.h"
 #include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
 #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -22,11 +24,20 @@
 
 class MockUserActionSignalHandler : public UserActionSignalHandler {
  public:
-  MockUserActionSignalHandler() : UserActionSignalHandler(nullptr) {}
+  MockUserActionSignalHandler() : UserActionSignalHandler(nullptr, nullptr) {}
   MOCK_METHOD(void, SetRelevantUserActions, (std::set<uint64_t>));
   MOCK_METHOD(void, EnableMetrics, (bool));
 };
 
+class MockHistogramSignalHandler : public HistogramSignalHandler {
+ public:
+  MockHistogramSignalHandler() : HistogramSignalHandler(nullptr, nullptr) {}
+  using HistogramAndSignalTypeSet =
+      const std::set<std::pair<std::string, SignalType>>&;
+  MOCK_METHOD(void, SetRelevantHistograms, (HistogramAndSignalTypeSet));
+  MOCK_METHOD(void, EnableMetrics, (bool));
+};
+
 class SignalFilterProcessorTest : public testing::Test {
  public:
   SignalFilterProcessorTest() = default;
@@ -38,13 +49,16 @@
     segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
     user_action_signal_handler_ =
         std::make_unique<MockUserActionSignalHandler>();
+    histogram_signal_handler_ = std::make_unique<MockHistogramSignalHandler>();
     signal_filter_processor_ = std::make_unique<SignalFilterProcessor>(
-        segment_database_.get(), user_action_signal_handler_.get());
+        segment_database_.get(), user_action_signal_handler_.get(),
+        histogram_signal_handler_.get());
   }
 
   base::test::TaskEnvironment task_environment_;
   std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
   std::unique_ptr<MockUserActionSignalHandler> user_action_signal_handler_;
+  std::unique_ptr<MockHistogramSignalHandler> histogram_signal_handler_;
   std::unique_ptr<SignalFilterProcessor> signal_filter_processor_;
 };
 
@@ -68,10 +82,33 @@
   ASSERT_THAT(actions, Contains(base::HashMetricName(kUserActionName2)));
 }
 
+TEST_F(SignalFilterProcessorTest, HistogramRegistrationFlow) {
+  std::string kHistogramName1 = "some_histogram_1";
+  segment_database_->AddHistogramValueFeature(
+      OptimizationTarget::OPTIMIZATION_TARGET_PAGE_TOPICS, kHistogramName1);
+  std::string kHistogramName2 = "some_histogram_2";
+  segment_database_->AddHistogramValueFeature(
+      OptimizationTarget::OPTIMIZATION_TARGET_LANGUAGE_DETECTION,
+      kHistogramName2);
+
+  std::set<std::pair<std::string, SignalType>> histograms;
+  EXPECT_CALL(*histogram_signal_handler_, SetRelevantHistograms(_))
+      .Times(1)
+      .WillOnce(SaveArg<0>(&histograms));
+
+  signal_filter_processor_->OnSignalListUpdated();
+  ASSERT_THAT(histograms, Contains(std::make_pair(
+                              kHistogramName1, SignalType::HISTOGRAM_VALUE)));
+  ASSERT_THAT(histograms, Contains(std::make_pair(
+                              kHistogramName2, SignalType::HISTOGRAM_VALUE)));
+}
+
 TEST_F(SignalFilterProcessorTest, EnableMetrics) {
   EXPECT_CALL(*user_action_signal_handler_, EnableMetrics(true));
+  EXPECT_CALL(*histogram_signal_handler_, EnableMetrics(true));
   signal_filter_processor_->EnableMetrics(true);
   EXPECT_CALL(*user_action_signal_handler_, EnableMetrics(false));
+  EXPECT_CALL(*histogram_signal_handler_, EnableMetrics(false));
   signal_filter_processor_->EnableMetrics(false);
 }
 
diff --git a/components/segmentation_platform/internal/signals/user_action_signal_handler.cc b/components/segmentation_platform/internal/signals/user_action_signal_handler.cc
index 0d2e3b4a..54f0600e 100644
--- a/components/segmentation_platform/internal/signals/user_action_signal_handler.cc
+++ b/components/segmentation_platform/internal/signals/user_action_signal_handler.cc
@@ -4,14 +4,18 @@
 
 #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
 
+#include "base/callback_helpers.h"
 #include "base/metrics/metrics_hashes.h"
-#include "components/segmentation_platform/internal/database/user_action_database.h"
+#include "base/time/clock.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
 
 namespace segmentation_platform {
 
 UserActionSignalHandler::UserActionSignalHandler(
-    UserActionDatabase* user_action_database)
-    : db_(user_action_database), metrics_enabled_(false) {
+    SignalDatabase* signal_database,
+    base::Clock* clock)
+    : db_(signal_database), clock_(clock), metrics_enabled_(false) {
   action_callback_ = base::BindRepeating(&UserActionSignalHandler::OnUserAction,
                                          weak_ptr_factory_.GetWeakPtr());
 }
@@ -44,7 +48,8 @@
   if (iter == user_actions_.end())
     return;
 
-  db_->WriteUserAction(user_action_hash, action_time);
+  db_->WriteSample(SignalType::USER_ACTION, user_action_hash, absl::nullopt,
+                   clock_->Now(), base::DoNothing());
 }
 
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/signals/user_action_signal_handler.h b/components/segmentation_platform/internal/signals/user_action_signal_handler.h
index b114c17..6a1baa3 100644
--- a/components/segmentation_platform/internal/signals/user_action_signal_handler.h
+++ b/components/segmentation_platform/internal/signals/user_action_signal_handler.h
@@ -7,21 +7,24 @@
 
 #include <set>
 
-#include "base/bind.h"
-#include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/user_metrics.h"
 #include "base/time/time.h"
 
+namespace base {
+class Clock;
+}  // namespace base
+
 namespace segmentation_platform {
 
-class UserActionDatabase;
+class SignalDatabase;
 
 // Responsible for listening to user action events and persisting it to the
 // internal database for future processing.
 class UserActionSignalHandler {
  public:
-  explicit UserActionSignalHandler(UserActionDatabase* user_action_database);
+  explicit UserActionSignalHandler(SignalDatabase* signal_database,
+                                   base::Clock* clock);
   virtual ~UserActionSignalHandler();
 
   // Disallow copy/assign.
@@ -40,7 +43,10 @@
                     base::TimeTicks action_time);
 
   // The database storing relevant user actions.
-  UserActionDatabase* db_;
+  SignalDatabase* db_;
+
+  // Used for getting current time.
+  base::Clock* clock_;
 
   // The callback registered with user metrics module that gets invoked for
   // every user action.
diff --git a/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc b/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc
index 95bfeb2..4287b01 100644
--- a/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc
+++ b/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc
@@ -5,12 +5,15 @@
 #include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
 
 #include "base/metrics/metrics_hashes.h"
+#include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
-#include "components/segmentation_platform/internal/database/user_action_database.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
+using testing::Eq;
 
 namespace segmentation_platform {
 
@@ -20,12 +23,6 @@
 
 }  // namespace
 
-class MockUserActionDatabase : public UserActionDatabase {
- public:
-  MockUserActionDatabase() = default;
-  MOCK_METHOD(void, WriteUserAction, (uint64_t, base::TimeTicks));
-};
-
 class UserActionSignalHandlerTest : public testing::Test {
  public:
   UserActionSignalHandlerTest() = default;
@@ -34,9 +31,10 @@
   void SetUp() override {
     base::SetRecordActionTaskRunner(
         task_environment_.GetMainThreadTaskRunner());
-    user_action_database_ = std::make_unique<MockUserActionDatabase>();
-    user_action_signal_handler_ =
-        std::make_unique<UserActionSignalHandler>(user_action_database_.get());
+    signal_database_ = std::make_unique<MockSignalDatabase>();
+    user_action_signal_handler_ = std::make_unique<UserActionSignalHandler>(
+        signal_database_.get(), &test_clock_);
+    test_clock_.SetNow(base::Time::UnixEpoch() + base::TimeDelta::FromHours(8));
   }
 
   void SetupUserActions() {
@@ -46,28 +44,30 @@
   }
 
   base::test::TaskEnvironment task_environment_;
-  std::unique_ptr<MockUserActionDatabase> user_action_database_;
+  base::SimpleTestClock test_clock_;
+  std::unique_ptr<MockSignalDatabase> signal_database_;
   std::unique_ptr<UserActionSignalHandler> user_action_signal_handler_;
 };
 
 TEST_F(UserActionSignalHandlerTest, UserActionsAreRecorded) {
-  base::TimeTicks time = base::TimeTicks::Now();
-
   // Initialize and register the list of user actions we are listening to.
   user_action_signal_handler_->EnableMetrics(true);
   SetupUserActions();
 
   // Fire a registered user action. It should be recorded.
-  EXPECT_CALL(*user_action_database_, WriteUserAction(kExpectedHash, time));
-  // user_action_signal_handler_->EnableMetrics(true);
-  base::RecordComputedActionAt(kExpectedUserAction, time);
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION, kExpectedHash,
+                          Eq(absl::nullopt), test_clock_.Now(), _));
+  base::RecordComputedActionAt(kExpectedUserAction, base::TimeTicks::Now());
 
   // Fire an unrelated user action. It should be ignored.
   std::string kUnrelatedUserAction = "unrelated_event";
-  EXPECT_CALL(*user_action_database_,
-              WriteUserAction(base::HashMetricName(kUnrelatedUserAction), time))
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION,
+                          base::HashMetricName(kUnrelatedUserAction),
+                          Eq(absl::nullopt), test_clock_.Now(), _))
       .Times(0);
-  base::RecordComputedActionAt(kUnrelatedUserAction, time);
+  base::RecordComputedActionAt(kUnrelatedUserAction, base::TimeTicks::Now());
 }
 
 TEST_F(UserActionSignalHandlerTest, DisableMetrics) {
@@ -75,29 +75,37 @@
   SetupUserActions();
 
   // Metrics is disabled on startup.
-  EXPECT_CALL(*user_action_database_,
-              WriteUserAction(base::HashMetricName(kExpectedUserAction), time))
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION,
+                          base::HashMetricName(kExpectedUserAction),
+                          Eq(absl::nullopt), _, _))
       .Times(0);
   base::RecordComputedActionAt(kExpectedUserAction, time);
 
   // Enable metrics.
   user_action_signal_handler_->EnableMetrics(true);
-  EXPECT_CALL(*user_action_database_,
-              WriteUserAction(base::HashMetricName(kExpectedUserAction), time))
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION,
+                          base::HashMetricName(kExpectedUserAction),
+                          Eq(absl::nullopt), _, _))
       .Times(1);
   base::RecordComputedActionAt(kExpectedUserAction, time);
 
   // Disable metrics again.
   user_action_signal_handler_->EnableMetrics(false);
-  EXPECT_CALL(*user_action_database_,
-              WriteUserAction(base::HashMetricName(kExpectedUserAction), time))
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION,
+                          base::HashMetricName(kExpectedUserAction),
+                          Eq(absl::nullopt), _, _))
       .Times(0);
   base::RecordComputedActionAt(kExpectedUserAction, time);
 
   // Enable metrics again.
   user_action_signal_handler_->EnableMetrics(true);
-  EXPECT_CALL(*user_action_database_,
-              WriteUserAction(base::HashMetricName(kExpectedUserAction), time))
+  EXPECT_CALL(*signal_database_,
+              WriteSample(SignalType::USER_ACTION,
+                          base::HashMetricName(kExpectedUserAction),
+                          Eq(absl::nullopt), _, _))
       .Times(1);
   base::RecordComputedActionAt(kExpectedUserAction, time);
 }
diff --git a/components/test/data/payments/paulpay.com/README.md b/components/test/data/payments/paulpay.com/README.md
new file mode 100644
index 0000000..1e5755e
--- /dev/null
+++ b/components/test/data/payments/paulpay.com/README.md
@@ -0,0 +1,2 @@
+Just-in-time installable payment handler that's missing a service worker JS
+file, which causes the just-in-time install to fail.
diff --git a/components/test/data/payments/paulpay.com/pay b/components/test/data/payments/paulpay.com/pay
new file mode 100644
index 0000000..9f7865c
--- /dev/null
+++ b/components/test/data/payments/paulpay.com/pay
@@ -0,0 +1,12 @@
+{
+  "default_applications": ["pay"],
+  "name": "Paul Pay",
+  "icons": [{
+    "src": "../icon.png",
+    "sizes": "40x40",
+    "type": "image/png"
+  }],
+  "serviceworker": {
+    "src": "app.js"
+  }
+}
diff --git a/components/webapps/browser/installable/installable_manager.cc b/components/webapps/browser/installable/installable_manager.cc
index 7c8e559f..6d6a4b97 100644
--- a/components/webapps/browser/installable/installable_manager.cc
+++ b/components/webapps/browser/installable/installable_manager.cc
@@ -22,6 +22,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/manifest_icon_downloader.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/page.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_features.h"
@@ -624,7 +625,9 @@
   content::WebContents* web_contents = GetWebContents();
   DCHECK(web_contents);
 
-  web_contents->GetManifest(base::BindOnce(
+  // This uses DidFinishNavigation to abort when the primary page changes.
+  // Therefore this should always be the correct page.
+  web_contents->GetMainFrame()->GetPage().GetManifest(base::BindOnce(
       &InstallableManager::OnDidGetManifest, weak_factory_.GetWeakPtr()));
 }
 
diff --git a/content/browser/bluetooth/web_bluetooth_pairing_manager.cc b/content/browser/bluetooth/web_bluetooth_pairing_manager.cc
index de857c7..119280b2 100644
--- a/content/browser/bluetooth/web_bluetooth_pairing_manager.cc
+++ b/content/browser/bluetooth/web_bluetooth_pairing_manager.cc
@@ -27,7 +27,12 @@
   DCHECK(pairing_manager_delegate_);
 }
 
-WebBluetoothPairingManager::~WebBluetoothPairingManager() = default;
+WebBluetoothPairingManager::~WebBluetoothPairingManager() {
+  auto pending_pair_device_ids = std::move(pending_pair_device_ids_);
+  for (const auto& device_id : pending_pair_device_ids) {
+    pairing_manager_delegate_->CancelPairing(device_id);
+  }
+}
 
 void WebBluetoothPairingManager::PairForCharacteristicReadValue(
     const std::string& characteristic_instance_id,
@@ -44,31 +49,48 @@
     return;
   }
 
+  if (pending_pair_device_ids_.contains(device_id)) {
+    // This implementation could be more sophisticated by joining the outcome
+    // of this operation with the existing pairing operation. This is expected
+    // to be an unlikely event, so for now just ensure that there is only ever
+    // one pairing operation for a device at a time.
+    std::move(read_callback)
+        .Run(WebBluetoothServiceImpl::TranslateConnectErrorAndRecord(
+                 BluetoothDevice::ConnectErrorCode::ERROR_AUTH_CANCELED),
+             /*value=*/absl::nullopt);
+    return;
+  }
+
+  pending_pair_device_ids_.insert(device_id);
   auto split_read_callback = base::SplitOnceCallback(std::move(read_callback));
   pairing_manager_delegate_->PairDevice(
       device_id, this,
       base::BindOnce(
           &WebBluetoothPairingManager::OnReadCharacteristicValuePairSuccess,
-          weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id,
+          weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, device_id,
           std::move(split_read_callback.first)),
       base::BindOnce(
           &WebBluetoothPairingManager::OnReadCharacteristicValuePairFailure,
-          weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id,
+          weak_ptr_factory_.GetWeakPtr(), characteristic_instance_id, device_id,
           num_pair_attempts + 1, std::move(split_read_callback.second)));
 }
 
 void WebBluetoothPairingManager::OnReadCharacteristicValuePairSuccess(
     std::string characteristic_instance_id,
+    blink::WebBluetoothDeviceId device_id,
     WebBluetoothService::RemoteCharacteristicReadValueCallback read_callback) {
+  pending_pair_device_ids_.erase(device_id);
   pairing_manager_delegate_->RemoteCharacteristicReadValue(
       characteristic_instance_id, std::move(read_callback));
 }
 
 void WebBluetoothPairingManager::OnReadCharacteristicValuePairFailure(
     std::string characteristic_instance_id,
+    blink::WebBluetoothDeviceId device_id,
     int num_pair_attempts,
     WebBluetoothService::RemoteCharacteristicReadValueCallback read_callback,
     BluetoothDevice::ConnectErrorCode error_code) {
+  pending_pair_device_ids_.erase(device_id);
   if (error_code == BluetoothDevice::ConnectErrorCode::ERROR_AUTH_REJECTED &&
       num_pair_attempts < kMaxPairAttempts) {
     PairForCharacteristicReadValue(characteristic_instance_id,
diff --git a/content/browser/bluetooth/web_bluetooth_pairing_manager.h b/content/browser/bluetooth/web_bluetooth_pairing_manager.h
index beb137e..9474089 100644
--- a/content/browser/bluetooth/web_bluetooth_pairing_manager.h
+++ b/content/browser/bluetooth/web_bluetooth_pairing_manager.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/containers/flat_set.h"
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
 #include "device/bluetooth/bluetooth_device.h"
@@ -49,11 +50,13 @@
  private:
   void OnReadCharacteristicValuePairSuccess(
       std::string characteristic_instance_id,
+      blink::WebBluetoothDeviceId device_id,
       blink::mojom::WebBluetoothService::RemoteCharacteristicReadValueCallback
           read_callback);
 
   void OnReadCharacteristicValuePairFailure(
       std::string characteristic_instance_id,
+      blink::WebBluetoothDeviceId device_id,
       int num_pair_attempts,
       blink::mojom::WebBluetoothService::RemoteCharacteristicReadValueCallback
           read_callback,
@@ -71,6 +74,9 @@
                       uint32_t passkey) override;
   void AuthorizePairing(device::BluetoothDevice* device) override;
 
+  // The device IDs currently in the pairing process.
+  base::flat_set<blink::WebBluetoothDeviceId> pending_pair_device_ids_;
+
   // The purpose of WebBluetoothPairingManagerDelegate is to support
   // this class. Currently the WebBluetoothPairingManagerDelegate implementation
   // also owns this class (and thus will outlive it). The contract is that
diff --git a/content/browser/bluetooth/web_bluetooth_pairing_manager_delegate.h b/content/browser/bluetooth/web_bluetooth_pairing_manager_delegate.h
index 29b964c8..11f7a88 100644
--- a/content/browser/bluetooth/web_bluetooth_pairing_manager_delegate.h
+++ b/content/browser/bluetooth/web_bluetooth_pairing_manager_delegate.h
@@ -33,6 +33,10 @@
       base::OnceClosure callback,
       device::BluetoothDevice::ConnectErrorCallback error_callback) = 0;
 
+  // Cancels a pairing attempt to a remote device, clearing its reference to
+  // the pairing delegate.
+  virtual void CancelPairing(const blink::WebBluetoothDeviceId& device_id) = 0;
+
   // Reads the value for the characteristic identified by
   // |characteristic_instance_id|. If the value is successfully read the
   // callback will be run with WebBluetoothResult::SUCCESS and the
diff --git a/content/browser/bluetooth/web_bluetooth_pairing_manager_unittest.cc b/content/browser/bluetooth/web_bluetooth_pairing_manager_unittest.cc
index 438278a4..c433165 100644
--- a/content/browser/bluetooth/web_bluetooth_pairing_manager_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_pairing_manager_unittest.cc
@@ -35,11 +35,14 @@
     kSucceedFirst,   // Successfully authenticate on first pair attempt.
     kSucceedSecond,  // Successfully authenticate on second pair attempt.
     kFailAll,        // Fail authentication on all pair attempts.
+    kSuspend,        // Suspend in-progress authentication.
+    kFirstSuspend,   // First auth is suspended, following will succeed.
     kUnspecified,    // Initial (error) behavior.
   };
 
   BluetoothPairingManagerTest()
-      : valid_device_id(kValidDeviceID), pairing_manager_(this) {}
+      : valid_device_id(kValidDeviceID),
+        pairing_manager_(std::make_unique<WebBluetoothPairingManager>(this)) {}
   ~BluetoothPairingManagerTest() override = default;
 
   void SetUp() override {}
@@ -57,6 +60,7 @@
       base::OnceClosure callback,
       BluetoothDevice::ConnectErrorCallback error_callback) override {
     ASSERT_TRUE(device_id.IsValid());
+    EXPECT_EQ(device_id, valid_device_id);
     num_pair_attempts_++;
 
     switch (auth_behavior_) {
@@ -82,12 +86,44 @@
       case AuthBehavior::kFailAll:
         std::move(error_callback).Run(BluetoothDevice::ERROR_AUTH_REJECTED);
         break;
+      case AuthBehavior::kSuspend:
+        EXPECT_TRUE(pair_callback_.is_null());
+        EXPECT_TRUE(pair_error_callback_.is_null());
+        pair_callback_ = std::move(callback);
+        pair_error_callback_ = std::move(error_callback);
+        break;
+      case AuthBehavior::kFirstSuspend:
+        if (num_pair_attempts_ == 1) {
+          EXPECT_TRUE(pair_callback_.is_null());
+          EXPECT_TRUE(pair_error_callback_.is_null());
+          pair_callback_ = std::move(callback);
+          pair_error_callback_ = std::move(error_callback);
+        } else {
+          device_paired_ = true;
+          std::move(callback).Run();
+        }
+        break;
       case AuthBehavior::kUnspecified:
         NOTREACHED() << "Test must set auth behavior";
         break;
     }
   }
 
+  void CancelPairing(const WebBluetoothDeviceId& device_id) override {
+    ASSERT_TRUE(device_id.IsValid());
+    EXPECT_EQ(device_id, valid_device_id);
+    pair_callback_.Reset();
+    EXPECT_FALSE(pair_error_callback_.is_null());
+    std::move(pair_error_callback_).Run(BluetoothDevice::ERROR_AUTH_CANCELED);
+  }
+
+  void ResumeSuspendedPairingWithSuccess() {
+    device_paired_ = true;
+    pair_error_callback_.Reset();
+    EXPECT_FALSE(pair_callback_.is_null());
+    std::move(pair_callback_).Run();
+  }
+
   void RemoteCharacteristicReadValue(
       const std::string& characteristic_instance_id,
       WebBluetoothService::RemoteCharacteristicReadValueCallback callback)
@@ -120,17 +156,23 @@
 
   int num_pair_attempts() const { return num_pair_attempts_; }
 
-  WebBluetoothPairingManager& pairing_manager() { return pairing_manager_; }
+  void DeletePairingManager() { pairing_manager_.reset(); }
+
+  WebBluetoothPairingManager* pairing_manager() {
+    return pairing_manager_.get();
+  }
 
  private:
   int num_pair_attempts_ = 0;
   bool device_paired_ = false;
+  base::OnceClosure pair_callback_;
+  BluetoothDevice::ConnectErrorCallback pair_error_callback_;
   AuthBehavior auth_behavior_ = AuthBehavior::kUnspecified;
   const std::string characteristic_instance_id_ = {"valid-id-for-tesing"};
   const std::string invalid_characteristic_instance_id_ = {"invalid-id"};
   const WebBluetoothDeviceId valid_device_id;
   const WebBluetoothDeviceId invalid_device_id;
-  WebBluetoothPairingManager pairing_manager_;
+  std::unique_ptr<WebBluetoothPairingManager> pairing_manager_;
 };
 
 TEST_F(BluetoothPairingManagerTest, ReadSuccessfulAuthFirstSuccess) {
@@ -138,7 +180,7 @@
   SetAuthBehavior(AuthBehavior::kSucceedFirst);
 
   base::RunLoop loop;
-  pairing_manager().PairForCharacteristicReadValue(
+  pairing_manager()->PairForCharacteristicReadValue(
       characteristic_instance_id(), kStartingPairAttemptCount,
       base::BindLambdaForTesting(
           [&loop](WebBluetoothResult result,
@@ -157,7 +199,7 @@
   SetAuthBehavior(AuthBehavior::kSucceedSecond);
 
   base::RunLoop loop;
-  pairing_manager().PairForCharacteristicReadValue(
+  pairing_manager()->PairForCharacteristicReadValue(
       characteristic_instance_id(), kStartingPairAttemptCount,
       base::BindLambdaForTesting(
           [&loop](WebBluetoothResult result,
@@ -176,7 +218,7 @@
   SetAuthBehavior(AuthBehavior::kFailAll);
 
   base::RunLoop loop;
-  pairing_manager().PairForCharacteristicReadValue(
+  pairing_manager()->PairForCharacteristicReadValue(
       characteristic_instance_id(), kStartingPairAttemptCount,
       base::BindLambdaForTesting(
           [&loop](WebBluetoothResult result,
@@ -194,7 +236,7 @@
   SetAuthBehavior(AuthBehavior::kFailAll);
 
   base::RunLoop loop;
-  pairing_manager().PairForCharacteristicReadValue(
+  pairing_manager()->PairForCharacteristicReadValue(
       invalid_characteristic_instance_id(), kStartingPairAttemptCount,
       base::BindLambdaForTesting(
           [&loop](WebBluetoothResult result,
@@ -207,4 +249,62 @@
   EXPECT_EQ(0, num_pair_attempts());
 }
 
+TEST_F(BluetoothPairingManagerTest, ReadCharacteristicDeleteDelegate) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  SetAuthBehavior(AuthBehavior::kSuspend);
+
+  base::RunLoop loop;
+  pairing_manager()->PairForCharacteristicReadValue(
+      characteristic_instance_id(), kStartingPairAttemptCount,
+      base::BindLambdaForTesting(
+          [&loop](WebBluetoothResult result,
+                  const absl::optional<std::vector<uint8_t>>& value) {
+            EXPECT_EQ(WebBluetoothResult::CONNECT_AUTH_CANCELED, result);
+            loop.Quit();
+          }));
+
+  // Deleting the pairing manager will cancel all pending device pairing
+  // operations. Test this is true.
+  DeletePairingManager();
+  loop.Run();
+  EXPECT_EQ(1, num_pair_attempts());
+}
+
+TEST_F(BluetoothPairingManagerTest, ReadCharacteristicDoublePair) {
+  base::test::SingleThreadTaskEnvironment task_environment;
+  SetAuthBehavior(AuthBehavior::kFirstSuspend);
+
+  int callback_count = 0;
+  base::RunLoop loop;
+  pairing_manager()->PairForCharacteristicReadValue(
+      characteristic_instance_id(), kStartingPairAttemptCount,
+      base::BindLambdaForTesting(
+          [&loop, &callback_count](
+              WebBluetoothResult result,
+              const absl::optional<std::vector<uint8_t>>& value) {
+            EXPECT_EQ(WebBluetoothResult::SUCCESS, result);
+            EXPECT_EQ(value, kTestValue) << "Incorrect characteristic value";
+            if (++callback_count == 2)
+              loop.Quit();
+          }));
+
+  // Now try to pair for reading a second time. This should fail due to an
+  // in-progress pairing.
+  pairing_manager()->PairForCharacteristicReadValue(
+      characteristic_instance_id(), kStartingPairAttemptCount,
+      base::BindLambdaForTesting(
+          [&loop, &callback_count](
+              WebBluetoothResult result,
+              const absl::optional<std::vector<uint8_t>>& value) {
+            EXPECT_EQ(WebBluetoothResult::CONNECT_AUTH_CANCELED, result);
+            if (++callback_count == 2)
+              loop.Quit();
+          }));
+
+  ResumeSuspendedPairingWithSuccess();
+  loop.Run();
+
+  EXPECT_EQ(1, num_pair_attempts()) << "Only the first operation should pair";
+}
+
 }  // namespace content
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 9921e3b..223f47c9 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -2346,6 +2346,16 @@
   return device_id;
 }
 
+BluetoothDevice* WebBluetoothServiceImpl::GetCachedDevice(
+    const blink::WebBluetoothDeviceId& device_id) {
+  DCHECK(device_id.IsValid());
+  CacheQueryResult query_result = QueryCacheForDevice(device_id);
+  if (query_result.outcome != CacheQueryOutcome::SUCCESS)
+    return nullptr;
+
+  return query_result.device;
+}
+
 void WebBluetoothServiceImpl::PairDevice(
     const blink::WebBluetoothDeviceId& device_id,
     BluetoothDevice::PairingDelegate* pairing_delegate,
@@ -2357,14 +2367,7 @@
     return;
   }
 
-  CacheQueryResult query_result = QueryCacheForDevice(device_id);
-  if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
-    std::move(error_callback)
-        .Run(BluetoothDevice::ConnectErrorCode::ERROR_UNKNOWN);
-    return;
-  }
-
-  BluetoothDevice* device = query_result.device;
+  BluetoothDevice* device = GetCachedDevice(device_id);
   if (!device) {
     std::move(error_callback)
         .Run(BluetoothDevice::ConnectErrorCode::ERROR_UNKNOWN);
@@ -2377,4 +2380,15 @@
                std::move(error_callback));
 }
 
+void WebBluetoothServiceImpl::CancelPairing(
+    const blink::WebBluetoothDeviceId& device_id) {
+  DCHECK(device_id.IsValid());
+
+  BluetoothDevice* device = GetCachedDevice(device_id);
+  if (!device)
+    return;
+
+  device->CancelPairing();
+}
+
 }  // namespace content
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index 5517212..d3fd1ef 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -355,6 +355,10 @@
   CacheQueryResult QueryCacheForDevice(
       const blink::WebBluetoothDeviceId& device_id);
 
+  // Return the cached BluetoothDevice for the given |device_id|.
+  device::BluetoothDevice* GetCachedDevice(
+      const blink::WebBluetoothDeviceId& device_id);
+
   // Queries the platform cache for a Service with |service_instance_id|. Fills
   // in the |outcome| field, and |device| and |service| fields if successful.
   CacheQueryResult QueryCacheForService(const std::string& service_instance_id);
@@ -408,6 +412,7 @@
       device::BluetoothDevice::PairingDelegate* pairing_delegate,
       base::OnceClosure callback,
       device::BluetoothDevice::ConnectErrorCallback error_callback) override;
+  void CancelPairing(const blink::WebBluetoothDeviceId& device_id) override;
 
   // Used to open a BluetoothChooser and start a device discovery session.
   std::unique_ptr<BluetoothDeviceChooserController> device_chooser_controller_;
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index f9027332..9a83620 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -85,11 +85,6 @@
     observer.BrowserChildProcessLaunchedAndConnected(data);
 }
 
-void NotifyProcessHostConnected(const ChildProcessData& data) {
-  for (auto& observer : g_browser_child_process_observers.Get())
-    observer.BrowserChildProcessHostConnected(data);
-}
-
 void NotifyProcessHostDisconnected(const ChildProcessData& data) {
   for (auto& observer : g_browser_child_process_observers.Get())
     observer.BrowserChildProcessHostDisconnected(data);
@@ -203,11 +198,7 @@
     content::ProcessType process_type,
     BrowserChildProcessHostDelegate* delegate,
     ChildProcessHost::IpcMode ipc_mode)
-    : data_(process_type),
-      delegate_(delegate),
-      channel_(nullptr),
-      is_channel_connected_(false),
-      notify_child_disconnected_(false) {
+    : data_(process_type), delegate_(delegate) {
   DCHECK_CURRENTLY_ON(base::FeatureList::IsEnabled(features::kProcessHostOnUI)
                           ? BrowserThread::UI
                           : BrowserThread::IO);
@@ -226,7 +217,7 @@
 BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
   g_child_process_list.Get().remove(this);
 
-  if (notify_child_disconnected_) {
+  if (notify_child_connection_status_) {
     GetUIThreadTaskRunner({})->PostTask(
         FROM_HERE,
         base::BindOnce(&NotifyProcessHostDisconnected, data_.Duplicate()));
@@ -300,11 +291,7 @@
   DCHECK_CURRENTLY_ON(base::FeatureList::IsEnabled(features::kProcessHostOnUI)
                           ? BrowserThread::UI
                           : BrowserThread::IO);
-  DCHECK(child_process_.get())
-      << "Requesting a child process handle before launching.";
-  DCHECK(child_process_->GetProcess().IsValid())
-      << "Requesting a child process handle before launch has completed OK.";
-  return child_process_->GetProcess();
+  return data_.GetProcess();
 }
 
 std::unique_ptr<base::PersistentMemoryAllocator>
@@ -380,7 +367,11 @@
 
   data_.sandbox_type = delegate->GetSandboxType();
 
-  notify_child_disconnected_ = true;
+  // Note that if this host has a legacy IPC Channel, we don't dispatch any
+  // connection status notifications until we observe OnChannelConnected().
+  if (!has_legacy_ipc_channel_)
+    notify_child_connection_status_ = true;
+
   child_process_ = std::make_unique<ChildProcessLauncher>(
       std::move(delegate), std::move(cmd_line), data_.id, this,
       std::move(*child_process_host_->GetMojoInvitation()),
@@ -389,6 +380,9 @@
                           base::ThreadTaskRunnerHandle::Get()),
       std::move(files_to_preload), terminate_on_shutdown);
   ShareMetricsAllocatorToProcess();
+
+  if (!has_legacy_ipc_channel_)
+    OnProcessConnected();
 }
 
 void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
@@ -434,27 +428,21 @@
                           ? BrowserThread::UI
                           : BrowserThread::IO);
 
-  is_channel_connected_ = true;
-  notify_child_disconnected_ = true;
-
-#if defined(OS_MAC)
-  ChildProcessTaskPortProvider::GetInstance()->OnChildProcessLaunched(
-      peer_pid, static_cast<ChildProcessHostImpl*>(child_process_host_.get())
-                    ->child_process());
-#endif
-
-#if defined(OS_WIN)
-  // From this point onward, the exit of the child process is detected by an
-  // error on the IPC channel.
-  early_exit_watcher_.StopWatching();
-#endif
-
-  GetUIThreadTaskRunner({})->PostTask(
-      FROM_HERE,
-      base::BindOnce(&NotifyProcessHostConnected, data_.Duplicate()));
+  DCHECK(has_legacy_ipc_channel_);
+  notify_child_connection_status_ = true;
 
   delegate_->OnChannelConnected(peer_pid);
 
+  OnProcessConnected();
+}
+
+void BrowserChildProcessHostImpl::OnProcessConnected() {
+#if defined(OS_WIN)
+  // From this point onward, the exit of the child process is detected by an
+  // error on the IPC channel or ChildProcessHost pipe.
+  early_exit_watcher_.StopWatching();
+#endif
+
   if (IsProcessLaunched()) {
     GetUIThreadTaskRunner({})->PostTask(
         FROM_HERE,
@@ -489,7 +477,11 @@
 }
 
 void BrowserChildProcessHostImpl::OnChannelInitialized(IPC::Channel* channel) {
-  channel_ = channel;
+  has_legacy_ipc_channel_ = true;
+
+  // When using a legacy IPC Channel, we defer any notifications until the
+  // Channel handshake is complete. See OnChannelConnected().
+  notify_child_connection_status_ = false;
 }
 
 void BrowserChildProcessHostImpl::OnChildDisconnected() {
@@ -504,7 +496,8 @@
   // early exit watcher so GetTerminationStatus can close the process handle.
   early_exit_watcher_.StopWatching();
 #endif
-  if (child_process_.get() || data_.GetProcess().IsValid()) {
+  const base::Process& process = data_.GetProcess();
+  if (child_process_.get() || (process.IsValid() && !process.is_current())) {
     ChildProcessTerminationInfo info =
         GetTerminationInfo(true /* known_dead */);
 #if defined(OS_ANDROID)
@@ -564,11 +557,11 @@
     }
 #endif
   }
-  channel_ = nullptr;
   delete delegate_;  // Will delete us
 }
 
 bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
+  DCHECK(has_legacy_ipc_channel_);
   return child_process_host_->Send(message);
 }
 
@@ -646,7 +639,7 @@
 
 void BrowserChildProcessHostImpl::OnProcessLaunchFailed(int error_code) {
   delegate_->OnProcessLaunchFailed(error_code);
-  notify_child_disconnected_ = false;
+  notify_child_connection_status_ = false;
   delete delegate_;  // Will delete us
 }
 
@@ -664,6 +657,13 @@
   const base::Process& process = child_process_->GetProcess();
   DCHECK(process.IsValid());
 
+#if defined(OS_MAC)
+  ChildProcessTaskPortProvider::GetInstance()->OnChildProcessLaunched(
+      process.Pid(),
+      static_cast<ChildProcessHostImpl*>(child_process_host_.get())
+          ->child_process());
+#endif
+
 #if defined(OS_WIN)
   // Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
   // child process exits. This watcher is stopped once the IPC channel is
@@ -676,7 +676,7 @@
   data_.SetProcess(process.Duplicate());
   delegate_->OnProcessLaunched();
 
-  if (is_channel_connected_) {
+  if (notify_child_connection_status_) {
     GetUIThreadTaskRunner({})->PostTask(
         FROM_HERE,
         base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
diff --git a/content/browser/browser_child_process_host_impl.h b/content/browser/browser_child_process_host_impl.h
index 35fc5f7..24cfc859 100644
--- a/content/browser/browser_child_process_host_impl.h
+++ b/content/browser/browser_child_process_host_impl.h
@@ -151,6 +151,8 @@
   friend class BrowserChildProcessHostIterator;
   friend class BrowserChildProcessObserver;
 
+  void OnProcessConnected();
+
   static BrowserChildProcessList* GetIterator();
 
   static void AddObserver(BrowserChildProcessObserver* observer);
@@ -218,9 +220,8 @@
   // transferred to the child process.
   base::WritableSharedMemoryRegion metrics_shared_region_;
 
-  IPC::Channel* channel_ = nullptr;
-  bool is_channel_connected_;
-  bool notify_child_disconnected_;
+  bool has_legacy_ipc_channel_ = false;
+  bool notify_child_connection_status_ = true;
 
 #if defined(OS_ANDROID)
   // whether the child process can use pre-warmed up connection for better
diff --git a/content/browser/browser_process_io_thread.cc b/content/browser/browser_process_io_thread.cc
index bd264fb..1ea28e4 100644
--- a/content/browser/browser_process_io_thread.cc
+++ b/content/browser/browser_process_io_thread.cc
@@ -162,7 +162,7 @@
 
       ChildProcessHostImpl* child_process =
           static_cast<ChildProcessHostImpl*>(it.GetHost());
-      auto& process = child_process->peer_process();
+      auto& process = child_process->GetPeerProcess();
       if (!process.IsValid())
         continue;
       base::ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives;
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 262633b..b0e93e7 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -746,12 +746,6 @@
   }
 #endif
 
-  // In case we never started, clean up.
-  while (!queued_messages_.empty()) {
-    delete queued_messages_.front();
-    queued_messages_.pop();
-  }
-
   // This is only called on the IO thread so no race against the constructor
   // for another GpuProcessHost.
   if (g_gpu_process_hosts[kind_] == this)
@@ -864,8 +858,6 @@
 
   TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD);
 
-  process_->GetHost()->CreateChannelMojo();
-
   mode_ = GpuDataManagerImpl::GetInstance()->GetGpuMode();
 
   if (in_process_) {
@@ -931,37 +923,6 @@
   return true;
 }
 
-bool GpuProcessHost::Send(IPC::Message* msg) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (process_->GetHost()->IsChannelOpening()) {
-    queued_messages_.push(msg);
-    return true;
-  }
-
-  bool result = process_->Send(msg);
-  if (!result) {
-    // Channel is hosed, but we may not get destroyed for a while. Send
-    // outstanding channel creation failures now so that the caller can restart
-    // with a new process/channel without waiting.
-    SendOutstandingReplies();
-  }
-  return result;
-}
-
-bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return true;
-}
-
-void GpuProcessHost::OnChannelConnected(int32_t peer_pid) {
-  TRACE_EVENT0("gpu", "GpuProcessHost::OnChannelConnected");
-
-  while (!queued_messages_.empty()) {
-    Send(queued_messages_.front());
-    queued_messages_.pop();
-  }
-}
-
 void GpuProcessHost::OnProcessLaunched() {
   UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
                       base::TimeTicks::Now() - init_start_time_);
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index 99ff97a..8c107d0 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -14,7 +14,6 @@
 
 #include "base/atomicops.h"
 #include "base/callback.h"
-#include "base/containers/queue.h"
 #include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/weak_ptr.h"
@@ -31,8 +30,6 @@
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_info.h"
 #include "gpu/config/gpu_mode.h"
-#include "gpu/ipc/common/surface_handle.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
@@ -62,7 +59,6 @@
 #endif
 
 class GpuProcessHost : public BrowserChildProcessHostDelegate,
-                       public IPC::Sender,
                        public viz::GpuHostImpl::Delegate {
  public:
   static int GetGpuCrashCount();
@@ -95,9 +91,6 @@
   int host_id() const { return host_id_; }
   base::ProcessId process_id() const { return process_id_; }
 
-  // IPC::Sender implementation.
-  bool Send(IPC::Message* msg) override;
-
   // What kind of GPU process, e.g. sandboxed or unsandboxed.
   GpuProcessKind kind();
 
@@ -144,8 +137,6 @@
   bool Init();
 
   // BrowserChildProcessHostDelegate implementation.
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void OnChannelConnected(int32_t peer_pid) override;
   void OnProcessLaunched() override;
   void OnProcessLaunchFailed(int error_code) override;
   void OnProcessCrashed(int exit_code) override;
@@ -207,9 +198,6 @@
   // GPU process id in case GPU is not in-process.
   base::ProcessId process_id_ = base::kNullProcessId;
 
-  // Qeueud messages to send when the process launches.
-  base::queue<IPC::Message*> queued_messages_;
-
   // Whether the GPU process is valid, set to false after Send() failed.
   bool valid_;
 
diff --git a/content/browser/manifest/manifest_browsertest.cc b/content/browser/manifest/manifest_browsertest.cc
index 6085e566..f948e60 100644
--- a/content/browser/manifest/manifest_browsertest.cc
+++ b/content/browser/manifest/manifest_browsertest.cc
@@ -15,6 +15,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "content/public/browser/page.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
@@ -92,8 +93,9 @@
   }
 
   void GetManifestAndWait() {
-    shell()->web_contents()->GetManifest(base::BindOnce(
-        &ManifestBrowserTest::OnGetManifest, base::Unretained(this)));
+    shell()->web_contents()->GetMainFrame()->GetPage().GetManifest(
+        base::BindOnce(&ManifestBrowserTest::OnGetManifest,
+                       base::Unretained(this)));
 
     message_loop_runner_ = new MessageLoopRunner();
     message_loop_runner_->Run();
diff --git a/content/browser/media/key_system_support_impl.cc b/content/browser/media/key_system_support_impl.cc
index 22e895d..84bf832 100644
--- a/content/browser/media/key_system_support_impl.cc
+++ b/content/browser/media/key_system_support_impl.cc
@@ -75,6 +75,8 @@
       video_codecs[media::VideoCodec::kCodecH264] = {};
     else if (codec == "hevc")
       video_codecs[media::VideoCodec::kCodecHEVC] = {};
+    else if (codec == "mp4a")
+      audio_codecs.push_back(media::AudioCodec::kCodecAAC);
     else if (codec == "vorbis")
       audio_codecs.push_back(media::AudioCodec::kCodecVorbis);
     else
diff --git a/content/browser/net/accept_header_browsertest.cc b/content/browser/net/accept_header_browsertest.cc
index 89364a35..cd56f35 100644
--- a/content/browser/net/accept_header_browsertest.cc
+++ b/content/browser/net/accept_header_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/test/bind.h"
 #include "build/build_config.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/page.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -191,7 +192,8 @@
   // Ensure that if an Accept header is already set, it is not overwritten.
   EXPECT_EQ("custom/type", GetFor("/xhr_with_accept_header"));
 
-  shell()->web_contents()->GetManifest(base::DoNothing());
+  shell()->web_contents()->GetMainFrame()->GetPage().GetManifest(
+      base::DoNothing());
 
   // ResourceType::kSubResource
   EXPECT_EQ("*/*", GetFor("/manifest"));
diff --git a/content/browser/payments/payment_app_info_fetcher.cc b/content/browser/payments/payment_app_info_fetcher.cc
index c6141100..d5ad831 100644
--- a/content/browser/payments/payment_app_info_fetcher.cc
+++ b/content/browser/payments/payment_app_info_fetcher.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/global_routing_id.h"
 #include "content/public/browser/manifest_icon_downloader.h"
+#include "content/public/browser/page.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
 #include "third_party/blink/public/common/storage_key/storage_key.h"
@@ -150,7 +151,7 @@
     web_contents_helper_ =
         std::make_unique<WebContentsHelper>(top_level_web_content);
 
-    top_level_web_content->GetManifest(
+    top_level_render_frame_host->GetPage().GetManifest(
         base::BindOnce(&PaymentAppInfoFetcher::SelfDeleteFetcher::
                            FetchPaymentAppManifestCallback,
                        weak_ptr_factory_.GetWeakPtr()));
diff --git a/content/browser/renderer_host/page_impl.cc b/content/browser/renderer_host/page_impl.cc
index b7cadd4..b2a65c8 100644
--- a/content/browser/renderer_host/page_impl.cc
+++ b/content/browser/renderer_host/page_impl.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/renderer_host/page_impl.h"
 
+#include "content/browser/manifest/manifest_manager_host.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 
 namespace content {
@@ -16,4 +17,10 @@
   return manifest_url_;
 }
 
+void PageImpl::GetManifest(GetManifestCallback callback) {
+  ManifestManagerHost* manifest_manager_host =
+      ManifestManagerHost::GetOrCreateForCurrentDocument(&main_document_);
+  manifest_manager_host->GetManifest(std::move(callback));
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/page_impl.h b/content/browser/renderer_host/page_impl.h
index 11744782..7ac4d38 100644
--- a/content/browser/renderer_host/page_impl.h
+++ b/content/browser/renderer_host/page_impl.h
@@ -28,6 +28,7 @@
 
   // Page implementation.
   const GURL& GetManifestURL() override;
+  void GetManifest(GetManifestCallback callback) override;
 
   RenderFrameHostImpl* main_document() { return &main_document_; }
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 5576d1bd..3b0e34f 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1464,6 +1464,8 @@
 
  private:
   // mojom::ChildProcessHost implementation:
+  void Ping(PingCallback callback) override { std::move(callback).Run(); }
+
   void BindHostReceiver(mojo::GenericPendingReceiver receiver) override {
     const auto& interceptor = GetBindHostReceiverInterceptor();
     if (interceptor) {
diff --git a/content/browser/sms/sms_fetcher_impl.cc b/content/browser/sms/sms_fetcher_impl.cc
index 11b4c14..3c37ea97 100644
--- a/content/browser/sms/sms_fetcher_impl.cc
+++ b/content/browser/sms/sms_fetcher_impl.cc
@@ -63,10 +63,9 @@
   subscribers_.Push(origin_list, subscriber);
 
   // Fetches a remote SMS.
-  // TODO(crbug.com/1015645): Support iframe in cross-device WebOTP.
   base::OnceClosure cancel_callback =
       GetContentClient()->browser()->FetchRemoteSms(
-          WebContents::FromRenderFrameHost(render_frame_host), origin_list[0],
+          WebContents::FromRenderFrameHost(render_frame_host), origin_list,
           base::BindOnce(&SmsFetcherImpl::OnRemote,
                          weak_ptr_factory_.GetWeakPtr()));
   if (cancel_callback)
diff --git a/content/browser/sms/sms_fetcher_impl_unittest.cc b/content/browser/sms/sms_fetcher_impl_unittest.cc
index 6ec67c8..0185dcf 100644
--- a/content/browser/sms/sms_fetcher_impl_unittest.cc
+++ b/content/browser/sms/sms_fetcher_impl_unittest.cc
@@ -35,7 +35,7 @@
   MOCK_METHOD3(
       FetchRemoteSms,
       base::OnceClosure(WebContents*,
-                        const url::Origin&,
+                        const std::vector<url::Origin>&,
                         base::OnceCallback<void(absl::optional<OriginList>,
                                                 absl::optional<std::string>,
                                                 absl::optional<FailureType>)>));
@@ -111,7 +111,7 @@
 
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
@@ -133,7 +133,7 @@
 
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
@@ -154,7 +154,7 @@
 
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
@@ -179,7 +179,7 @@
 
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
@@ -261,7 +261,7 @@
 
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
@@ -284,7 +284,7 @@
   base::MockOnceClosure cancel_callback;
   EXPECT_CALL(*client(), FetchRemoteSms(_, _, _))
       .WillOnce(Invoke(
-          [&](WebContents*, const url::Origin&,
+          [&](WebContents*, const OriginList&,
               base::OnceCallback<void(absl::optional<OriginList>,
                                       absl::optional<std::string>,
                                       absl::optional<FailureType>)> callback) {
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc
index 677ad33..442ed38c 100644
--- a/content/browser/ssl/ssl_manager.cc
+++ b/content/browser/ssl/ssl_manager.cc
@@ -213,9 +213,8 @@
   NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
   if (entry && entry->GetURL().SchemeIsCryptographic() &&
       entry->GetSSL().certificate) {
-    WebContentsImpl* contents = static_cast<WebContentsImpl*>(
-        controller_->delegate()->GetWebContents());
-    ukm::SourceId source_id = contents->GetMainFrame()->GetPageUkmSourceId();
+    RenderFrameHostImpl* main_frame = controller_->frame_tree().GetMainFrame();
+    ukm::SourceId source_id = main_frame->GetPageUkmSourceId();
     LogMixedContentMetrics(MixedContentType::kOptionallyBlockableMixedContent,
                            source_id, ukm::UkmRecorder::Get());
   }
@@ -227,9 +226,8 @@
   NavigationEntryImpl* entry = controller_->GetLastCommittedEntry();
   if (entry && entry->GetURL().SchemeIsCryptographic() &&
       entry->GetSSL().certificate) {
-    WebContentsImpl* contents = static_cast<WebContentsImpl*>(
-        controller_->delegate()->GetWebContents());
-    ukm::SourceId source_id = contents->GetMainFrame()->GetPageUkmSourceId();
+    RenderFrameHostImpl* main_frame = controller_->frame_tree().GetMainFrame();
+    ukm::SourceId source_id = main_frame->GetPageUkmSourceId();
     LogMixedContentMetrics(MixedContentType::kMixedForm, source_id,
                            ukm::UkmRecorder::Get());
   }
@@ -245,9 +243,9 @@
     // Only record information about subresources with cert errors if the
     // main page is HTTPS with a valid certificate.
     if (!net::IsCertStatusError(entry->GetSSL().cert_status)) {
-      WebContentsImpl* contents = static_cast<WebContentsImpl*>(
-          controller_->delegate()->GetWebContents());
-      ukm::SourceId source_id = contents->GetMainFrame()->GetPageUkmSourceId();
+      RenderFrameHostImpl* main_frame =
+          controller_->frame_tree().GetMainFrame();
+      ukm::SourceId source_id = main_frame->GetPageUkmSourceId();
       LogMixedContentMetrics(
           MixedContentType::kOptionallyBlockableWithCertErrors, source_id,
           ukm::UkmRecorder::Get());
@@ -262,9 +260,8 @@
     return;
 
   if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate) {
-    WebContentsImpl* contents = static_cast<WebContentsImpl*>(
-        controller_->delegate()->GetWebContents());
-    ukm::SourceId source_id = contents->GetMainFrame()->GetPageUkmSourceId();
+    RenderFrameHostImpl* main_frame = controller_->frame_tree().GetMainFrame();
+    ukm::SourceId source_id = main_frame->GetPageUkmSourceId();
     LogMixedContentMetrics(MixedContentType::kBlockableMixedContent, source_id,
                            ukm::UkmRecorder::Get());
   }
@@ -291,9 +288,8 @@
   // main page is HTTPS with a valid certificate.
   if (entry->GetURL().SchemeIsCryptographic() && entry->GetSSL().certificate &&
       !net::IsCertStatusError(entry->GetSSL().cert_status)) {
-    WebContentsImpl* contents = static_cast<WebContentsImpl*>(
-        controller_->delegate()->GetWebContents());
-    ukm::SourceId source_id = contents->GetMainFrame()->GetPageUkmSourceId();
+    RenderFrameHostImpl* main_frame = controller_->frame_tree().GetMainFrame();
+    ukm::SourceId source_id = main_frame->GetPageUkmSourceId();
     LogMixedContentMetrics(MixedContentType::kBlockableWithCertErrors,
                            source_id, ukm::UkmRecorder::Get());
   }
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index 3699174e..dc2de56 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -94,13 +94,6 @@
   return weak_ptr_factory_.GetWeakPtr();
 }
 
-bool UtilityProcessHost::Send(IPC::Message* message) {
-  if (!StartProcess())
-    return false;
-
-  return process_->Send(message);
-}
-
 void UtilityProcessHost::SetSandboxType(
     sandbox::policy::SandboxType sandbox_type) {
   sandbox_type_ = sandbox_type;
@@ -164,7 +157,6 @@
   started_ = true;
   process_->SetName(name_);
   process_->SetMetricsName(metrics_name_);
-  process_->GetHost()->CreateChannelMojo();
 
   if (RenderProcessHost::run_renderer_in_process()) {
     DCHECK(g_utility_main_thread_factory);
@@ -343,10 +335,6 @@
   return true;
 }
 
-bool UtilityProcessHost::OnMessageReceived(const IPC::Message& message) {
-  return true;
-}
-
 void UtilityProcessHost::OnProcessLaunched() {
   launch_state_ = LaunchState::kLaunchComplete;
   for (auto& callback : pending_run_service_callbacks_)
diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
index 5c39d5b..37e1568 100644
--- a/content/browser/utility_process_host.h
+++ b/content/browser/utility_process_host.h
@@ -19,7 +19,6 @@
 #include "content/common/child_process.mojom.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_child_process_host_delegate.h"
-#include "ipc/ipc_sender.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/system/message_pipe.h"
@@ -52,8 +51,7 @@
 // avoid a use after free since this object is deleted synchronously but the
 // client notification is asynchronous.  See http://crbug.com/108871.
 class CONTENT_EXPORT UtilityProcessHost
-    : public IPC::Sender,
-      public BrowserChildProcessHostDelegate {
+    : public BrowserChildProcessHostDelegate {
  public:
   static void RegisterUtilityMainThreadFactory(
       UtilityMainThreadFactoryFunction create);
@@ -116,11 +114,7 @@
   // Starts the child process if needed, returns true on success.
   bool StartProcess();
 
-  // IPCSender:
-  bool Send(IPC::Message* message) override;
-
   // BrowserChildProcessHostDelegate:
-  bool OnMessageReceived(const IPC::Message& message) override;
   void OnProcessLaunched() override;
   void OnProcessLaunchFailed(int error_code) override;
   void OnProcessCrashed(int exit_code) override;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 117f99e..763c1508 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -69,7 +69,6 @@
 #include "content/browser/download/save_package.h"
 #include "content/browser/find_request_manager.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/manifest/manifest_manager_host.h"
 #include "content/browser/media/audio_stream_broker.h"
 #include "content/browser/media/audio_stream_monitor.h"
 #include "content/browser/media/media_web_contents_observer.h"
@@ -5202,14 +5201,6 @@
   return was_ever_audible_;
 }
 
-void WebContentsImpl::GetManifest(GetManifestCallback callback) {
-  OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::GetManifest");
-  // TODO(yuzus, 1061899): Move this function to RenderFrameHostImpl.
-  ManifestManagerHost* manifest_manager_host =
-      ManifestManagerHost::GetOrCreateForCurrentDocument(GetMainFrame());
-  manifest_manager_host->GetManifest(std::move(callback));
-}
-
 void WebContentsImpl::ExitFullscreen(bool will_cause_resize) {
   OPTIONAL_TRACE_EVENT0("content", "WebContentsImpl::ExitFullscreen");
   // Clean up related state and initiate the fullscreen exit.
@@ -5747,7 +5738,7 @@
   // Use the last committed entry, since the pending entry hasn't loaded yet and
   // won't be copied into the cloned tab.
   NavigationEntryImpl* last_committed_entry =
-      GetController().GetLastCommittedEntry();
+      frame->frame_tree()->controller().GetLastCommittedEntry();
   if (!last_committed_entry)
     return;
 
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index cb525161..f682f50 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -533,7 +533,6 @@
             blink::mojom::FindOptionsPtr options) override;
   void StopFinding(StopFindAction action) override;
   bool WasEverAudible() override;
-  void GetManifest(GetManifestCallback callback) override;
   bool IsFullscreen() override;
   bool ShouldShowStaleContentOnEviction() override;
   void ExitFullscreen(bool will_cause_resize) override;
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index 0a7416ea..efce9fad 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -156,45 +156,47 @@
 }
 #endif
 
+void TerminateSelfOnDisconnect() {
+  // For renderer/worker processes:
+  // On POSIX, at least, one can install an unload handler which loops
+  // forever and leave behind a renderer process which eats 100% CPU forever.
+  //
+  // This is because the terminate signals (FrameMsg_BeforeUnload and the
+  // error from the IPC sender) are routed to the main message loop but never
+  // processed (because that message loop is stuck in V8).
+  //
+  // One could make the browser SIGKILL the renderers, but that leaves open a
+  // large window where a browser failure (or a user, manually terminating
+  // the browser because "it's stuck") will leave behind a process eating all
+  // the CPU.
+  //
+  // So, we install a filter on the sender so that we can process this event
+  // here and kill the process.
+  base::debug::StopProfiling();
+#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) ||  \
+    defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
+    defined(UNDEFINED_SANITIZER)
+  // Some sanitizer tools rely on exit handlers (e.g. to run leak detection,
+  // or dump code coverage data to disk). Instead of exiting the process
+  // immediately, we give it 60 seconds to run exit handlers.
+  CHECK(CreateWaitAndExitThread(base::TimeDelta::FromSeconds(60)));
+#if defined(LEAK_SANITIZER)
+  // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
+  // leaks are found, the process will exit here.
+  __lsan_do_leak_check();
+#endif
+#else
+  base::Process::TerminateCurrentProcessImmediately(0);
+#endif
+}
+
 class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
  public:
   // IPC::MessageFilter
-  void OnChannelError() override {
-    // For renderer/worker processes:
-    // On POSIX, at least, one can install an unload handler which loops
-    // forever and leave behind a renderer process which eats 100% CPU forever.
-    //
-    // This is because the terminate signals (FrameMsg_BeforeUnload and the
-    // error from the IPC sender) are routed to the main message loop but never
-    // processed (because that message loop is stuck in V8).
-    //
-    // One could make the browser SIGKILL the renderers, but that leaves open a
-    // large window where a browser failure (or a user, manually terminating
-    // the browser because "it's stuck") will leave behind a process eating all
-    // the CPU.
-    //
-    // So, we install a filter on the sender so that we can process this event
-    // here and kill the process.
-    base::debug::StopProfiling();
-#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
-    defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
-    defined(UNDEFINED_SANITIZER)
-    // Some sanitizer tools rely on exit handlers (e.g. to run leak detection,
-    // or dump code coverage data to disk). Instead of exiting the process
-    // immediately, we give it 60 seconds to run exit handlers.
-    CHECK(CreateWaitAndExitThread(base::TimeDelta::FromSeconds(60)));
-#if defined(LEAK_SANITIZER)
-    // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
-    // leaks are found, the process will exit here.
-    __lsan_do_leak_check();
-#endif
-#else
-    base::Process::TerminateCurrentProcessImmediately(0);
-#endif
-  }
+  void OnChannelError() override { TerminateSelfOnDisconnect(); }
 
  protected:
-  ~SuicideOnChannelErrorFilter() override {}
+  ~SuicideOnChannelErrorFilter() override = default;
 };
 
 #endif  // OS(POSIX)
@@ -415,15 +417,13 @@
   return ChildThreadImpl::current();
 }
 
-ChildThreadImpl::Options::Options() : connect_to_browser(false) {}
+ChildThreadImpl::Options::Options() = default;
 
 ChildThreadImpl::Options::Options(const Options& other) = default;
 
-ChildThreadImpl::Options::~Options() {
-}
+ChildThreadImpl::Options::~Options() = default;
 
-ChildThreadImpl::Options::Builder::Builder() {
-}
+ChildThreadImpl::Options::Builder::Builder() = default;
 
 ChildThreadImpl::Options::Builder&
 ChildThreadImpl::Options::Builder::InBrowserProcess(
@@ -434,6 +434,12 @@
 }
 
 ChildThreadImpl::Options::Builder&
+ChildThreadImpl::Options::Builder::WithLegacyIPCChannel(bool with_channel) {
+  options_.with_legacy_ipc_channel = with_channel;
+  return *this;
+}
+
+ChildThreadImpl::Options::Builder&
 ChildThreadImpl::Options::Builder::ConnectToBrowser(
     bool connect_to_browser_parms) {
   options_.connect_to_browser = connect_to_browser_parms;
@@ -545,14 +551,17 @@
   IPC::Logging::GetInstance();
 #endif
 
-  channel_ = IPC::SyncChannel::Create(
-      this, ChildProcess::current()->io_task_runner(),
-      ipc_task_runner_ ? ipc_task_runner_ : base::ThreadTaskRunnerHandle::Get(),
-      ChildProcess::current()->GetShutDownEvent());
+  if (options.with_legacy_ipc_channel) {
+    channel_ = IPC::SyncChannel::Create(
+        this, ChildProcess::current()->io_task_runner(),
+        ipc_task_runner_ ? ipc_task_runner_
+                         : base::ThreadTaskRunnerHandle::Get(),
+        ChildProcess::current()->GetShutDownEvent());
 #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
-  if (!IsInBrowserProcess())
-    IPC::Logging::GetInstance()->SetIPCSender(this);
+    if (!IsInBrowserProcess())
+      IPC::Logging::GetInstance()->SetIPCSender(this);
 #endif
+  }
 
   mojo::ScopedMessagePipeHandle child_process_pipe_for_receiver;
   mojo::ScopedMessagePipeHandle child_process_host_pipe_for_remote;
@@ -576,8 +585,10 @@
         invitation.ExtractMessagePipe(kChildProcessReceiverAttachmentName);
     child_process_host_pipe_for_remote =
         invitation.ExtractMessagePipe(kChildProcessHostRemoteAttachmentName);
-    legacy_ipc_bootstrap_pipe =
-        invitation.ExtractMessagePipe(kLegacyIpcBootstrapAttachmentName);
+    if (options.with_legacy_ipc_channel) {
+      legacy_ipc_bootstrap_pipe =
+          invitation.ExtractMessagePipe(kLegacyIpcBootstrapAttachmentName);
+    }
   } else {
     child_process_pipe_for_receiver =
         options.mojo_invitation->ExtractMessagePipe(
@@ -585,8 +596,10 @@
     child_process_host_pipe_for_remote =
         options.mojo_invitation->ExtractMessagePipe(
             kChildProcessHostRemoteAttachmentName);
-    legacy_ipc_bootstrap_pipe = options.mojo_invitation->ExtractMessagePipe(
-        kLegacyIpcBootstrapAttachmentName);
+    if (options.with_legacy_ipc_channel) {
+      legacy_ipc_bootstrap_pipe = options.mojo_invitation->ExtractMessagePipe(
+          kLegacyIpcBootstrapAttachmentName);
+    }
   }
 
   // Now that we've recovered the message pipe for the ChildProcessHost, build
@@ -596,7 +609,8 @@
   child_process_host_ = mojo::SharedRemote<mojom::ChildProcessHost>(
       std::move(remote_host), GetIOTaskRunner());
 
-  sync_message_filter_ = channel_->CreateSyncMessageFilter();
+  if (options.with_legacy_ipc_channel)
+    sync_message_filter_ = channel_->CreateSyncMessageFilter();
 
   // In single process mode, browser-side tracing and memory will cover the
   // whole process including renderers.
@@ -634,23 +648,35 @@
 #if defined(OS_POSIX)
   // Check that --process-type is specified so we don't do this in unit tests
   // and single-process mode.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType))
-    channel_->AddFilter(new SuicideOnChannelErrorFilter());
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kProcessType)) {
+    if (options.with_legacy_ipc_channel) {
+      channel_->AddFilter(new SuicideOnChannelErrorFilter());
+    } else {
+      child_process_host_.set_disconnect_handler(
+          base::BindOnce(&TerminateSelfOnDisconnect), GetIOTaskRunner());
+    }
+  }
 #endif
 
   // Add filters passed here via options.
-  for (auto* startup_filter : options.startup_filters) {
-    channel_->AddFilter(startup_filter);
+  if (options.with_legacy_ipc_channel) {
+    for (auto* startup_filter : options.startup_filters) {
+      channel_->AddFilter(startup_filter);
+    }
+
+    DCHECK(legacy_ipc_bootstrap_pipe.is_valid());
+    channel_->Init(IPC::ChannelMojo::CreateClientFactory(
+                       std::move(legacy_ipc_bootstrap_pipe),
+                       ChildProcess::current()->io_task_runner(),
+                       ipc_task_runner_ ? ipc_task_runner_
+                                        : base::ThreadTaskRunnerHandle::Get()),
+                   /*create_pipe_now=*/true);
+  } else {
+    DCHECK(options.startup_filters.empty());
   }
 
   DCHECK(child_process_pipe_for_receiver.is_valid());
-  DCHECK(legacy_ipc_bootstrap_pipe.is_valid());
-  channel_->Init(IPC::ChannelMojo::CreateClientFactory(
-                     std::move(legacy_ipc_bootstrap_pipe),
-                     ChildProcess::current()->io_task_runner(),
-                     ipc_task_runner_ ? ipc_task_runner_
-                                      : base::ThreadTaskRunnerHandle::Get()),
-                 /*create_pipe_now=*/true);
 
   ChildThreadImpl::GetIOTaskRunner()->PostTask(
       FROM_HERE,
@@ -668,6 +694,11 @@
       connection_timeout = temp;
   }
 
+  if (!options.with_legacy_ipc_channel) {
+    child_process_host_->Ping(
+        base::BindOnce(&ChildThreadImpl::OnChannelConnected,
+                       base::Unretained(this), /*unused=*/0));
+  }
   main_thread_runner_->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&ChildThreadImpl::EnsureConnected,
@@ -693,17 +724,32 @@
   IPC::Logging::GetInstance()->SetIPCSender(NULL);
 #endif
 
-  channel_->RemoveFilter(sync_message_filter_.get());
+  if (channel_) {
+    channel_->RemoveFilter(sync_message_filter_.get());
 
-  // The ChannelProxy object caches a pointer to the IPC thread, so need to
-  // reset it as it's not guaranteed to outlive this object.
-  // NOTE: this also has the side-effect of not closing the main IPC channel to
-  // the browser process.  This is needed because this is the signal that the
-  // browser uses to know that this process has died, so we need it to be alive
-  // until this process is shut down, and the OS closes the handle
-  // automatically.  We used to watch the object handle on Windows to do this,
-  // but it wasn't possible to do so on POSIX.
-  channel_->ClearIPCTaskRunner();
+    // The ChannelProxy object caches a pointer to the IPC thread, so need to
+    // reset it as it's not guaranteed to outlive this object.
+    // NOTE: this also has the side-effect of not closing the main IPC channel
+    // to the browser process.  This is needed because this is the signal that
+    // the browser uses to know that this process has died, so we need it to be
+    // alive until this process is shut down, and the OS closes the handle
+    // automatically.  We used to watch the object handle on Windows to do this,
+    // but it wasn't possible to do so on POSIX.
+    channel_->ClearIPCTaskRunner();
+  } else if (!IsInBrowserProcess()) {
+    // With no legacy IPC channel, the browser monitors the lifetime of the
+    // ChildProcessHost connection to detect our exit. For reasons similar to
+    // above, we leak our side of this connection to ensure that the browser
+    // does not observe disconnection until after our process is actually
+    // terminated.
+    auto leaked_remote =
+        std::make_unique<mojo::SharedRemote<mojom::ChildProcessHost>>(
+            std::move(child_process_host_));
+    auto* leaked_remote_ptr = leaked_remote.release();
+    ALLOW_UNUSED_LOCAL(leaked_remote_ptr);
+    ANNOTATE_LEAKING_OBJECT_PTR(leaked_remote_ptr);
+  }
+
   g_lazy_child_thread_impl_tls.Pointer()->Set(nullptr);
 }
 
@@ -765,7 +811,8 @@
 }
 
 void ChildThreadImpl::BindHostReceiver(mojo::GenericPendingReceiver receiver) {
-  child_process_host_->BindHostReceiver(std::move(receiver));
+  if (child_process_host_)
+    child_process_host_->BindHostReceiver(std::move(receiver));
 }
 
 IPC::MessageRouter* ChildThreadImpl::GetRouter() {
@@ -814,6 +861,10 @@
   background_tracing_agent_provider_->AddBinding(std::move(receiver));
 }
 
+void ChildThreadImpl::DisconnectChildProcessHost() {
+  child_process_host_.reset();
+}
+
 void ChildThreadImpl::RunServiceDeprecated(
     const std::string& service_name,
     mojo::ScopedMessagePipeHandle service_pipe) {
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index cefd680be..5253934 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -124,6 +124,11 @@
     return child_process_host_;
   }
 
+  // Explicitly closes the ChildProcessHost connection. This will cause the
+  // host-side object to be torn down and clean up resources tied to this
+  // process (or this thread object, in single-process mode).
+  void DisconnectChildProcessHost();
+
   virtual void RunServiceDeprecated(const std::string& service_name,
                                     mojo::ScopedMessagePipeHandle service_pipe);
 
@@ -243,10 +248,11 @@
 
   class Builder;
 
-  bool connect_to_browser;
+  bool with_legacy_ipc_channel = true;
+  bool connect_to_browser = false;
   scoped_refptr<base::SingleThreadTaskRunner> browser_process_io_runner;
   std::vector<IPC::MessageFilter*> startup_filters;
-  mojo::OutgoingInvitation* mojo_invitation;
+  mojo::OutgoingInvitation* mojo_invitation = nullptr;
   scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner;
 
   // Indicates that this child process exposes one or more Mojo interfaces to
@@ -269,6 +275,7 @@
 
   Builder& InBrowserProcess(const InProcessChildThreadParams& params);
   Builder& ConnectToBrowser(bool connect_to_browser);
+  Builder& WithLegacyIPCChannel(bool with_legacy_ipc_channel);
   Builder& AddStartupFilter(IPC::MessageFilter* filter);
   Builder& IPCTaskRunner(
       scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner);
diff --git a/content/common/child_process.mojom b/content/common/child_process.mojom
index c0ba5b9..ea3947a1 100644
--- a/content/common/child_process.mojom
+++ b/content/common/child_process.mojom
@@ -13,6 +13,15 @@
 // The primordial interface child processes use to push requests to their
 // browser-side host object.
 interface ChildProcessHost {
+  // Pings the parent process, expecting a reply. Used to verify that the
+  // process and this interface connection are operational. When a child
+  // process is started, it begins a timer (default 15 seconds) and sends this
+  // message to the browser. If no reply comes back before time runs out, the
+  // process self-terminates. There are no other interesting side effects, nor
+  // are there any constraints on what either process can do while this is in
+  // flight.
+  Ping() => ();
+
   // Requests that the browser bind |receiver| on behalf of the child process.
   // Whether or not the interface type encapsulated by |receiver| is supported
   // depends on the process type and potentially on the Content embedder.
diff --git a/content/common/child_process_host_impl.cc b/content/common/child_process_host_impl.cc
index 995f1fa1..8dda040 100644
--- a/content/common/child_process_host_impl.cc
+++ b/content/common/child_process_host_impl.cc
@@ -138,6 +138,13 @@
     receiver_.Bind(mojo::PendingReceiver<mojom::ChildProcessHost>(
         mojo_invitation_->AttachMessagePipe(
             kChildProcessHostRemoteAttachmentName)));
+    receiver_.set_disconnect_handler(
+        base::BindOnce(&ChildProcessHostImpl::OnDisconnectedFromChildProcess,
+                       base::Unretained(this)));
+
+#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
+    child_process_->SetProfilingFile(OpenProfilingFile());
+#endif
   }
 }
 
@@ -148,9 +155,9 @@
   if (!channel_)
     return;
 
-  for (size_t i = 0; i < filters_.size(); ++i) {
-    filters_[i]->OnChannelClosing();
-    filters_[i]->OnFilterRemoved();
+  for (auto& filter : filters_) {
+    filter->OnChannelClosing();
+    filter->OnFilterRemoved();
   }
 }
 
@@ -165,6 +172,20 @@
   child_process_->BindReceiver(std::move(receiver));
 }
 
+base::Process& ChildProcessHostImpl::GetPeerProcess() {
+  if (!peer_process_.IsValid()) {
+    const base::Process& process = delegate_->GetProcess();
+    if (process.IsValid()) {
+      peer_process_ = base::Process::OpenWithExtraPrivileges(process.Pid());
+      if (!peer_process_.IsValid())
+        peer_process_ = process.Duplicate();
+      DCHECK(peer_process_.IsValid());
+    }
+  }
+
+  return peer_process_;
+}
+
 void ChildProcessHostImpl::RunServiceDeprecated(
     const std::string& service_name,
     mojo::ScopedMessagePipeHandle service_pipe) {
@@ -198,6 +219,12 @@
   }
   DCHECK(channel_);
 
+  // Since we're initializing a legacy IPC Channel, we will use its connection
+  // status to monitor child process lifetime instead of using the status of the
+  // `receiver_` endpoint.
+  if (receiver_.is_bound())
+    receiver_.set_disconnect_handler(base::NullCallback());
+
   bool initialized = InitChannel();
   DCHECK(initialized);
 }
@@ -206,8 +233,8 @@
   if (!channel_->Connect())
     return false;
 
-  for (size_t i = 0; i < filters_.size(); ++i)
-    filters_[i]->OnFilterAdded(channel_.get());
+  for (auto& filter : filters_)
+    filter->OnFilterAdded(channel_.get());
 
   delegate_->OnChannelInitialized(channel_.get());
 
@@ -217,15 +244,23 @@
   child_process_->SetIPCLoggingEnabled(enabled);
 #endif
 
-#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
-  child_process_->SetProfilingFile(OpenProfilingFile());
-#endif
-
   opening_channel_ = true;
 
   return true;
 }
 
+void ChildProcessHostImpl::OnDisconnectedFromChildProcess() {
+  if (channel_) {
+    opening_channel_ = false;
+    delegate_->OnChannelError();
+    for (auto& filter : filters_)
+      filter->OnChannelError();
+  }
+
+  // This will delete host_, which will also destroy this!
+  delegate_->OnChildDisconnected();
+}
+
 bool ChildProcessHostImpl::IsChannelOpening() {
   return opening_channel_;
 }
@@ -270,6 +305,10 @@
          1;
 }
 
+void ChildProcessHostImpl::Ping(PingCallback callback) {
+  std::move(callback).Run();
+}
+
 void ChildProcessHostImpl::BindHostReceiver(
     mojo::GenericPendingReceiver receiver) {
   delegate_->BindHostReceiver(std::move(receiver));
@@ -288,8 +327,8 @@
 #endif
 
   bool handled = false;
-  for (size_t i = 0; i < filters_.size(); ++i) {
-    if (filters_[i]->OnMessageReceived(msg)) {
+  for (auto& filter : filters_) {
+    if (filter->OnMessageReceived(msg)) {
       handled = true;
       break;
     }
@@ -307,27 +346,26 @@
 }
 
 void ChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
-  if (!peer_process_.IsValid()) {
-    peer_process_ = base::Process::OpenWithExtraPrivileges(peer_pid);
-    if (!peer_process_.IsValid())
-       peer_process_ = delegate_->GetProcess().Duplicate();
-    DCHECK(peer_process_.IsValid());
-  }
+  // We ignore the `peer_pid` argument, which ultimately comes over IPC from the
+  // remote process, in favor of the PID already known by the browser after
+  // launching the process. This is partly because IPC Channel is being phased
+  // out and some process types no longer use it, but also because there's
+  // really no need to get this information from the child process when we
+  // already have it.
+  //
+  // TODO(crbug.com/616980): Remove the peer_pid argument altogether from
+  // IPC::Listener::OnChannelConnected.
+  const base::Process& peer_process = GetPeerProcess();
+  base::ProcessId pid =
+      peer_process.IsValid() ? peer_process.Pid() : base::GetCurrentProcId();
   opening_channel_ = false;
-  delegate_->OnChannelConnected(peer_pid);
-  for (size_t i = 0; i < filters_.size(); ++i)
-    filters_[i]->OnChannelConnected(peer_pid);
+  delegate_->OnChannelConnected(pid);
+  for (auto& filter : filters_)
+    filter->OnChannelConnected(pid);
 }
 
 void ChildProcessHostImpl::OnChannelError() {
-  opening_channel_ = false;
-  delegate_->OnChannelError();
-
-  for (size_t i = 0; i < filters_.size(); ++i)
-    filters_[i]->OnChannelError();
-
-  // This will delete host_, which will also destroy this!
-  delegate_->OnChildDisconnected();
+  OnDisconnectedFromChildProcess();
 }
 
 void ChildProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) {
diff --git a/content/common/child_process_host_impl.h b/content/common/child_process_host_impl.h
index 5f9408c..f13405b 100644
--- a/content/common/child_process_host_impl.h
+++ b/content/common/child_process_host_impl.h
@@ -78,7 +78,7 @@
       const std::string& service_name,
       mojo::ScopedMessagePipeHandle service_pipe) override;
 
-  base::Process& peer_process() { return peer_process_; }
+  base::Process& GetPeerProcess();
   mojom::ChildProcess* child_process() { return child_process_.get(); }
 
  private:
@@ -87,6 +87,7 @@
   ChildProcessHostImpl(ChildProcessHostDelegate* delegate, IpcMode ipc_mode);
 
   // mojom::ChildProcessHost implementation:
+  void Ping(PingCallback callback) override;
   void BindHostReceiver(mojo::GenericPendingReceiver receiver) override;
 
   // IPC::Listener methods:
@@ -99,6 +100,8 @@
   // non-null.
   bool InitChannel();
 
+  void OnDisconnectedFromChildProcess();
+
 #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
   void DumpProfilingData(base::OnceClosure callback) override;
 #endif
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index c342022d..b8f2e441 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -60,12 +60,14 @@
   base::debug::DumpWithoutCrashing();
 }
 
-ChildThreadImpl::Options GetOptions() {
+ChildThreadImpl::Options GetOptions(
+    const InProcessChildThreadParams* in_process_params = nullptr) {
   ChildThreadImpl::Options::Builder builder;
-
   builder.ConnectToBrowser(true);
   builder.ExposesInterfacesToBrowser();
-
+  builder.WithLegacyIPCChannel(false);
+  if (in_process_params)
+    builder.InBrowserProcess(*in_process_params);
   return builder.Build();
 }
 
@@ -105,11 +107,7 @@
 GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params,
                                std::unique_ptr<gpu::GpuInit> gpu_init)
     : GpuChildThread(base::DoNothing(),
-                     ChildThreadImpl::Options::Builder()
-                         .InBrowserProcess(params)
-                         .ConnectToBrowser(true)
-                         .ExposesInterfacesToBrowser()
-                         .Build(),
+                     GetOptions(&params),
                      std::move(gpu_init)) {}
 
 GpuChildThread::GpuChildThread(base::RepeatingClosure quit_closure,
@@ -152,14 +150,6 @@
   return viz_main_.gpu_service()->gpu_info().in_process_gpu;
 }
 
-bool GpuChildThread::Send(IPC::Message* msg) {
-  // The GPU process must never send a synchronous IPC message to the browser
-  // process. This could result in deadlock.
-  DCHECK(!msg->is_sync());
-
-  return ChildThreadImpl::Send(msg);
-}
-
 void GpuChildThread::OnInitializationFailed() {
   OnChannelError();
 }
diff --git a/content/gpu/gpu_child_thread.h b/content/gpu/gpu_child_thread.h
index 9bf0ae5..ea5e61b6 100644
--- a/content/gpu/gpu_child_thread.h
+++ b/content/gpu/gpu_child_thread.h
@@ -61,7 +61,6 @@
   bool in_process_gpu() const;
 
   // ChildThreadImpl:
-  bool Send(IPC::Message* msg) override;
   void BindServiceInterface(mojo::GenericPendingReceiver receiver) override;
 
   // viz::VizMainImpl::Delegate:
diff --git a/content/public/browser/browser_child_process_host_delegate.cc b/content/public/browser/browser_child_process_host_delegate.cc
index b9558df..329e65bf 100644
--- a/content/public/browser/browser_child_process_host_delegate.cc
+++ b/content/public/browser/browser_child_process_host_delegate.cc
@@ -10,4 +10,9 @@
   return absl::nullopt;
 }
 
+bool BrowserChildProcessHostDelegate::OnMessageReceived(
+    const IPC::Message& message) {
+  return false;
+}
+
 }  // namespace content
diff --git a/content/public/browser/browser_child_process_host_delegate.h b/content/public/browser/browser_child_process_host_delegate.h
index 42a8a5d..363dc20 100644
--- a/content/public/browser/browser_child_process_host_delegate.h
+++ b/content/public/browser/browser_child_process_host_delegate.h
@@ -38,6 +38,10 @@
   // Binds an interface receiver in the host process, as requested by the child
   // process.
   virtual void BindHostReceiver(mojo::GenericPendingReceiver receiver) {}
+
+  // Default no-op handler for incoming legacy IPCs, for processes that don't
+  // use legacy IPC.
+  bool OnMessageReceived(const IPC::Message& message) override;
 };
 
 }  // namespace content
diff --git a/content/public/browser/browser_child_process_observer.h b/content/public/browser/browser_child_process_observer.h
index ddf9cd2..62472a0 100644
--- a/content/public/browser/browser_child_process_observer.h
+++ b/content/public/browser/browser_child_process_observer.h
@@ -17,11 +17,6 @@
 // interface; use RenderProcessHostObserver instead.
 class CONTENT_EXPORT BrowserChildProcessObserver {
  public:
-  // Called when a child process host has connected to a child process.
-  // Note that |data.handle| may be invalid, if the child process connects to
-  // the pipe before the process launcher's reply arrives.
-  virtual void BrowserChildProcessHostConnected(const ChildProcessData& data) {}
-
   // Called when a child process has successfully launched and has connected to
   // it child process host. The |data.handle| is guaranteed to be valid.
   virtual void BrowserChildProcessLaunchedAndConnected(
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 3b3eefc0..e8abe79 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -1139,7 +1139,7 @@
 
 base::OnceClosure ContentBrowserClient::FetchRemoteSms(
     content::WebContents* web_contents,
-    const url::Origin& origin,
+    const std::vector<url::Origin>& origin_list,
     base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                             absl::optional<std::string>,
                             absl::optional<content::SmsFetchFailureType>)>
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 83f502a..9c11388f 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -1924,7 +1924,7 @@
       const GURL& site_for_cookies,
       const absl::optional<url::Origin>& top_frame_origin);
 
-  // Requests an SMS from |origin| from a remote device with telephony
+  // Requests an SMS from |origin_list| from a remote device with telephony
   // capabilities, for example the user's mobile phone. Callbacks |callback|
   // with the origins and one-time-code from the SMS upon success or a failure
   // type on error. The returned callback cancels receiving of the response.
@@ -1933,7 +1933,7 @@
   // is disabled.
   virtual base::OnceClosure FetchRemoteSms(
       content::WebContents* web_contents,
-      const url::Origin& origin,
+      const std::vector<url::Origin>& origin_list,
       base::OnceCallback<void(absl::optional<std::vector<url::Origin>>,
                               absl::optional<std::string>,
                               absl::optional<content::SmsFetchFailureType>)>
diff --git a/content/public/browser/page.h b/content/public/browser/page.h
index d4638c87..8718c87f 100644
--- a/content/public/browser/page.h
+++ b/content/public/browser/page.h
@@ -5,9 +5,14 @@
 #ifndef CONTENT_PUBLIC_BROWSER_PAGE_H_
 #define CONTENT_PUBLIC_BROWSER_PAGE_H_
 
+#include "base/callback.h"
 #include "content/common/content_export.h"
 #include "url/gurl.h"
 
+namespace blink {
+struct Manifest;
+}  // namespace blink
+
 namespace content {
 
 // Page represents a collection of documents with the same main document.
@@ -55,6 +60,15 @@
   // See https://w3c.github.io/manifest/#web-application-manifest
   virtual const GURL& GetManifestURL() = 0;
 
+  // The callback invoked when the renderer responds to a request for the main
+  // frame document's manifest. The url will be empty if the document specifies
+  // no manifest, and the manifest will be empty if any other failures occurred.
+  using GetManifestCallback =
+      base::OnceCallback<void(const GURL&, const blink::Manifest&)>;
+
+  // Requests the manifest URL and the Manifest of the main frame's document.
+  virtual void GetManifest(GetManifestCallback callback) = 0;
+
  private:
   // This interface should only be implemented inside content.
   friend class PageImpl;
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index d2a72168..28716ea 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -55,7 +55,6 @@
 namespace web_pref {
 struct WebPreferences;
 }
-struct Manifest;
 struct UserAgentOverride;
 struct RendererPreferences;
 }  // namespace blink
@@ -1053,15 +1052,6 @@
   // navigation.
   virtual bool WasEverAudible() = 0;
 
-  // The callback invoked when the renderer responds to a request for the main
-  // frame document's manifest. The url will be empty if the document specifies
-  // no manifest, and the manifest will be empty if any other failures occurred.
-  using GetManifestCallback =
-      base::OnceCallback<void(const GURL&, const blink::Manifest&)>;
-
-  // Requests the manifest URL and the Manifest of the main frame's document.
-  virtual void GetManifest(GetManifestCallback callback) = 0;
-
   // Returns whether the renderer is in fullscreen mode.
   virtual bool IsFullscreen() = 0;
 
diff --git a/content/public/common/child_process_host.h b/content/public/common/child_process_host.h
index f9233d5..7f14e00 100644
--- a/content/public/common/child_process_host.h
+++ b/content/public/common/child_process_host.h
@@ -148,11 +148,14 @@
   // null if someone else has taken ownership.
   virtual absl::optional<mojo::OutgoingInvitation>& GetMojoInvitation() = 0;
 
-  // Creates the IPC channel over a Mojo message pipe. The pipe connection is
-  // brokered through the Service Manager like any other service connection.
+  // Creates a legacy IPC channel over a Mojo message pipe. Must be called if
+  // legacy IPC will be used to communicate with the child process, but
+  // otherwise should not be called.
   virtual void CreateChannelMojo() = 0;
 
-  // Returns true iff the IPC channel is currently being opened;
+  // Returns true iff the IPC channel is currently being opened; this means
+  // CreateChannelMojo() has been called, but OnChannelConnected() has not yet
+  // been invoked.
   virtual bool IsChannelOpening() = 0;
 
   // Adds an IPC message filter.  A reference will be kept to the filter.
diff --git a/content/renderer/loader/navigation_body_loader.cc b/content/renderer/loader/navigation_body_loader.cc
index 48fbbdb..09a606a3 100644
--- a/content/renderer/loader/navigation_body_loader.cc
+++ b/content/renderer/loader/navigation_body_loader.cc
@@ -221,8 +221,7 @@
       std::move(response_head_), blink::PreviewsTypes::PREVIEWS_OFF);
 
   if (code_cache_host) {
-    code_cache_loader_ =
-        blink::WebCodeCacheLoader::CreateForFrame(code_cache_host);
+    code_cache_loader_ = blink::WebCodeCacheLoader::Create(code_cache_host);
     code_cache_loader_->FetchFromCodeCache(
         blink::mojom::CodeCacheType::kJavascript, original_url_,
         base::BindOnce(&NavigationBodyLoader::CodeCacheReceived,
diff --git a/content/test/data/accessibility/html/action-verbs-expected-auralinux.txt b/content/test/data/accessibility/html/action-verbs-expected-auralinux.txt
index be08a0a2..41a1d598 100644
--- a/content/test/data/accessibility/html/action-verbs-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/action-verbs-expected-auralinux.txt
@@ -33,4 +33,4 @@
 ++[push button] name='ARIA button with tab index' actions=(press)
 ++[push button] name='ARIA button with negative tab index' actions=(press)
 ++[section]
-++++[push button] name='ARIA button that is an active descendant' actions=(press)
\ No newline at end of file
+++++[push button] name='ARIA button that is an active descendant' actions=(press)
diff --git a/content/test/data/accessibility/html/action-verbs-expected-blink.txt b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
index 7940831..8d4beff5 100644
--- a/content/test/data/accessibility/html/action-verbs-expected-blink.txt
+++ b/content/test/data/accessibility/html/action-verbs-expected-blink.txt
@@ -31,8 +31,8 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='Summary'
 ++++++++++++++inlineTextBox name='Summary'
-++++++++genericContainer ignored invisible
-++++++++++staticText ignored name='Details'
+++++++++genericContainer ignored
+++++++++++staticText ignored invisible name='Details'
 ++++++popUpButton collapsed value='Pop-up button' defaultActionVerb=open haspopup=menu
 ++++++++menuListPopup invisible
 ++++++++++menuListOption name='Pop-up button' defaultActionVerb=select selected=true
@@ -59,4 +59,4 @@
 ++++++genericContainer activedescendantId=button
 ++++++++button name='ARIA button that is an active descendant' defaultActionVerb=press
 ++++++++++staticText name='ARIA button that is an active descendant'
-++++++++++++inlineTextBox name='ARIA button that is an active descendant'
\ No newline at end of file
+++++++++++++inlineTextBox name='ARIA button that is an active descendant'
diff --git a/content/test/data/accessibility/html/details-expected-blink.txt b/content/test/data/accessibility/html/details-expected-blink.txt
index acc009d..742e8504 100644
--- a/content/test/data/accessibility/html/details-expected-blink.txt
+++ b/content/test/data/accessibility/html/details-expected-blink.txt
@@ -8,8 +8,11 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='details tag'
 ++++++++++++++inlineTextBox name='details tag'
-++++++++genericContainer ignored invisible
+++++++++genericContainer ignored
+++++++++++staticText ignored invisible name='<newline>    '
+++++++++++staticText ignored invisible name='<newline>    '
 ++++++++++paragraph ignored invisible
+++++++++++staticText ignored invisible name='<newline>  '
 ++++++details
 ++++++++genericContainer ignored
 ++++++++++disclosureTriangle name='details tag open'
diff --git a/content/test/data/accessibility/html/landmark-expected-auralinux.txt b/content/test/data/accessibility/html/landmark-expected-auralinux.txt
index 376dbbe..64834fa4 100644
--- a/content/test/data/accessibility/html/landmark-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/landmark-expected-auralinux.txt
@@ -146,4 +146,4 @@
 ++++++[static] name='This should NOT have footer role.'
 ++[landmark] xml-roles:main
 ++++[section]
-++++++[static] name='This should NOT have footer role.'
\ No newline at end of file
+++++++[static] name='This should NOT have footer role.'
diff --git a/content/test/data/accessibility/html/landmark-expected-blink.txt b/content/test/data/accessibility/html/landmark-expected-blink.txt
index 9bce6f6..ebe9bb85 100644
--- a/content/test/data/accessibility/html/landmark-expected-blink.txt
+++ b/content/test/data/accessibility/html/landmark-expected-blink.txt
@@ -73,7 +73,7 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='Details'
 ++++++++++++++inlineTextBox name='Details'
-++++++++genericContainer ignored invisible
+++++++++genericContainer ignored
 ++++++++++headerAsNonLandmark ignored invisible
 ++++++group
 ++++++++headerAsNonLandmark
@@ -126,7 +126,7 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='Details'
 ++++++++++++++inlineTextBox name='Details'
-++++++++genericContainer ignored invisible
+++++++++genericContainer ignored
 ++++++++++genericContainer ignored invisible
 ++++++group
 ++++++++genericContainer ignored
@@ -178,7 +178,7 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='Details'
 ++++++++++++++inlineTextBox name='Details'
-++++++++genericContainer ignored invisible
+++++++++genericContainer ignored
 ++++++++++footerAsNonLandmark ignored invisible
 ++++++group
 ++++++++footerAsNonLandmark
@@ -231,7 +231,7 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='Details'
 ++++++++++++++inlineTextBox name='Details'
-++++++++genericContainer ignored invisible
+++++++++genericContainer ignored
 ++++++++++genericContainer ignored invisible
 ++++++group
 ++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/html/summary-expected-auralinux.txt b/content/test/data/accessibility/html/summary-expected-auralinux.txt
index 11d460e5..f5dcbab 100644
--- a/content/test/data/accessibility/html/summary-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/summary-expected-auralinux.txt
@@ -4,4 +4,4 @@
 ++++++[static] name='details tag'
 ++[panel]
 ++++[toggle button] name='name' description='details #2' description-from:summary
-++++++[static] name='details #2'
\ No newline at end of file
+++++++[static] name='details #2'
diff --git a/content/test/data/accessibility/html/summary-expected-blink.txt b/content/test/data/accessibility/html/summary-expected-blink.txt
index 7c2bc804..46c9434 100644
--- a/content/test/data/accessibility/html/summary-expected-blink.txt
+++ b/content/test/data/accessibility/html/summary-expected-blink.txt
@@ -8,8 +8,11 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='details tag'
 ++++++++++++++inlineTextBox name='details tag'
-++++++++genericContainer ignored invisible htmlTag='slot'
+++++++++genericContainer ignored htmlTag='slot'
+++++++++++staticText ignored invisible name='<newline>    '
+++++++++++staticText ignored invisible name='<newline>    '
 ++++++++++paragraph ignored invisible htmlTag='p'
+++++++++++staticText ignored invisible name='<newline>  '
 ++++++details htmlTag='details'
 ++++++++genericContainer ignored htmlTag='slot'
 ++++++++++disclosureTriangle collapsed description='details #2' htmlTag='summary' name='name' descriptionFrom=summary
@@ -17,5 +20,8 @@
 ++++++++++++++staticText ignored name='%E2%96%B8 '
 ++++++++++++staticText name='details #2'
 ++++++++++++++inlineTextBox name='details #2'
-++++++++genericContainer ignored invisible htmlTag='slot'
+++++++++genericContainer ignored htmlTag='slot'
+++++++++++staticText ignored invisible name='<newline>    '
+++++++++++staticText ignored invisible name='<newline>    '
 ++++++++++paragraph ignored invisible htmlTag='p'
+++++++++++staticText ignored invisible name='<newline>  '
diff --git a/content/test/test_blink_web_unit_test_support.h b/content/test/test_blink_web_unit_test_support.h
index ee2155f..162e999 100644
--- a/content/test/test_blink_web_unit_test_support.h
+++ b/content/test/test_blink_web_unit_test_support.h
@@ -71,7 +71,7 @@
 
   std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler_;
   bool threaded_animation_ = true;
-  bool use_zoom_for_dsf_ = false;
+  bool use_zoom_for_dsf_ = true;
   cc::TestTaskGraphRunner test_task_graph_runner_;
 
   base::WeakPtrFactory<TestBlinkWebUnitTestSupport> weak_factory_{this};
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 17bd43b8..6bf414b 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -25,7 +25,6 @@
 #include "content/utility/services.h"
 #include "content/utility/utility_blink_platform_with_sandbox_support_impl.h"
 #include "content/utility/utility_service_factory.h"
-#include "ipc/ipc_sync_channel.h"
 #include "mojo/public/cpp/bindings/binder_map.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/service_factory.h"
@@ -151,6 +150,7 @@
 UtilityThreadImpl::UtilityThreadImpl(base::RepeatingClosure quit_closure)
     : ChildThreadImpl(std::move(quit_closure),
                       ChildThreadImpl::Options::Builder()
+                          .WithLegacyIPCChannel(false)
                           .ServiceBinder(GetServiceBinder())
                           .ExposesInterfacesToBrowser()
                           .Build()) {
@@ -160,6 +160,7 @@
 UtilityThreadImpl::UtilityThreadImpl(const InProcessChildThreadParams& params)
     : ChildThreadImpl(base::DoNothing(),
                       ChildThreadImpl::Options::Builder()
+                          .WithLegacyIPCChannel(false)
                           .InBrowserProcess(params)
                           .ServiceBinder(GetServiceBinder())
                           .ExposesInterfacesToBrowser()
@@ -184,11 +185,11 @@
     return;
   }
 
-  // Close the channel to cause the UtilityProcessHost to be deleted. We need to
-  // take a different code path than the multi-process case because that case
+  // Disconnect from the UtilityProcessHost to cause it to be deleted. We need
+  // to take a different code path than the multi-process case because that case
   // depends on the child process going away to close the channel, but that
   // can't happen when we're in single process mode.
-  channel()->Close();
+  DisconnectChildProcessHost();
 }
 
 void UtilityThreadImpl::EnsureBlinkInitialized() {
diff --git a/device/vr/android/arcore/arcore_shim.cc b/device/vr/android/arcore/arcore_shim.cc
index ce11175..a2dae32 100644
--- a/device/vr/android/arcore/arcore_shim.cc
+++ b/device/vr/android/arcore/arcore_shim.cc
@@ -29,6 +29,7 @@
   DO(ArAugmentedImage_getTrackingMethod)                           \
   DO(ArAugmentedImageDatabase_addImageWithPhysicalSize)            \
   DO(ArAugmentedImageDatabase_create)                              \
+  DO(ArAugmentedImageDatabase_destroy)                             \
   DO(ArAugmentedImageDatabase_getNumImages)                        \
   DO(ArCamera_getDisplayOrientedPose)                              \
   DO(ArCamera_getProjectionMatrix)                                 \
@@ -288,6 +289,11 @@
       session, out_augmented_image_database);
 }
 
+void ArAugmentedImageDatabase_destroy(
+    ArAugmentedImageDatabase* augmented_image_database) {
+  g_arcore_api->impl_ArAugmentedImageDatabase_destroy(augmented_image_database);
+}
+
 void ArAugmentedImageDatabase_getNumImages(
     const ArSession* session,
     const ArAugmentedImageDatabase* augmented_image_database,
diff --git a/device/vr/android/arcore/scoped_arcore_objects.h b/device/vr/android/arcore/scoped_arcore_objects.h
index 6c8a08b..c7abfe7 100644
--- a/device/vr/android/arcore/scoped_arcore_objects.h
+++ b/device/vr/android/arcore/scoped_arcore_objects.h
@@ -14,7 +14,11 @@
 template <class T>
 struct ScopedGenericArObject {
   static T InvalidValue() { return nullptr; }
-  static void Free(T object) {}
+
+  // Implementation not provided by design - this will cause linker errors if a
+  // ScopedArCoreObject<T> is used for T that does not have a template
+  // specialization defining the Free() method.
+  static void Free(T object);
 };
 
 template <>
@@ -74,6 +78,30 @@
 }
 
 template <>
+void inline ScopedGenericArObject<ArAugmentedImageDatabase*>::Free(
+    ArAugmentedImageDatabase* ar_augmented_image_database) {
+  ArAugmentedImageDatabase_destroy(ar_augmented_image_database);
+}
+
+template <>
+void inline ScopedGenericArObject<ArLightEstimate*>::Free(
+    ArLightEstimate* ar_light_estimate) {
+  ArLightEstimate_destroy(ar_light_estimate);
+}
+
+template <>
+void inline ScopedGenericArObject<ArAnchorList*>::Free(
+    ArAnchorList* ar_anchor_list) {
+  ArAnchorList_destroy(ar_anchor_list);
+}
+
+template <>
+void inline ScopedGenericArObject<ArCameraIntrinsics*>::Free(
+    ArCameraIntrinsics* ar_camera_intrinsics) {
+  ArCameraIntrinsics_destroy(ar_camera_intrinsics);
+}
+
+template <>
 void inline ScopedGenericArObject<ArAnchor*>::Free(ArAnchor* ar_anchor) {
   ArAnchor_release(ar_anchor);
 }
diff --git a/docs/user_handle_mapping.md b/docs/user_handle_mapping.md
index 0c55f8d..5424c70 100644
--- a/docs/user_handle_mapping.md
+++ b/docs/user_handle_mapping.md
@@ -1,114 +1,49 @@
 For Chromium contributors that have different nicks on other domains.
 
-| **@chromium.org** | **IRC nick(s)** | **@google.com** |
-|:------------------|:----------------|:----------------|
-| aa                | aboodman        | aa              |
-| abw               | abw-cr          | abw             |
-| acleung           | acleung         | acleung         |
-| adamk             | aklein          | adamk           |
-| ajwong            | awong           | ajwong          |
-| aluebs            | aluebs          | aluebs          |
-| amanda            | awalker         | awalker         |
-| amit              | joshia          | joshia          |
-| amstan            | amstan          | amstan          |
-| ananta            | iyengar         | iyengar         |
-| anantha           | anantha         | ananthak        |
-| avi               | motownavi       | avi             |
-| ben               | beng            | beng            |
-| benhansen         | benhansen       | benhansen       |
-| benhenry          | benry           | benhenry        |
-| bnutter           |                 | bnutter         |
-| bxx               | bxs             | bxx             |
-| ccameron          | ccameron        | ccameron        |
-| csharp            | csharp1         | csharp          |
-| cthomp            | cthomp          | cthomp          |
-| darin, fishd      | fishd           | darin           |
-| dbaron            |                 | ldavidbaron     |
-| dbeam             | danbeam         | dbeam           |
-| dmurph            | dmurph          | dmurph          |
-| dom               | domfarolino     | domfarolino     |
-| dougt             | dougt           | dft             |
-| eaugusti          | eriq            | eaugustine      |
-| erg               | eglaysher       | erg             |
-| eroman            | eroman          | ericroman       |
-| esprehn           | esprehn         | esprehn         |
-| evan              | evmar           | evanm           |
-| feng              | feng            | fqian           |
-| fmeawad           | fmeawad-cr      | fmeawad         |
-| gab               | gabc            | gab             |
-| gsathya           | gsathya         | gunasekaran     |
-| hans              | hwennborg       | hwennborg       |
-| haven             | periodic        | haven           |
-| ian               | ifette          | ifette          |
-| inferno           | inferno         | aarya           |
-| iannucci          | iannucci        | iannucci        |
-| jaikk             |                 | jaikk           |
-| jansson           | jansson         | jansson         |
-| janx              | janx            | janx            |
-| jam               | jam2            | jabdelmalek     |
-| jchaffraix        | jchaffraix      | jchaffraix      |
-| jeremy            | jeremymos       | playmobil       |
-| jln               | julien\`        | jln             |
-| jochen            | jochen\_\_      | eisinger        |
-| johnchen          |                 | zhanliang       |
-| johnnyg           | johnny\_g       | johnnyg         |
-| joi               | joisig          | joi             |
-| jonross           | jonrossca       | jonross         |
-| jshin             | jshin           | jungshik        |
-| jww               | jww\_\_         | jww             |
-| jyasskin          | jyasskin        | jyasskin        |
-| katie             |                 | katydek         |
-| karen             | kareng          | kareng          |
-| keescook          | kees            | keescook        |
-| koz               |                 | jameskozianski  |
-| kuchhal           | kuchhal         | rahulk          |
-| levin             | dave\_levin     | levin           |
-| lfg               | lfg\_           | lfg             |
-| littledan         | littledan       | dehrenberg      |
-| loonybear         | loonybear       | lunalu          |
-| luken             | luken_chromium  | luken           |
-| mark              | markmentovai    | mmentovai       |
-| mbarbella         | mbarbella       | mbarbella       |
-| mmeade            | mmeade          | mmeade          |
-| mednik            | mednik          | mednik          |
-| mgaba             | mgaba           | mgaba           |
-| mlinck            | dullb0yj4ck     | mlinck          |
-| msw               | msw\_           | msw             |
-| nick              | nickcarter      | ncarter         |
-| oleg              |                 | olege           |
-| ortuno            | ortuno          | ortuno          |
-| pam               | pamg            | pamg            |
-| paulirish         | paul\_irish      | paulirish       |
-| patrick           | pjohnson        | pjohnson        |
-| peter             | beverloo        | beverloo        |
-| phajdan.jr        | phajdan-jr      | phajdan         |
-| pwnall            | pwnall          | costan          |
-| rch               | RyanHamilton    | rch             |
-| rdevlin.cronin    | rdcronin        | rdcronin        |
-| rlp               | rpetterson      | rlp             |
-| robliao           | robliao         | robliao         |
-| rsleevi           | sleevi, rsleevi | sleevi          |
-| sarah             |                 | sarahgordon     |
-| satish            | satish\_        | satish          |
-| scheglov          |                 | scheglov        |
-| scottbyer         | sbyer           | scottbyer       |
-| sdy               | sdy, sidney, Sidnicious | sdy     |
-| shans             |                 | shanestephens   |
-| shrike            | shrike          | shrike          |
-| smut              | Sana            | smut            |
-| svaldez           | dvorak42, svaldez | svaldez         |
-| tansell           | mithro@mithis.com | tansell         |
-| thestig           | leiz            | thestig         |
-| tim               | timsteele       | timsteele       |
-| tony              | tony^work       | tc              |
-| tonyg             | tonyg-cr        | tonyg           |
-| tyoshino          | tyoshino        | tyoshino        |
-| vabr              | vabr            | vabr            |
-| vadimt            | vadimt          | vadimt          |
-| viettrungluu      | trungl          | vtl             |
-| wad               | redpig          | drewry          |
-| wez               | real\_wez       | wez             |
-| wjmaclean         | seumas, wjmaclean | wjmaclean, wjm, seumas |
-| yoz               | yaws            | yoz             |
-| zmo               | zhenyao         | zmo             |
-| robertma          | Hexcles         | robertma        |
+| **@chromium.org** | **@google.com** |
+|:------------------|:----------------|
+| amanda            | awalker         |
+| amit              | joshia          |
+| ananta            | iyengar         |
+| anantha           | ananthak        |
+| ben               | beng            |
+| darin, fishd      | darin           |
+| dbaron            | ldavidbaron     |
+| dom               | domfarolino     |
+| dougt             | dft             |
+| eaugusti          | eaugustine      |
+| eroman            | ericroman       |
+| evan              | evanm           |
+| feng              | fqian           |
+| gsathya           | gunasekaran     |
+| hans              | hwennborg       |
+| ian               | ifette          |
+| inferno           | aarya           |
+| jam               | jabdelmalek     |
+| jeremy            | playmobil       |
+| jochen            | eisinger        |
+| johnchen          | zhanliang       |
+| jshin             | jungshik        |
+| katie             | katydek         |
+| karen             | kareng          |
+| koz               | jameskozianski  |
+| kuchhal           | rahulk          |
+| littledan         | dehrenberg      |
+| loonybear         | lunalu          |
+| mark              | mmentovai       |
+| nick              | ncarter         |
+| oleg              | olege           |
+| pam               | pamg            |
+| patrick           | pjohnson        |
+| peter             | beverloo        |
+| phajdan.jr        | phajdan         |
+| pwnall            | costan          |
+| rdevlin.cronin    | rdcronin        |
+| rsleevi           | sleevi          |
+| sarah             | sarahgordon     |
+| shans             | shanestephens   |
+| tim               | timsteele       |
+| tony              | tc              |
+| viettrungluu      | vtl             |
+| wad               | drewry          |
+| wjmaclean         | wjmaclean, wjm, seumas |
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index a241ea78..3443912 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -55,6 +55,9 @@
     # TODO(ghazale): anything under api/ should be moved out of this target.
     "api/activity_log/web_request_constants.cc",
     "api/activity_log/web_request_constants.h",
+    "api/api_resource.cc",
+    "api/api_resource.h",
+    "api/api_resource_manager.h",
     "api/declarative/declarative_api.cc",
     "api/declarative/declarative_api.h",
     "api/declarative/declarative_rule.h",
@@ -126,6 +129,38 @@
     "api/declarative_webrequest/webrequest_constants.h",
     "api/declarative_webrequest/webrequest_rules_registry.cc",
     "api/declarative_webrequest/webrequest_rules_registry.h",
+    "api/device_permissions_manager.cc",
+    "api/device_permissions_manager.h",
+    "api/device_permissions_prompt.cc",
+    "api/device_permissions_prompt.h",
+    "api/execute_code_function.cc",
+    "api/execute_code_function.h",
+    "api/extensions_api_client.cc",
+    "api/extensions_api_client.h",
+    "api/guest_view/app_view/app_view_guest_internal_api.cc",
+    "api/guest_view/app_view/app_view_guest_internal_api.h",
+    "api/guest_view/guest_view_internal_api.cc",
+    "api/guest_view/guest_view_internal_api.h",
+    "api/guest_view/web_view/web_view_internal_api.cc",
+    "api/guest_view/web_view/web_view_internal_api.h",
+    "api/hid/hid_api.cc",
+    "api/hid/hid_api.h",
+    "api/hid/hid_connection_resource.cc",
+    "api/hid/hid_connection_resource.h",
+    "api/hid/hid_device_manager.cc",
+    "api/hid/hid_device_manager.h",
+    "api/system_display/display_info_provider.cc",
+    "api/system_display/display_info_provider.h",
+    "api/system_display/system_display_api.cc",
+    "api/system_display/system_display_api.h",
+    "api/usb/usb_api.cc",
+    "api/usb/usb_api.h",
+    "api/usb/usb_device_manager.cc",
+    "api/usb/usb_device_manager.h",
+    "api/usb/usb_device_resource.cc",
+    "api/usb/usb_device_resource.h",
+    "api/web_contents_capture_client.cc",
+    "api/web_contents_capture_client.h",
     "api/web_request/form_data_parser.cc",
     "api/web_request/form_data_parser.h",
     "api/web_request/permission_helper.cc",
@@ -512,6 +547,7 @@
     "//content/public/common",
     "//crypto:platform",
     "//extensions:extensions_browser_resources",
+    "//extensions/browser/api/virtual_keyboard_private:virtual_keyboard_delegate",
     "//extensions/browser/guest_view/web_view/web_ui",
     "//extensions/buildflags",
     "//extensions/common",
@@ -553,6 +589,7 @@
     "//extensions/browser/kiosk",
     "//extensions/browser/value_store",
     "//ipc",
+    "//services/device/public/cpp/usb:usb",
     "//third_party/re2",
   ]
 
diff --git a/extensions/browser/PRESUBMIT.py b/extensions/browser/PRESUBMIT.py
index 98d9cc9d..5ebdba9 100644
--- a/extensions/browser/PRESUBMIT.py
+++ b/extensions/browser/PRESUBMIT.py
@@ -8,6 +8,8 @@
 for more details on the presubmit API built into depot_tools.
 """
 
+USE_PYTHON3 = True
+
 import sys
 
 def _CreateHistogramValueChecker(input_api, output_api, path):
diff --git a/extensions/browser/api/BUILD.gn b/extensions/browser/api/BUILD.gn
index fad106b..3845583 100644
--- a/extensions/browser/api/BUILD.gn
+++ b/extensions/browser/api/BUILD.gn
@@ -12,34 +12,11 @@
 
 source_set("api") {
   sources = [
-    "api_resource.cc",
-    "api_resource.h",
-    "api_resource_manager.h",
     "async_api_function.cc",
     "async_api_function.h",
-    "device_permissions_manager.cc",
-    "device_permissions_manager.h",
-    "device_permissions_prompt.cc",
-    "device_permissions_prompt.h",
-    "execute_code_function.cc",
-    "execute_code_function.h",
-    "extensions_api_client.cc",
-    "extensions_api_client.h",
-    "guest_view/app_view/app_view_guest_internal_api.cc",
-    "guest_view/app_view/app_view_guest_internal_api.h",
-    "guest_view/guest_view_internal_api.cc",
-    "guest_view/guest_view_internal_api.h",
-    "guest_view/web_view/web_view_internal_api.cc",
-    "guest_view/web_view/web_view_internal_api.h",
 
-    # TODO(crbug.com/1206265): anything under hid/, storage/, system_display/
-    # and usb/ should be moved out of this target.
-    "hid/hid_api.cc",
-    "hid/hid_api.h",
-    "hid/hid_connection_resource.cc",
-    "hid/hid_connection_resource.h",
-    "hid/hid_device_manager.cc",
-    "hid/hid_device_manager.h",
+    # TODO(crbug.com/1206265): anything under storage/ should be moved out of
+    # this target.
     "storage/backend_task_runner.cc",
     "storage/backend_task_runner.h",
     "storage/local_value_store_cache.cc",
@@ -59,55 +36,27 @@
     "storage/value_store_cache.h",
     "storage/weak_unlimited_settings_storage.cc",
     "storage/weak_unlimited_settings_storage.h",
-    "system_display/display_info_provider.cc",
-    "system_display/display_info_provider.h",
-    "system_display/system_display_api.cc",
-    "system_display/system_display_api.h",
-    "usb/usb_api.cc",
-    "usb/usb_api.h",
-    "usb/usb_device_manager.cc",
-    "usb/usb_device_manager.h",
-    "usb/usb_device_resource.cc",
-    "usb/usb_device_resource.h",
-    "web_contents_capture_client.cc",
-    "web_contents_capture_client.h",
-  ]
-
-  configs += [
-    # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-    "//build/config/compiler:no_size_t_to_int_warning",
   ]
 
   public_deps = [
     "//base",
     "//content/public/browser",
     "//content/public/common",
-    "//extensions/browser:browser_sources",
     "//extensions/common",
     "//extensions/common/api",
     "//ipc",
-    "//services/device/public/cpp/usb:usb",
   ]
 
   deps = [
     "//base:i18n",
     "//build:chromeos_buildflags",
-    "//components/guest_view/browser:browser",
-    "//components/guest_view/common:common",
     "//components/keyed_service/content:content",
-    "//content/public/browser",
-    "//content/public/common",
     "//extensions/browser:browser_sources",
-    "//extensions/browser/api/virtual_keyboard_private:virtual_keyboard_delegate",
-    "//extensions/browser/guest_view/web_view/web_ui:web_ui",
-    "//extensions/common",
     "//extensions/common:mojom",
     "//extensions/common/api",
     "//extensions/strings",
     "//services/device/public/cpp/hid",
-    "//services/device/public/cpp/usb",
     "//services/device/public/mojom",
-    "//services/device/public/mojom:usb",
   ]
 
   # TODO(michaelpg): Move these deps to the individual APIs that require them.
diff --git a/extensions/common/api/PRESUBMIT.py b/extensions/common/api/PRESUBMIT.py
index ded0ec9c..bdc75b4 100644
--- a/extensions/common/api/PRESUBMIT.py
+++ b/extensions/common/api/PRESUBMIT.py
@@ -8,6 +8,8 @@
 for more details on the presubmit API built into depot_tools.
 """
 
+USE_PYTHON3 = True
+
 import sys
 
 
diff --git a/extensions/common/api/externs_checker.py b/extensions/common/api/externs_checker.py
index 09a97bb1..55ff78f 100644
--- a/extensions/common/api/externs_checker.py
+++ b/extensions/common/api/externs_checker.py
@@ -15,7 +15,7 @@
     self._output_api = output_api
     self._api_pairs = api_pairs
 
-    for path in api_pairs.keys() + api_pairs.values():
+    for path in list(api_pairs.keys()) + list(api_pairs.values()):
       if not input_api.os_path.exists(path):
         raise OSError('Path Not Found: %s' % path)
 
diff --git a/extensions/common/permissions/PRESUBMIT.py b/extensions/common/permissions/PRESUBMIT.py
index f767c72..6bd9746 100644
--- a/extensions/common/permissions/PRESUBMIT.py
+++ b/extensions/common/permissions/PRESUBMIT.py
@@ -7,6 +7,9 @@
 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
 for more details on the presubmit API built into depot_tools.
 """
+
+USE_PYTHON3 = True
+
 import sys
 
 def _CreateAPIPermissionIDChecker(input_api, output_api):
diff --git a/extensions/renderer/resources/automation/PRESUBMIT.py b/extensions/renderer/resources/automation/PRESUBMIT.py
new file mode 100644
index 0000000..11dd39a
--- /dev/null
+++ b/extensions/renderer/resources/automation/PRESUBMIT.py
@@ -0,0 +1,39 @@
+# 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.
+
+"""Presubmit script for files in extensions/renderer/resources/automation.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+def _CheckWebDevStyle(input_api, output_api):
+  results = []
+
+  try:
+    import sys
+    old_sys_path = sys.path[:]
+    cwd = input_api.PresubmitLocalPath()
+    sys.path += [input_api.os_path.join(cwd, '../..', '..', '..', 'tools')]
+    from web_dev_style import presubmit_support
+    results += presubmit_support.CheckStyle(input_api, output_api)
+  finally:
+    sys.path = old_sys_path
+
+  return results
+
+
+def _CheckChangeOnUploadOrCommit(input_api, output_api):
+  results = _CheckWebDevStyle(input_api, output_api)
+  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api,
+                                                         check_js=True)
+  return results
+
+
+def CheckChangeOnUpload(input_api, output_api):
+  return _CheckChangeOnUploadOrCommit(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+  return _CheckChangeOnUploadOrCommit(input_api, output_api)
diff --git a/extensions/renderer/resources/automation/automation_custom_bindings.js b/extensions/renderer/resources/automation/automation_custom_bindings.js
index 789f5a84..e423be2 100644
--- a/extensions/renderer/resources/automation/automation_custom_bindings.js
+++ b/extensions/renderer/resources/automation/automation_custom_bindings.js
@@ -3,23 +3,22 @@
 // found in the LICENSE file.
 
 // Custom bindings for the automation API.
-var AutomationRootNode = require('automationNode').AutomationRootNode;
-var automationInternal = getInternalApi('automationInternal');
-var exceptionHandler = require('uncaught_exception_handler');
-var logging = requireNative('logging');
-var nativeAutomationInternal = requireNative('automationInternal');
-var DestroyAccessibilityTree =
+const AutomationRootNode = require('automationNode').AutomationRootNode;
+const automationInternal = getInternalApi('automationInternal');
+const exceptionHandler = require('uncaught_exception_handler');
+const logging = requireNative('logging');
+const nativeAutomationInternal = requireNative('automationInternal');
+const DestroyAccessibilityTree =
     nativeAutomationInternal.DestroyAccessibilityTree;
-var StartCachingAccessibilityTrees =
+const StartCachingAccessibilityTrees =
     nativeAutomationInternal.StartCachingAccessibilityTrees;
-var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver;
-var RemoveTreeChangeObserver =
+const AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver;
+const RemoveTreeChangeObserver =
     nativeAutomationInternal.RemoveTreeChangeObserver;
-var GetFocusNative = nativeAutomationInternal.GetFocus;
-var GetAccessibilityFocusNative =
+const GetFocusNative = nativeAutomationInternal.GetFocus;
+const GetAccessibilityFocusNative =
     nativeAutomationInternal.GetAccessibilityFocus;
-var SetDesktopID =
-    nativeAutomationInternal.SetDesktopID;
+const SetDesktopID = nativeAutomationInternal.SetDesktopID;
 
 /**
  * A namespace to export utility functions to other files in automation.
@@ -27,22 +26,24 @@
 window.automationUtil = function() {};
 
 // TODO(aboxhall): Look into using WeakMap
-var idToCallback = {};
+const idToCallback = {};
 
-var desktopId = undefined;
+let desktopId = undefined;
 
 automationUtil.storeTreeCallback = function(id, callback) {
-  if (!callback)
+  if (!callback) {
     return;
+  }
 
-  var targetTree = AutomationRootNode.get(id);
+  const targetTree = AutomationRootNode.get(id);
   if (!targetTree) {
     // If we haven't cached the tree, hold the callback until the tree is
     // populated by the initial onAccessibilityEvent call.
-    if (id in idToCallback)
+    if (id in idToCallback) {
       idToCallback[id].push(callback);
-    else
+    } else {
       idToCallback[id] = [callback];
+    }
   } else {
     callback(targetTree);
   }
@@ -61,10 +62,10 @@
 automationUtil.nextTreeChangeObserverId = 1;
 
 apiBridge.registerCustomHook(function(bindingsAPI) {
-  var apiFunctions = bindingsAPI.apiFunctions;
+  const apiFunctions = bindingsAPI.apiFunctions;
 
   // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj.
-automationUtil.tabIDToAutomationNode = {};
+  automationUtil.tabIDToAutomationNode = {};
   apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) {
     StartCachingAccessibilityTrees();
 
@@ -80,7 +81,7 @@
       return;
     }
 
-    var params = { tabID: tabID };
+    const params = {tabID: tabID};
     automationInternal.enableTab(params,
                                  function onEnable(treeID, resultTabID) {
           if (bindingUtil.hasLastError()) {
@@ -94,11 +95,12 @@
         });
   });
 
-  var desktopTree = null;
+  let desktopTree = null;
   apiFunctions.setHandleRequest('getDesktop', function(callback) {
     StartCachingAccessibilityTrees();
-    if (desktopId !== undefined)
+    if (desktopId !== undefined) {
       desktopTree = AutomationRootNode.get(desktopId);
+    }
     if (!desktopTree) {
       automationInternal.enableDesktop(function(treeId) {
         if (bindingUtil.hasLastError()) {
@@ -122,12 +124,12 @@
   });
 
   apiFunctions.setHandleRequest('getFocus', function(callback) {
-    var focusedNodeInfo = GetFocusNative();
+    const focusedNodeInfo = GetFocusNative();
     if (!focusedNodeInfo) {
       callback(null);
       return;
     }
-    var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
+    const tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
     if (tree) {
       callback(privates(tree).impl.get(focusedNodeInfo.nodeId));
       return;
@@ -135,18 +137,19 @@
   });
 
   apiFunctions.setHandleRequest('getAccessibilityFocus', function(callback) {
-    var focusedNodeInfo = GetAccessibilityFocusNative();
+    const focusedNodeInfo = GetAccessibilityFocusNative();
     if (!focusedNodeInfo) {
       callback(null);
       return;
     }
-    var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
-    if (tree)
+    const tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
+    if (tree) {
       callback(privates(tree).impl.get(focusedNodeInfo.nodeId));
+    }
   });
 
   function removeTreeChangeObserver(observer) {
-    for (var id in automationUtil.treeChangeObserverMap) {
+    for (const id in automationUtil.treeChangeObserverMap) {
       if (automationUtil.treeChangeObserverMap[id] == observer) {
         RemoveTreeChangeObserver(id);
         delete automationUtil.treeChangeObserverMap[id];
@@ -160,7 +163,7 @@
 
   function addTreeChangeObserver(filter, observer) {
     removeTreeChangeObserver(observer);
-    var id = automationUtil.nextTreeChangeObserverId++;
+    const id = automationUtil.nextTreeChangeObserverId++;
     AddTreeChangeObserver(id, filter);
     automationUtil.treeChangeObserverMap[id] = observer;
   }
@@ -170,10 +173,11 @@
   });
 
   apiFunctions.setHandleRequest('setDocumentSelection', function(params) {
-    var anchorNodeImpl = privates(params.anchorObject).impl;
-    var focusNodeImpl = privates(params.focusObject).impl;
-    if (anchorNodeImpl.treeID !== focusNodeImpl.treeID)
+    const anchorNodeImpl = privates(params.anchorObject).impl;
+    const focusNodeImpl = privates(params.focusObject).impl;
+    if (anchorNodeImpl.treeID !== focusNodeImpl.treeID) {
       throw new Error('Selection anchor and focus must be in the same tree.');
+    }
     if (anchorNodeImpl.treeID === desktopId) {
       throw new Error('Use AutomationNode.setSelection to set the selection ' +
           'in the desktop tree.');
@@ -185,16 +189,16 @@
                                        anchorOffset: params.anchorOffset,
                                        focusOffset: params.focusOffset });
   });
-
 });
 
 automationInternal.onChildTreeID.addListener(function(childTreeId) {
-  var targetTree = AutomationRootNode.get(childTreeId);
+  const targetTree = AutomationRootNode.get(childTreeId);
 
   // If the tree is already loded, or if we previously requested it be loaded
   // (i.e. have a callback for it), don't try to do so again.
-  if (targetTree || idToCallback[childTreeId])
+  if (targetTree || idToCallback[childTreeId]) {
     return;
+  }
 
   // A WebView in the desktop tree has a different AX tree as its child.
   // When we encounter a WebView with a child AX tree id that we don't
@@ -212,21 +216,22 @@
   automationInternal.enableTree(childTreeId);
 });
 
-automationInternal.onTreeChange.addListener(function(observerID,
-                                                     treeID,
-                                                     nodeID,
-                                                     changeType) {
-  var tree = AutomationRootNode.getOrCreate(treeID);
-  if (!tree)
+automationInternal.onTreeChange.addListener(function(
+    observerID, treeID, nodeID, changeType) {
+  const tree = AutomationRootNode.getOrCreate(treeID);
+  if (!tree) {
     return;
+  }
 
-  var node = privates(tree).impl.get(nodeID);
-  if (!node)
+  const node = privates(tree).impl.get(nodeID);
+  if (!node) {
     return;
+  }
 
-  var observer = automationUtil.treeChangeObserverMap[observerID];
-  if (!observer)
+  const observer = automationUtil.treeChangeObserverMap[observerID];
+  if (!observer) {
     return;
+  }
 
   try {
     observer({target: node, type: changeType});
@@ -237,11 +242,12 @@
 });
 
 automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) {
-  var tree = AutomationRootNode.getOrCreate(treeID);
-  if (!tree)
+  const tree = AutomationRootNode.getOrCreate(treeID);
+  if (!tree) {
     return;
+  }
 
-  for (var i = 0; i < nodeIDs.length; i++) {
+  for (let i = 0; i < nodeIDs.length; i++) {
     privates(tree).impl.remove(nodeIDs[i]);
   }
 });
@@ -251,33 +257,36 @@
  * corresponding AutomationNode.
  */
 automationInternal.onAccessibilityEvent.addListener(function(eventParams) {
-  var id = eventParams.treeID;
-  var targetTree = AutomationRootNode.getOrCreate(id);
+  const id = eventParams.treeID;
+  const targetTree = AutomationRootNode.getOrCreate(id);
   if (eventParams.eventType == 'mediaStartedPlaying' ||
       eventParams.eventType == 'mediaStoppedPlaying') {
     // These events are global to the tree.
     eventParams.targetID = privates(targetTree).impl.id;
   }
 
-  if (!privates(targetTree).impl.onAccessibilityEvent(eventParams))
+  if (!privates(targetTree).impl.onAccessibilityEvent(eventParams)) {
     return;
+  }
 
   // If we're not waiting on a callback to getTree(), we can early out here.
-  if (!(id in idToCallback))
+  if (!(id in idToCallback)) {
     return;
+  }
 
   // We usually get a 'placeholder' tree first, which doesn't have any url
   // attribute or child nodes. If we've got that, wait for the full tree before
   // calling the callback.
   // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553)
-  if (id != desktopId && !targetTree.url && targetTree.children.length == 0)
+  if (id != desktopId && !targetTree.url && targetTree.children.length == 0) {
     return;
+  }
 
   // If the tree wasn't available when getTree() was called, the callback will
   // have been cached in idToCallback, so call and delete it now that we
   // have the complete tree.
-  for (var i = 0; i < idToCallback[id].length; i++) {
-    var callback = idToCallback[id][i];
+  for (let i = 0; i < idToCallback[id].length; i++) {
+    const callback = idToCallback[id][i];
     callback(targetTree);
   }
   delete idToCallback[id];
@@ -285,11 +294,11 @@
 
 automationInternal.onAccessibilityTreeDestroyed.addListener(function(id) {
   // Destroy the AutomationRootNode.
-  var targetTree = AutomationRootNode.get(id);
+  const targetTree = AutomationRootNode.get(id);
   if (targetTree) {
     privates(targetTree).impl.destroy();
     AutomationRootNode.destroy(id);
-    for (var tabID in automationUtil.tabIDToAutomationNode) {
+    for (const tabID in automationUtil.tabIDToAutomationNode) {
       if (automationUtil.tabIDToAutomationNode[tabID] == targetTree) {
         delete automationUtil.tabIDToAutomationNode[tabID];
       }
@@ -309,17 +318,19 @@
 
 automationInternal.onActionResult.addListener(function(
     treeID, requestID, result) {
-  var targetTree = AutomationRootNode.get(treeID);
-  if (!targetTree)
+  const targetTree = AutomationRootNode.get(treeID);
+  if (!targetTree) {
     return;
+  }
 
   privates(targetTree).impl.onActionResult(requestID, result);
 });
 
 automationInternal.onGetTextLocationResult.addListener(function(
     textLocationParams) {
-  var targetTree = AutomationRootNode.get(textLocationParams.treeID);
-  if (!targetTree)
+  const targetTree = AutomationRootNode.get(textLocationParams.treeID);
+  if (!targetTree) {
     return;
+  }
   privates(targetTree).impl.onGetTextLocationResult(textLocationParams);
 });
diff --git a/extensions/renderer/resources/automation/automation_event.js b/extensions/renderer/resources/automation/automation_event.js
index f107941..0781cfb2 100644
--- a/extensions/renderer/resources/automation/automation_event.js
+++ b/extensions/renderer/resources/automation/automation_event.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var utils = require('utils');
+const utils = require('utils');
 
 function AutomationEventImpl(
     type, target, eventFrom, eventFromAction, mouseX, mouseY, intents) {
diff --git a/extensions/renderer/resources/automation/automation_node.js b/extensions/renderer/resources/automation/automation_node.js
index dc723bf0..361954b47 100644
--- a/extensions/renderer/resources/automation/automation_node.js
+++ b/extensions/renderer/resources/automation/automation_node.js
@@ -2,20 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var AutomationEvent = require('automationEvent').AutomationEvent;
-var automationInternal = getInternalApi('automationInternal');
-var AutomationTreeCache = require('automationTreeCache').AutomationTreeCache;
-var exceptionHandler = require('uncaught_exception_handler');
+const AutomationEvent = require('automationEvent').AutomationEvent;
+const automationInternal = getInternalApi('automationInternal');
+const AutomationTreeCache = require('automationTreeCache').AutomationTreeCache;
+const exceptionHandler = require('uncaught_exception_handler');
 
-var natives = requireNative('automationInternal');
+const natives = requireNative('automationInternal');
 
-var IsInteractPermitted = natives.IsInteractPermitted;
+const IsInteractPermitted = natives.IsInteractPermitted;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The id of the root node.
  */
-var GetRootID = natives.GetRootID;
+const GetRootID = natives.GetRootID;
 
 /**
  * Similar to above, but may move to ancestor roots if the current tree
@@ -23,75 +23,74 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {{treeID: string, nodeID: number}}
  */
-var GetPublicRoot = natives.GetPublicRoot;
+const GetPublicRoot = natives.GetPublicRoot;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The title of the document.
  */
-var GetDocTitle = natives.GetDocTitle;
+const GetDocTitle = natives.GetDocTitle;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The url of the document.
  */
-var GetDocURL = natives.GetDocURL;
+const GetDocURL = natives.GetDocURL;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?boolean} True if the document has finished loading.
  */
-var GetDocLoaded = natives.GetDocLoaded;
+const GetDocLoaded = natives.GetDocLoaded;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The loading progress, from 0.0 to 1.0 (fully loaded).
  */
-var GetDocLoadingProgress =
-    natives.GetDocLoadingProgress;
+const GetDocLoadingProgress = natives.GetDocLoadingProgress;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {boolean} Whether the selection's anchor comes after its focus in the
  *     accessibility tree.
  */
-var GetIsSelectionBackward = natives.GetIsSelectionBackward;
+const GetIsSelectionBackward = natives.GetIsSelectionBackward;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The ID of the selection anchor object.
  */
-var GetAnchorObjectID = natives.GetAnchorObjectID;
+const GetAnchorObjectID = natives.GetAnchorObjectID;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The selection anchor offset.
  */
-var GetAnchorOffset = natives.GetAnchorOffset;
+const GetAnchorOffset = natives.GetAnchorOffset;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The selection anchor affinity.
  */
-var GetAnchorAffinity = natives.GetAnchorAffinity;
+const GetAnchorAffinity = natives.GetAnchorAffinity;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The ID of the selection focus object.
  */
-var GetFocusObjectID = natives.GetFocusObjectID;
+const GetFocusObjectID = natives.GetFocusObjectID;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The selection focus offset.
  */
-var GetFocusOffset = natives.GetFocusOffset;
+const GetFocusOffset = natives.GetFocusOffset;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The selection focus affinity.
  */
-var GetFocusAffinity = natives.GetFocusAffinity;
+const GetFocusAffinity = natives.GetFocusAffinity;
 
 /**
  * The start of the selection always comes before its end in the accessibility
@@ -100,7 +99,7 @@
  * @return {?number} The ID of the object at the start of the
  *     selection.
  */
-var GetSelectionStartObjectID = natives.GetSelectionStartObjectID;
+const GetSelectionStartObjectID = natives.GetSelectionStartObjectID;
 
 /**
  * The start of the selection always comes before its end in the accessibility
@@ -108,7 +107,7 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The offset at the start of the selection.
  */
-var GetSelectionStartOffset = natives.GetSelectionStartOffset;
+const GetSelectionStartOffset = natives.GetSelectionStartOffset;
 
 /**
  * The start of the selection always comes before its end in the accessibility
@@ -116,7 +115,7 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The affinity at the start of the selection.
  */
-var GetSelectionStartAffinity = natives.GetSelectionStartAffinity;
+const GetSelectionStartAffinity = natives.GetSelectionStartAffinity;
 
 /**
  * The end of the selection always comes after its start in the accessibility
@@ -124,7 +123,7 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The ID of the object at the end of the selection.
  */
-var GetSelectionEndObjectID = natives.GetSelectionEndObjectID;
+const GetSelectionEndObjectID = natives.GetSelectionEndObjectID;
 
 /**
  * The end of the selection always comes after its start in the accessibility
@@ -132,7 +131,7 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?number} The offset at the end of the selection.
  */
-var GetSelectionEndOffset = natives.GetSelectionEndOffset;
+const GetSelectionEndOffset = natives.GetSelectionEndOffset;
 
 /**
  * The end of the selection always comes after its start in the accessibility
@@ -140,7 +139,7 @@
  * @param {string} axTreeID The id of the accessibility tree.
  * @return {?string} The affinity at the end of the selection.
  */
-var GetSelectionEndAffinity = natives.GetSelectionEndAffinity;
+const GetSelectionEndAffinity = natives.GetSelectionEndAffinity;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -148,7 +147,7 @@
  * @return {?number} The id of the node's parent, or undefined if it's the
  *    root of its tree or if the tree or node wasn't found.
  */
-var GetParentID = natives.GetParentID;
+const GetParentID = natives.GetParentID;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -156,7 +155,7 @@
  * @return {?number} The number of children of the node, or undefined if
  *     the tree or node wasn't found.
  */
-var GetChildCount = natives.GetChildCount;
+const GetChildCount = natives.GetChildCount;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -165,7 +164,7 @@
  * @return {?number} The id of the child at the given index, or undefined
  *     if the tree or node or child at that index wasn't found.
  */
-var GetChildIDAtIndex = natives.GetChildIDAtIndex;
+const GetChildIDAtIndex = natives.GetChildIDAtIndex;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -173,14 +172,14 @@
  * @return {?number} The ids of the children of the node, or undefined
  *     if the tree or node wasn't found.
  */
-var GetChildIds = natives.GetChildIDs;
+const GetChildIds = natives.GetChildIDs;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {?Object} An object mapping html attributes to values.
  */
-var GetHtmlAttributes = natives.GetHtmlAttributes;
+const GetHtmlAttributes = natives.GetHtmlAttributes;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -188,7 +187,7 @@
  * @return {?number} The index of this node in its parent, or undefined if
  *     the tree or node or node parent wasn't found.
  */
-var GetIndexInParent = natives.GetIndexInParent;
+const GetIndexInParent = natives.GetIndexInParent;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -196,7 +195,7 @@
  * @return {?Object} An object with a string key for every state flag set,
  *     or undefined if the tree or node or node parent wasn't found.
  */
-var GetState = natives.GetState;
+const GetState = natives.GetState;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -204,14 +203,14 @@
  * @return {string} The restriction, one of
  * "disabled", "readOnly" or undefined if enabled or other object not disabled
  */
-var GetRestriction = natives.GetRestriction;
+const GetRestriction = natives.GetRestriction;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {string} The checked state, as undefined, "true", "false" or "mixed".
  */
-var GetChecked = natives.GetChecked;
+const GetChecked = natives.GetChecked;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -219,7 +218,7 @@
  * @return {string} The role of the node, or undefined if the tree or
  *     node wasn't found.
  */
-var GetRole = natives.GetRole;
+const GetRole = natives.GetRole;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -227,7 +226,7 @@
  * @return {?automation.Rect} The location of the node, or undefined if
  *     the tree or node wasn't found.
  */
-var GetLocation = natives.GetLocation;
+const GetLocation = natives.GetLocation;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -239,7 +238,7 @@
  *     or the location if there are no subranges, or undefined if
  *     the tree or node wasn't found.
  */
-var GetBoundsForRange = natives.GetBoundsForRange;
+const GetBoundsForRange = natives.GetBoundsForRange;
 
 /**
  * @param {number} left The left location of the text range.
@@ -251,7 +250,7 @@
  * @return {?automation.Rect} The bounding box of the subrange of this node,
  *     specified by arguments provided to the function.
  */
-var ComputeGlobalBounds = natives.ComputeGlobalBounds;
+const ComputeGlobalBounds = natives.ComputeGlobalBounds;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -259,7 +258,7 @@
  * @return {?automation.Rect} The unclipped location of the node, or
  * undefined if the tree or node wasn't found.
  */
-var GetUnclippedLocation = natives.GetUnclippedLocation;
+const GetUnclippedLocation = natives.GetUnclippedLocation;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -268,15 +267,15 @@
  *     array if this node has no text content, or undefined if the tree or node
  *     was not found.
  */
-var GetLineStartOffsets = requireNative(
-    'automationInternal').GetLineStartOffsets;
+const GetLineStartOffsets =
+    requireNative('automationInternal').GetLineStartOffsets;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of the node.
  * @return {?string} The computed name of this node.
  */
-var GetName = natives.GetName;
+const GetName = natives.GetName;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -285,7 +284,7 @@
  * @return {?string} The value of this attribute, or undefined if the tree,
  *     node, or attribute wasn't found.
  */
-var GetStringAttribute = natives.GetStringAttribute;
+const GetStringAttribute = natives.GetStringAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -294,7 +293,7 @@
  * @return {?boolean} The value of this attribute, or undefined if the tree,
  *     node, or attribute wasn't found.
  */
-var GetBoolAttribute = natives.GetBoolAttribute;
+const GetBoolAttribute = natives.GetBoolAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -303,7 +302,7 @@
  * @return {?number} The value of this attribute, or undefined if the tree,
  *     node, or attribute wasn't found.
  */
-var GetIntAttribute = natives.GetIntAttribute;
+const GetIntAttribute = natives.GetIntAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -312,8 +311,7 @@
  * @return {?Array<number>} The ids of nodes who have a relationship pointing
  *     to |nodeID| (a reverse relationship).
  */
-var GetIntAttributeReverseRelations =
-    natives.GetIntAttributeReverseRelations;
+const GetIntAttributeReverseRelations = natives.GetIntAttributeReverseRelations;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -322,7 +320,7 @@
  * @return {?number} The value of this attribute, or undefined if the tree,
  *     node, or attribute wasn't found.
  */
-var GetFloatAttribute = natives.GetFloatAttribute;
+const GetFloatAttribute = natives.GetFloatAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -331,8 +329,7 @@
  * @return {?Array<number>} The value of this attribute, or undefined
  *     if the tree, node, or attribute wasn't found.
  */
-var GetIntListAttribute =
-    natives.GetIntListAttribute;
+const GetIntListAttribute = natives.GetIntListAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -341,7 +338,7 @@
  * @return {?Array<number>} The ids of nodes who have a relationship pointing
  *     to |nodeID| (a reverse relationship).
  */
-var GetIntListAttributeReverseRelations =
+const GetIntListAttributeReverseRelations =
     natives.GetIntListAttributeReverseRelations;
 
 /**
@@ -351,21 +348,21 @@
  * @return {?string} The value of this attribute, or undefined if the tree,
  *     node, or attribute wasn't found.
  */
-var GetHtmlAttribute = natives.GetHtmlAttribute;
+const GetHtmlAttribute = natives.GetHtmlAttribute;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {automation.NameFromType} The source of the node's name.
  */
-var GetNameFrom = natives.GetNameFrom;
+const GetNameFrom = natives.GetNameFrom;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {automation.DescriptionFromType} The node description source.
  */
-var GetDescriptionFrom = natives.GetDescriptionFrom;
+const GetDescriptionFrom = natives.GetDescriptionFrom;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -373,35 +370,35 @@
  * @return {?string} The image annotation status, which may
  *     include the annotation itself if completed successfully.
  */
-var GetImageAnnotation = natives.GetImageAnnotation;
+const GetImageAnnotation = natives.GetImageAnnotation;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {boolean}
  */
-var GetBold = natives.GetBold;
+const GetBold = natives.GetBold;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {boolean}
  */
-var GetItalic = natives.GetItalic;
+const GetItalic = natives.GetItalic;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {boolean}
  */
-var GetUnderline = natives.GetUnderline;
+const GetUnderline = natives.GetUnderline;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {boolean}
  */
-var GetLineThrough = natives.GetLineThrough;
+const GetLineThrough = natives.GetLineThrough;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -409,35 +406,35 @@
  * @return {?Array<automation.CustomAction>} List of custom actions of the
  *     node.
  */
-var GetCustomActions = natives.GetCustomActions;
+const GetCustomActions = natives.GetCustomActions;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {?Array<string>} List of standard actions of the node.
  */
-var GetStandardActions = natives.GetStandardActions;
+const GetStandardActions = natives.GetStandardActions;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {automation.NameFromType} The source of the node's name.
  */
-var GetDefaultActionVerb = natives.GetDefaultActionVerb;
+const GetDefaultActionVerb = natives.GetDefaultActionVerb;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {automation.HasPopup}
  */
-var GetHasPopup = natives.GetHasPopup;
+const GetHasPopup = natives.GetHasPopup;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {automation.AriaCurrentState}
  */
-var GetAriaCurrentState = natives.GetAriaCurrentState;
+const GetAriaCurrentState = natives.GetAriaCurrentState;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -446,70 +443,70 @@
  * @param {boolean} backward
  * @return {{treeId: string, nodeId: number}}
  */
-var GetNextTextMatch = natives.GetNextTextMatch;
+const GetNextTextMatch = natives.GetNextTextMatch;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {?Array<number>} A list of column header ids.
  */
-var GetTableCellColumnHeaders = natives.GetTableCellColumnHeaders;
+const GetTableCellColumnHeaders = natives.GetTableCellColumnHeaders;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {?Array<number>} A list of row header ids.
  */
-var GetTableCellRowHeaders = natives.GetTableCellRowHeaders;
+const GetTableCellRowHeaders = natives.GetTableCellRowHeaders;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} Column index for this cell.
  */
-var GetTableCellColumnIndex = natives.GetTableCellColumnIndex;
+const GetTableCellColumnIndex = natives.GetTableCellColumnIndex;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} Row index for this cell.
  */
-var GetTableCellRowIndex = natives.GetTableCellRowIndex;
+const GetTableCellRowIndex = natives.GetTableCellRowIndex;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} Column index for this cell.
  */
-var GetTableCellAriaColumnIndex = natives.GetTableCellAriaColumnIndex;
+const GetTableCellAriaColumnIndex = natives.GetTableCellAriaColumnIndex;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} Row index for this cell.
  */
-var GetTableCellAriaRowIndex = natives.GetTableCellAriaRowIndex;
+const GetTableCellAriaRowIndex = natives.GetTableCellAriaRowIndex;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} column count for this cell's table. 0 if not in a table.
  */
-var GetTableColumnCount = natives.GetTableColumnCount;
+const GetTableColumnCount = natives.GetTableColumnCount;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {number} Row count for this cell's table. 0 if not in a table.
  */
-var GetTableRowCount = natives.GetTableRowCount;
+const GetTableRowCount = natives.GetTableRowCount;
 
 /**
  * @param {string} axTreeId The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {string} Detected language for this node.
  */
-var GetDetectedLanguage = natives.GetDetectedLanguage;
+const GetDetectedLanguage = natives.GetDetectedLanguage;
 
 /**
  * @param {string} axTreeId The id of the accessibility tree.
@@ -518,7 +515,7 @@
  * @return {!Array<{startIndex: number, endIndex: number, language: string,
  * probability: number}>}
  */
-var GetLanguageAnnotationForStringAttribute =
+const GetLanguageAnnotationForStringAttribute =
     natives.GetLanguageAnnotationForStringAttribute;
 
 /**
@@ -526,55 +523,55 @@
  * @param {number} nodeID The id of a node.
  * @return {!Array<number>}
  */
-var GetWordStartOffsets = natives.GetWordStartOffsets;
+const GetWordStartOffsets = natives.GetWordStartOffsets;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {!Array<number>}
  */
-var GetWordEndOffsets = natives.GetWordEndOffsets;
+const GetWordEndOffsets = natives.GetWordEndOffsets;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {!Array<number>}
  */
-var GetSentenceStartOffsets = natives.GetSentenceStartOffsets;
+const GetSentenceStartOffsets = natives.GetSentenceStartOffsets;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {!Array<number>}
  */
-var GetSentenceEndOffsets = natives.GetSentenceEndOffsets;
+const GetSentenceEndOffsets = natives.GetSentenceEndOffsets;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  */
-var SetAccessibilityFocus = natives.SetAccessibilityFocus;
+const SetAccessibilityFocus = natives.SetAccessibilityFocus;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @param {string} eventType
  */
-var EventListenerAdded = natives.EventListenerAdded;
+const EventListenerAdded = natives.EventListenerAdded;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @param {string} eventType
  */
-var EventListenerRemoved = natives.EventListenerRemoved;
+const EventListenerRemoved = natives.EventListenerRemoved;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {Array}
  */
-var GetMarkers = natives.GetMarkers;
+const GetMarkers = natives.GetMarkers;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
@@ -583,24 +580,24 @@
  * @param {boolean} isUpstream
  * @return {!Object}
  */
-var CreateAutomationPosition = natives.CreateAutomationPosition;
+const CreateAutomationPosition = natives.CreateAutomationPosition;
 
 /**
  * @param {string} axTreeID The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {string} The sort direction.
  */
-var GetSortDirection = natives.GetSortDirection;
+const GetSortDirection = natives.GetSortDirection;
 
 /**
  * @param {string} axTreeId The id of the accessibility tree.
  * @param {number} nodeID The id of a node.
  * @return {string} .
  */
-var GetValue = natives.GetValue;
+const GetValue = natives.GetValue;
 
-var logging = requireNative('logging');
-var utils = require('utils');
+const logging = requireNative('logging');
+const utils = require('utils');
 
 /**
  * A single node in the Automation tree.
@@ -633,9 +630,10 @@
   },
 
   get parent() {
-    var info = GetParentID(this.treeID, this.id);
-    if (info)
+    const info = GetParentID(this.treeID, this.id);
+    if (info) {
       return AutomationRootNodeImpl.getNodeFromTree(info.treeId, info.nodeId);
+    }
   },
 
   get htmlAttributes() {
@@ -677,16 +675,18 @@
         'Error with bounds for range callback' :
         'Error with unclipped bounds for range callback';
 
-    if (!this.rootImpl)
+    if (!this.rootImpl) {
       return;
+    }
 
     // Not yet initialized.
     if (this.rootImpl.treeID === undefined || this.id === undefined) {
       return;
     }
 
-    if (!callback)
+    if (!callback) {
       return;
+    }
 
     if (!GetBoolAttribute(this.treeID, this.id, 'supportsTextLocation')) {
       try {
@@ -714,9 +714,10 @@
   },
 
   get unclippedLocation() {
-    var result = GetUnclippedLocation(this.treeID, this.id);
-    if (result === undefined)
+    let result = GetUnclippedLocation(this.treeID, this.id);
+    if (result === undefined) {
       result = GetLocation(this.treeID, this.id);
+    }
     return result;
   },
 
@@ -729,64 +730,76 @@
   },
 
   get childTree() {
-    var childTreeID = GetStringAttribute(this.treeID, this.id, 'childTreeId');
-    if (childTreeID)
+    const childTreeID = GetStringAttribute(this.treeID, this.id, 'childTreeId');
+    if (childTreeID) {
       return AutomationRootNodeImpl.get(childTreeID);
+    }
   },
 
   get firstChild() {
-    if (GetChildCount(this.treeID, this.id) == 0)
+    if (GetChildCount(this.treeID, this.id) == 0) {
       return undefined;
-    var info = GetChildIDAtIndex(this.treeID, this.id, 0);
-    if (info)
+    }
+    const info = GetChildIDAtIndex(this.treeID, this.id, 0);
+    if (info) {
       return AutomationRootNodeImpl.getNodeFromTree(info.treeId, info.nodeId);
+    }
   },
 
   get lastChild() {
-    var count = GetChildCount(this.treeID, this.id);
-    if (count == 0)
+    const count = GetChildCount(this.treeID, this.id);
+    if (count == 0) {
       return;
+    }
 
-    var info = GetChildIDAtIndex(this.treeID, this.id, count - 1);
-    if (info)
+    const info = GetChildIDAtIndex(this.treeID, this.id, count - 1);
+    if (info) {
       return AutomationRootNodeImpl.getNodeFromTree(info.treeId, info.nodeId);
+    }
   },
 
   get children() {
-    var info = GetChildIds(this.treeID, this.id);
-    if (!info)
+    const info = GetChildIds(this.treeID, this.id);
+    if (!info) {
       return [];
+    }
 
-    var children = [];
-    for (var i = 0; i < info.nodeIds.length; ++i) {
-      var childID = info.nodeIds[i];
-      var child = AutomationRootNodeImpl.getNodeFromTree(info.treeId, childID);
-      if (child)
+    const children = [];
+    for (let i = 0; i < info.nodeIds.length; ++i) {
+      const childID = info.nodeIds[i];
+      const child =
+          AutomationRootNodeImpl.getNodeFromTree(info.treeId, childID);
+      if (child) {
         $Array.push(children, child);
+      }
     }
     return children;
   },
 
   get previousSibling() {
-    var parent = this.parent;
-    if (!parent)
+    let parent = this.parent;
+    if (!parent) {
       return undefined;
+    }
     parent = privates(parent).impl;
-    var indexInParent = GetIndexInParent(this.treeID, this.id);
-    var info = GetChildIDAtIndex(parent.treeID, parent.id, indexInParent - 1);
-    if (info)
+    const indexInParent = GetIndexInParent(this.treeID, this.id);
+    const info = GetChildIDAtIndex(parent.treeID, parent.id, indexInParent - 1);
+    if (info) {
       return AutomationRootNodeImpl.getNodeFromTree(info.treeId, info.nodeId);
+    }
   },
 
   get nextSibling() {
-    var parent = this.parent;
-    if (!parent)
+    let parent = this.parent;
+    if (!parent) {
       return undefined;
+    }
     parent = privates(parent).impl;
-    var indexInParent = GetIndexInParent(this.treeID, this.id);
-    var info = GetChildIDAtIndex(parent.treeID, parent.id, indexInParent + 1);
-    if (info)
+    const indexInParent = GetIndexInParent(this.treeID, this.id);
+    const info = GetChildIDAtIndex(parent.treeID, parent.id, indexInParent + 1);
+    if (info) {
       return AutomationRootNodeImpl.getNodeFromTree(info.treeId, info.nodeId);
+    }
   },
 
   get nameFrom() {
@@ -822,7 +835,7 @@
   },
 
   get detectedLanguage() {
-    return GetDetectedLanguage(this.treeID, this.id)
+    return GetDetectedLanguage(this.treeID, this.id);
   },
 
   languageAnnotationForStringAttribute: function(attributeName) {
@@ -851,21 +864,23 @@
   },
 
   get tableCellColumnHeaders() {
-    var ids = GetTableCellColumnHeaders(this.treeID, this.id);
+    const ids = GetTableCellColumnHeaders(this.treeID, this.id);
     if (ids && this.rootImpl) {
-      var result = [];
-      for (var i = 0; i < ids.length; i++)
+      const result = [];
+      for (let i = 0; i < ids.length; i++) {
         result.push(this.rootImpl.get(ids[i]));
+      }
       return result;
     }
   },
 
   get tableCellRowHeaders() {
-    var ids = GetTableCellRowHeaders(this.treeID, this.id);
+    const ids = GetTableCellRowHeaders(this.treeID, this.id);
     if (ids && this.rootImpl) {
-      var result = [];
-      for (var i = 0; i < ids.length; i++)
+      const result = [];
+      for (let i = 0; i < ids.length; i++) {
         result.push(this.rootImpl.get(ids[i]));
+      }
       return result;
     }
   },
@@ -916,16 +931,17 @@
   },
 
   createPosition: function(offset, opt_isUpstream) {
-    var nativePosition = CreateAutomationPosition(
+    const nativePosition = CreateAutomationPosition(
         this.treeID, this.id, offset, !!opt_isUpstream);
 
     // Attach a getter for the node, which is only available in js.
     Object.defineProperty(nativePosition, 'node', {
       get: function() {
-        var tree =
+        const tree =
             AutomationTreeCache.idToAutomationRootNode[nativePosition.treeID];
-        if (!tree)
+        if (!tree) {
           return null;
+        }
 
         return privates(tree).impl.get(nativePosition.anchorID);
       }
@@ -958,7 +974,7 @@
 
   hitTestInternal: function(x, y, eventToFire, opt_callback) {
     // Convert from global to tree-relative coordinates.
-    var location = GetLocation(this.treeID, GetRootID(this.treeID));
+    const location = GetLocation(this.treeID, GetRootID(this.treeID));
     this.performAction_('hitTest',
                         { x: Math.floor(x - location.left),
                           y: Math.floor(y - location.top),
@@ -975,7 +991,7 @@
   },
 
   performStandardAction: function(action) {
-    var standardActions = GetStandardActions(this.treeID, this.id);
+    const standardActions = GetStandardActions(this.treeID, this.id);
     if (!standardActions ||
         !standardActions.find(item => action == item)) {
       throw 'Inapplicable action for node: ' + action;
@@ -1065,8 +1081,9 @@
   },
 
   domQuerySelector: function(selector, callback) {
-    if (!this.rootImpl)
+    if (!this.rootImpl) {
       callback();
+    }
     automationInternal.querySelector(
       { treeID: this.rootImpl.treeID,
         automationNodeID: this.id,
@@ -1087,20 +1104,23 @@
   },
 
   getNextTextMatch: function(searchStr, backward) {
-    var info = GetNextTextMatch(this.treeID, this.id, searchStr, backward);
+    const info = GetNextTextMatch(this.treeID, this.id, searchStr, backward);
 
-    if (!info)
+    if (!info) {
       return;
+    }
 
-    var impl = privates(AutomationRootNodeImpl.get(info.treeId)).impl;
-    if (impl)
+    const impl = privates(AutomationRootNodeImpl.get(info.treeId)).impl;
+    if (impl) {
       return impl.get(info.nodeId);
+    }
   },
 
   addEventListener: function(eventType, callback, capture) {
     this.removeEventListener(eventType, callback);
-    if (!this.listeners[eventType])
+    if (!this.listeners[eventType]) {
       this.listeners[eventType] = [];
+    }
 
     // Calling EventListenerAdded will also validate the args
     // and throw an exception it's not a valid event type, so no invalid event
@@ -1117,10 +1137,11 @@
   // TODO(dtseng/aboxhall): Check this impl against spec.
   removeEventListener: function(eventType, callback) {
     if (this.listeners[eventType]) {
-      var listeners = this.listeners[eventType];
-      for (var i = 0; i < listeners.length; i++) {
-        if (callback === listeners[i].callback)
+      const listeners = this.listeners[eventType];
+      for (let i = 0; i < listeners.length; i++) {
+        if (callback === listeners[i].callback) {
           $Array.splice(listeners, i, 1);
+        }
       }
 
       if (listeners.length == 0) {
@@ -1138,14 +1159,14 @@
 
   dispatchEvent: function(
       eventType, eventFrom, eventFromAction, mouseX, mouseY, intents) {
-    var path = [];
-    var parent = this.parent;
+    const path = [];
+    let parent = this.parent;
     while (parent) {
       $Array.push(path, parent);
       parent = parent.parent;
     }
 
-    var event = new AutomationEvent(
+    const event = new AutomationEvent(
         eventType, this.wrapper, eventFrom, eventFromAction, mouseX, mouseY,
         intents);
 
@@ -1156,43 +1177,46 @@
     // At any stage, a listener may call stopPropagation() on the event, which
     // will immediately stop event propagation through this path.
     if (this.dispatchEventAtCapturing_(event, path)) {
-      if (this.dispatchEventAtTargeting_(event, path))
+      if (this.dispatchEventAtTargeting_(event, path)) {
         this.dispatchEventAtBubbling_(event, path);
+      }
     }
   },
 
   toString: function() {
-    var parentID = GetParentID(this.treeID, this.id);
+    let parentID = GetParentID(this.treeID, this.id);
     parentID = parentID ? parentID.nodeId : null;
-    var childTreeID = GetStringAttribute(this.treeID, this.id, 'childTreeId');
-    var count = GetChildCount(this.treeID, this.id);
-    var childIDs = [];
-    for (var i = 0; i < count; ++i) {
-      var childID = GetChildIDAtIndex(this.treeID, this.id, i).nodeId;
+    const childTreeID = GetStringAttribute(this.treeID, this.id, 'childTreeId');
+    const count = GetChildCount(this.treeID, this.id);
+    const childIDs = [];
+    for (let i = 0; i < count; ++i) {
+      const childID = GetChildIDAtIndex(this.treeID, this.id, i).nodeId;
       $Array.push(childIDs, childID);
     }
-    var name = GetName(this.treeID, this.id);
+    const name = GetName(this.treeID, this.id);
 
-    var result = 'node id=' + this.id +
-        ' role=' + this.role +
-        ' state=' + $JSON.stringify(this.state) +
-        ' parentID=' + parentID +
+    let result = 'node id=' + this.id + ' role=' + this.role +
+        ' state=' + $JSON.stringify(this.state) + ' parentID=' + parentID +
         ' childIds=' + $JSON.stringify(childIDs);
-    if (childTreeID)
+    if (childTreeID) {
       result += ' childTreeID=' + childTreeID;
-    if (name)
+    }
+    if (name) {
       result += ' name=' + name;
-    if (this.className)
+    }
+    if (this.className) {
       result += ' className=' + this.className;
+    }
     return result;
   },
 
   dispatchEventAtCapturing_: function(event, path) {
     privates(event).impl.eventPhase = Event.CAPTURING_PHASE;
-    for (var i = path.length - 1; i >= 0; i--) {
+    for (let i = path.length - 1; i >= 0; i--) {
       this.fireEventListeners_(path[i], event);
-      if (privates(event).impl.propagationStopped)
+      if (privates(event).impl.propagationStopped) {
         return false;
+      }
     }
     return true;
   },
@@ -1205,35 +1229,41 @@
 
   dispatchEventAtBubbling_: function(event, path) {
     privates(event).impl.eventPhase = Event.BUBBLING_PHASE;
-    for (var i = 0; i < path.length; i++) {
+    for (let i = 0; i < path.length; i++) {
       this.fireEventListeners_(path[i], event);
-      if (privates(event).impl.propagationStopped)
+      if (privates(event).impl.propagationStopped) {
         return false;
+      }
     }
     return true;
   },
 
   fireEventListeners_: function(node, event) {
-    var nodeImpl = privates(node).impl;
-    if (!nodeImpl.rootImpl)
+    const nodeImpl = privates(node).impl;
+    if (!nodeImpl.rootImpl) {
       return;
+    }
 
-    var originalListeners = nodeImpl.listeners[event.type];
-    if (!originalListeners)
+    const originalListeners = nodeImpl.listeners[event.type];
+    if (!originalListeners) {
       return;
+    }
 
     // Make a copy of the original listeners since calling any of them can cause
     // the list to be modified.
-    var listeners = [];
-    for (var i = 0; i < originalListeners.length; i++)
+    const listeners = [];
+    for (let i = 0; i < originalListeners.length; i++) {
       listeners.push(originalListeners[i]);
+    }
 
-    var eventPhase = event.eventPhase;
-    for (var i = 0; i < listeners.length; i++) {
-      if (eventPhase == Event.CAPTURING_PHASE && !listeners[i].capture)
+    const eventPhase = event.eventPhase;
+    for (let i = 0; i < listeners.length; i++) {
+      if (eventPhase == Event.CAPTURING_PHASE && !listeners[i].capture) {
         continue;
-      if (eventPhase == Event.BUBBLING_PHASE && listeners[i].capture)
+      }
+      if (eventPhase == Event.BUBBLING_PHASE && listeners[i].capture) {
         continue;
+      }
 
       try {
         listeners[i].callback(event);
@@ -1245,8 +1275,9 @@
   },
 
   performAction_: function(actionType, opt_args, opt_callback) {
-    if (!this.rootImpl)
+    if (!this.rootImpl) {
       return;
+    }
 
     // Not yet initialized.
     if (this.rootImpl.treeID === undefined ||
@@ -1259,7 +1290,7 @@
       throw new Error(actionType + ' requires {"desktop": true} or' +
           ' {"interact": true} in the "automation" manifest key.');
     }
-    var requestID = -1;
+    let requestID = -1;
     if (opt_callback) {
       requestID = this.rootImpl.addActionResultCallback(opt_callback);
     }
@@ -1279,7 +1310,7 @@
       userCallback(null);
       return;
     }
-    var resultNode = this.rootImpl.get(resultAutomationNodeID);
+    const resultNode = this.rootImpl.get(resultAutomationNodeID);
     if (!resultNode) {
       logging.WARNING('Query selector result not in tree: ' +
                       resultAutomationNodeID);
@@ -1289,18 +1320,20 @@
   },
 
   findInternal_: function(params, opt_results) {
-    var result = null;
+    let result = null;
     this.forAllDescendants_(function(node) {
       if (privates(node).impl.matchInternal_(params)) {
-        if (opt_results)
+        if (opt_results) {
           $Array.push(opt_results, node);
-        else
+        } else {
           result = node;
+        }
         return !opt_results;
       }
     });
-    if (opt_results)
+    if (opt_results) {
       return opt_results;
+    }
     return result;
   },
 
@@ -1311,42 +1344,50 @@
    *     for each node. Return true to early-out the traversal.
    */
   forAllDescendants_: function(closure) {
-    var stack = $Array.reverse(this.wrapper.children);
+    const stack = $Array.reverse(this.wrapper.children);
     while (stack.length > 0) {
-      var node = $Array.pop(stack);
-      if (closure(node))
+      const node = $Array.pop(stack);
+      if (closure(node)) {
         return;
+      }
 
-      var children = node.children;
-      for (var i = children.length - 1; i >= 0; i--)
+      const children = node.children;
+      for (let i = children.length - 1; i >= 0; i--) {
         $Array.push(stack, children[i]);
+      }
     }
   },
 
   matchInternal_: function(params) {
-    if ($Object.keys(params).length === 0)
+    if ($Object.keys(params).length === 0) {
       return false;
+    }
 
-    if ('role' in params && this.role != params.role)
+    if ('role' in params && this.role != params.role) {
       return false;
+    }
 
     if ('state' in params) {
-      for (var state in params.state) {
-        if (params.state[state] != (state in this.state))
+      for (const state in params.state) {
+        if (params.state[state] != (state in this.state)) {
           return false;
+        }
       }
     }
     if ('attributes' in params) {
-      for (var attribute in params.attributes) {
-        var attrValue = params.attributes[attribute];
+      for (const attribute in params.attributes) {
+        const attrValue = params.attributes[attribute];
         if (typeof attrValue != 'object') {
-          if (this[attribute] !== attrValue)
+          if (this[attribute] !== attrValue) {
             return false;
+          }
         } else if (attrValue instanceof $RegExp.self) {
-          if (typeof this[attribute] != 'string')
+          if (typeof this[attribute] != 'string') {
             return false;
-          if (!attrValue.test(this[attribute]))
+          }
+          if (!attrValue.test(this[attribute])) {
             return false;
+          }
         } else {
           // TODO(aboxhall): handle intlist case.
           return false;
@@ -1357,7 +1398,7 @@
   }
 };
 
-var stringAttributes = [
+const stringAttributes = [
   'accessKey',
   'appId',
   'ariaInvalidValue',
@@ -1381,67 +1422,48 @@
   'url'
 ];
 
-var boolAttributes = [
+const boolAttributes = [
   'busy', 'clickable', 'containerLiveAtomic', 'containerLiveBusy',
   'nonAtomicTextFieldRoot', 'liveAtomic', 'modal', 'notUserSelectableStyle',
   'scrollable', 'selected', 'supportsTextLocation'
 ];
 
-var intAttributes = [
-    'backgroundColor',
-    'color',
-    'colorValue',
-    'hierarchicalLevel',
-    'posInSet',
-    'scrollX',
-    'scrollXMax',
-    'scrollXMin',
-    'scrollY',
-    'scrollYMax',
-    'scrollYMin',
-    'setSize',
-    'tableCellColumnSpan',
-    'tableCellRowSpan',
-    'ariaColumnCount',
-    'ariaRowCount',
-    'textSelEnd',
-    'textSelStart'];
+const intAttributes = [
+  'backgroundColor', 'color', 'colorValue', 'hierarchicalLevel', 'posInSet',
+  'scrollX', 'scrollXMax', 'scrollXMin', 'scrollY', 'scrollYMax', 'scrollYMin',
+  'setSize', 'tableCellColumnSpan', 'tableCellRowSpan', 'ariaColumnCount',
+  'ariaRowCount', 'textSelEnd', 'textSelStart'
+];
 
 // Int attribute, relation property to expose, reverse relation to expose.
-var nodeRefAttributes = [
-    ['activedescendantId', 'activeDescendant', 'activeDescendantFor'],
-    ['errormessageId', 'errorMessage', 'errorMessageFor'],
-    ['inPageLinkTargetId', 'inPageLinkTarget', null],
-    ['nextFocusId', 'nextFocus', null],
-    ['nextOnLineId', 'nextOnLine', null],
-    ['previousFocusId', 'previousFocus', null],
-    ['previousOnLineId', 'previousOnLine', null],
-    ['tableColumnHeaderId', 'tableColumnHeader', null],
-    ['tableHeaderId', 'tableHeader', null],
-    ['tableRowHeaderId', 'tableRowHeader', null]];
+const nodeRefAttributes = [
+  ['activedescendantId', 'activeDescendant', 'activeDescendantFor'],
+  ['errormessageId', 'errorMessage', 'errorMessageFor'],
+  ['inPageLinkTargetId', 'inPageLinkTarget', null],
+  ['nextFocusId', 'nextFocus', null], ['nextOnLineId', 'nextOnLine', null],
+  ['previousFocusId', 'previousFocus', null],
+  ['previousOnLineId', 'previousOnLine', null],
+  ['tableColumnHeaderId', 'tableColumnHeader', null],
+  ['tableHeaderId', 'tableHeader', null],
+  ['tableRowHeaderId', 'tableRowHeader', null]
+];
 
-var intListAttributes = [
-    'wordEnds',
-    'wordStarts'];
+const intListAttributes = ['wordEnds', 'wordStarts'];
 
 // Intlist attribute, relation property to expose, reverse relation to expose.
-var nodeRefListAttributes = [
-    ['controlsIds', 'controls', 'controlledBy'],
-    ['describedbyIds', 'describedBy', 'descriptionFor'],
-    ['detailsIds', 'details', 'detailsFor'],
-    ['flowtoIds', 'flowTo', 'flowFrom'],
-    ['labelledbyIds', 'labelledBy', 'labelFor']];
+const nodeRefListAttributes = [
+  ['controlsIds', 'controls', 'controlledBy'],
+  ['describedbyIds', 'describedBy', 'descriptionFor'],
+  ['detailsIds', 'details', 'detailsFor'], ['flowtoIds', 'flowTo', 'flowFrom'],
+  ['labelledbyIds', 'labelledBy', 'labelFor']
+];
 
-var floatAttributes = [
-    'fontSize',
-    'maxValueForRange',
-    'minValueForRange',
-    'valueForRange'];
+const floatAttributes =
+    ['fontSize', 'maxValueForRange', 'minValueForRange', 'valueForRange'];
 
-var htmlAttributes = [
-    ['type', 'inputType']];
+const htmlAttributes = [['type', 'inputType']];
 
-var publicAttributes = [];
+const publicAttributes = [];
 
 $Array.forEach(stringAttributes, function(attributeName) {
   $Array.push(publicAttributes, attributeName);
@@ -1474,39 +1496,42 @@
 });
 
 $Array.forEach(nodeRefAttributes, function(params) {
-  var srcAttributeName = params[0];
-  var dstAttributeName = params[1];
-  var dstReverseAttributeName = params[2];
+  const srcAttributeName = params[0];
+  const dstAttributeName = params[1];
+  const dstReverseAttributeName = params[2];
   $Array.push(publicAttributes, dstAttributeName);
   $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
     __proto__: null,
     get: function() {
-      var id = GetIntAttribute(this.treeID, this.id, srcAttributeName);
-      if (id && this.rootImpl)
+      const id = GetIntAttribute(this.treeID, this.id, srcAttributeName);
+      if (id && this.rootImpl) {
         return this.rootImpl.get(id);
-      else
+      } else {
         return undefined;
+      }
     }
   });
   if (dstReverseAttributeName) {
     $Array.push(publicAttributes, dstReverseAttributeName);
-    $Object.defineProperty(AutomationNodeImpl.prototype,
-                           dstReverseAttributeName, {
-      __proto__: null,
-      get: function() {
-        var ids = GetIntAttributeReverseRelations(
-            this.treeID, this.id, srcAttributeName);
-        if (!ids || !this.rootImpl)
-          return undefined;
-        var result = [];
-        for (var i = 0; i < ids.length; ++i) {
-          var node = this.rootImpl.get(ids[i]);
-          if (node)
-          $Array.push(result, node);
-        }
-        return result;
-      }
-    });
+    $Object.defineProperty(
+        AutomationNodeImpl.prototype, dstReverseAttributeName, {
+          __proto__: null,
+          get: function() {
+            const ids = GetIntAttributeReverseRelations(
+                this.treeID, this.id, srcAttributeName);
+            if (!ids || !this.rootImpl) {
+              return undefined;
+            }
+            const result = [];
+            for (let i = 0; i < ids.length; ++i) {
+              const node = this.rootImpl.get(ids[i]);
+              if (node) {
+                $Array.push(result, node);
+              }
+            }
+            return result;
+          }
+        });
   }
 });
 
@@ -1521,44 +1546,48 @@
 });
 
 $Array.forEach(nodeRefListAttributes, function(params) {
-  var srcAttributeName = params[0];
-  var dstAttributeName = params[1];
-  var dstReverseAttributeName = params[2];
+  const srcAttributeName = params[0];
+  const dstAttributeName = params[1];
+  const dstReverseAttributeName = params[2];
   $Array.push(publicAttributes, dstAttributeName);
   $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
     __proto__: null,
     get: function() {
-      var ids = GetIntListAttribute(this.treeID, this.id, srcAttributeName);
-      if (!ids || !this.rootImpl)
+      const ids = GetIntListAttribute(this.treeID, this.id, srcAttributeName);
+      if (!ids || !this.rootImpl) {
         return undefined;
-      var result = [];
-      for (var i = 0; i < ids.length; ++i) {
-        var node = this.rootImpl.get(ids[i]);
-        if (node)
+      }
+      const result = [];
+      for (let i = 0; i < ids.length; ++i) {
+        const node = this.rootImpl.get(ids[i]);
+        if (node) {
           $Array.push(result, node);
+        }
       }
       return result;
     }
   });
   if (dstReverseAttributeName) {
     $Array.push(publicAttributes, dstReverseAttributeName);
-    $Object.defineProperty(AutomationNodeImpl.prototype,
-                           dstReverseAttributeName, {
-      __proto__: null,
-      get: function() {
-        var ids = GetIntListAttributeReverseRelations(
-            this.treeID, this.id, srcAttributeName);
-        if (!ids || !this.rootImpl)
-          return undefined;
-        var result = [];
-        for (var i = 0; i < ids.length; ++i) {
-          var node = this.rootImpl.get(ids[i]);
-          if (node)
-          $Array.push(result, node);
-        }
-        return result;
-      }
-    });
+    $Object.defineProperty(
+        AutomationNodeImpl.prototype, dstReverseAttributeName, {
+          __proto__: null,
+          get: function() {
+            const ids = GetIntListAttributeReverseRelations(
+                this.treeID, this.id, srcAttributeName);
+            if (!ids || !this.rootImpl) {
+              return undefined;
+            }
+            const result = [];
+            for (let i = 0; i < ids.length; ++i) {
+              const node = this.rootImpl.get(ids[i]);
+              if (node) {
+                $Array.push(result, node);
+              }
+            }
+            return result;
+          }
+        });
   }
 });
 
@@ -1573,8 +1602,8 @@
 });
 
 $Array.forEach(htmlAttributes, function(params) {
-  var srcAttributeName = params[0];
-  var dstAttributeName = params[1];
+  const srcAttributeName = params[0];
+  const dstAttributeName = params[1];
   $Array.push(publicAttributes, dstAttributeName);
   $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, {
     __proto__: null,
@@ -1608,27 +1637,30 @@
 }
 
 utils.defineProperty(AutomationRootNodeImpl, 'get', function(treeID) {
-  var result = AutomationTreeCache.idToAutomationRootNode[treeID];
+  const result = AutomationTreeCache.idToAutomationRootNode[treeID];
   return result || undefined;
 });
 
 utils.defineProperty(AutomationRootNodeImpl, 'getOrCreate', function(treeID) {
-  if (AutomationTreeCache.idToAutomationRootNode[treeID])
+  if (AutomationTreeCache.idToAutomationRootNode[treeID]) {
     return AutomationTreeCache.idToAutomationRootNode[treeID];
-  var result = new AutomationRootNode(treeID);
+  }
+  const result = new AutomationRootNode(treeID);
   AutomationTreeCache.idToAutomationRootNode[treeID] = result;
   return result;
 });
 
 utils.defineProperty(
     AutomationRootNodeImpl, 'getNodeFromTree', function(treeId, nodeId) {
-  var tree = AutomationRootNodeImpl.get(treeId);
-  if (!tree)
-    return;
-  var impl = privates(tree).impl;
-  if (impl)
-    return impl.get(nodeId);
-});
+      const tree = AutomationRootNodeImpl.get(treeId);
+      if (!tree) {
+        return;
+      }
+      const impl = privates(tree).impl;
+      if (impl) {
+        return impl.get(nodeId);
+      }
+    });
 
 utils.defineProperty(AutomationRootNodeImpl, 'destroy', function(treeID) {
   delete AutomationTreeCache.idToAutomationRootNode[treeID];
@@ -1661,18 +1693,19 @@
 
   /**
    * A map from id to AutomationNode.
-   * @type {Object.<number, AutomationNode>}
+   * @type {Object<number, AutomationNode>}
    * @private
    */
   axNodeDataCache_: null,
 
   get id() {
-    var result = GetRootID(this.treeID);
+    const result = GetRootID(this.treeID);
 
     // Don't return undefined, because the id is often passed directly
     // as an argument to a native binding that expects only a valid number.
-    if (result === undefined)
+    if (result === undefined) {
       return -1;
+    }
 
     return result;
   },
@@ -1699,102 +1732,118 @@
 
   get anchorObject() {
     const id = GetAnchorObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return this.get(id);
+    }
     return undefined;
   },
 
   get anchorOffset() {
     const id = GetAnchorObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetAnchorOffset(this.treeID);
+    }
     return undefined;
   },
 
   get anchorAffinity() {
     const id = GetAnchorObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetAnchorAffinity(this.treeID);
+    }
     return undefined;
   },
 
   get focusObject() {
     const id = GetFocusObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return this.get(id);
+    }
     return undefined;
   },
 
   get focusOffset() {
     const id = GetFocusObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetFocusOffset(this.treeID);
+    }
     return undefined;
   },
 
   get focusAffinity() {
     const id = GetFocusObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetFocusAffinity(this.treeID);
+    }
     return undefined;
   },
 
   get selectionStartObject() {
     const id = GetSelectionStartObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return this.get(id);
+    }
     return undefined;
   },
 
   get selectionStartOffset() {
     const id = GetSelectionStartObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetSelectionStartOffset(this.treeID);
+    }
     return undefined;
   },
 
   get selectionStartAffinity() {
     const id = GetSelectionStartObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetSelectionStartAffinity(this.treeID);
+    }
     return undefined;
   },
 
   get selectionEndObject() {
     const id = GetSelectionEndObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return this.get(id);
+    }
     return undefined;
   },
 
   get selectionEndOffset() {
     const id = GetSelectionEndObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetSelectionEndOffset(this.treeID);
+    }
     return undefined;
   },
 
   get selectionEndAffinity() {
     const id = GetSelectionEndObjectID(this.treeID);
-    if (id && id != -1)
+    if (id && id != -1) {
       return GetSelectionEndAffinity(this.treeID);
+    }
     return undefined;
   },
 
   get: function(id) {
-    if (id == undefined)
+    if (id == undefined) {
       return undefined;
+    }
 
-    if (id == this.id)
+    if (id == this.id) {
       return this.wrapper;
+    }
 
-    var obj = this.axNodeDataCache_[id];
-    if (obj)
+    let obj = this.axNodeDataCache_[id];
+    if (obj) {
       return obj;
+    }
 
     // Validate the backing AXTree has the specified node.
-    if (!GetRole(this.treeID, id))
+    if (!GetRole(this.treeID, id)) {
       return;
+    }
 
     obj = new AutomationNode(this);
     privates(obj).impl.treeID = this.treeID;
@@ -1805,21 +1854,23 @@
   },
 
   remove: function(id) {
-    if (this.axNodeDataCache_[id])
+    if (this.axNodeDataCache_[id]) {
       privates(this.axNodeDataCache_[id]).impl.detach();
+    }
     delete this.axNodeDataCache_[id];
   },
 
   destroy: function() {
-    for (var id in this.axNodeDataCache_)
+    for (const id in this.axNodeDataCache_) {
       this.remove(id);
+    }
     this.detach();
   },
 
   onAccessibilityEvent: function(eventParams) {
-    var targetNode = this.get(eventParams.targetID);
+    const targetNode = this.get(eventParams.targetID);
     if (targetNode) {
-      var targetNodeImpl = privates(targetNode).impl;
+      const targetNodeImpl = privates(targetNode).impl;
       targetNodeImpl.dispatchEvent(
           eventParams.eventType, eventParams.eventFrom,
           eventParams.eventFromAction, eventParams.mouseX, eventParams.mouseY,
@@ -1843,9 +1894,9 @@
   },
 
   onGetTextLocationResult: function(textLocationParams) {
-    let requestID = textLocationParams.requestID;
+    const requestID = textLocationParams.requestID;
     if (requestID in AutomationRootNodeImpl.actionRequestIDToCallback) {
-      let callback =
+      const callback =
           AutomationRootNodeImpl.actionRequestIDToCallback[requestID];
       try {
         if (textLocationParams.result) {
@@ -1873,17 +1924,20 @@
 
   toString: function() {
     function toStringInternal(nodeImpl, indent) {
-      if (!nodeImpl)
+      if (!nodeImpl) {
         return '';
-      var output = '';
-      if (nodeImpl.isRootNode)
+      }
+      let output = '';
+      if (nodeImpl.isRootNode) {
         output += indent + 'tree id=' + nodeImpl.treeID + '\n';
+      }
       output += indent +
         $Function.call(AutomationNodeImpl.prototype.toString, nodeImpl) + '\n';
       indent += '  ';
-      var children = nodeImpl.children;
-      for (var i = 0; i < children.length; ++i)
+      const children = nodeImpl.children;
+      for (let i = 0; i < children.length; ++i) {
         output += toStringInternal(privates(children[i]).impl, indent);
+      }
       return output;
     }
     return toStringInternal(this, '');
diff --git a/extensions/renderer/resources/automation/automation_tree_cache.js b/extensions/renderer/resources/automation/automation_tree_cache.js
index 3a7b846..86250aef 100644
--- a/extensions/renderer/resources/automation/automation_tree_cache.js
+++ b/extensions/renderer/resources/automation/automation_tree_cache.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var utils = require('utils');
+const utils = require('utils');
 
 function AutomationTreeCacheImpl() {}
 
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index 822a187..5be1b482 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -1088,7 +1088,7 @@
       }
       builders {
         name: "chromium/try/lacros-arm-generic-rel"
-        experiment_percentage: 1
+        experiment_percentage: 10
         location_regexp: ".*"
         location_regexp_exclude: ".+/[+]/docs/.+"
         location_regexp_exclude: ".+/[+]/infra/config/.+"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index 0b142c8..1c82222 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -444,7 +444,7 @@
   * Experiment percentage: 1.0
 
 * [lacros-arm-generic-rel](https://ci.chromium.org/p/chromium/builders/try/lacros-arm-generic-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+lacros-arm-generic-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+lacros-arm-generic-rel))
-  * Experiment percentage: 1.0
+  * Experiment percentage: 10.0
 
 * [linux-1mbu-compile-fyi-rel](https://ci.chromium.org/p/chromium/builders/try/linux-1mbu-compile-fyi-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-1mbu-compile-fyi-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-1mbu-compile-fyi-rel))
   * Experiment percentage: 5.0
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 1cf89d6..9f52622 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -28294,6 +28294,136 @@
       }
     }
     builders {
+      name: "linux-local-ssd-nvme-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:linux-local-ssd-nvme-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      recipe {
+        name: "chromium"
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true}"
+        properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
+        properties_j: "$recipe_engine/isolated:{\"server\":\"https://isolateserver.appspot.com\"}"
+        properties_j: "$recipe_engine/resultdb/test_presentation:{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]}"
+        properties_j: "builder_group:\"infra\""
+      }
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.gtests_local"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.buildbucket.use_bbagent"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
+      name: "linux-local-ssd-scsi-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builder:linux-local-ssd-scsi-rel"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      recipe {
+        name: "chromium"
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        properties_j: "$build/goma:{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true}"
+        properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
+        properties_j: "$recipe_engine/isolated:{\"server\":\"https://isolateserver.appspot.com\"}"
+        properties_j: "$recipe_engine/resultdb/test_presentation:{\"column_keys\":[],\"grouping_keys\":[\"status\",\"v.test_suite\"]}"
+        properties_j: "builder_group:\"infra\""
+      }
+      execution_timeout_secs: 10800
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      experiments {
+        key: "chromium.resultdb.result_sink"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.gtests_local"
+        value: 100
+      }
+      experiments {
+        key: "chromium.resultdb.result_sink.junit_tests"
+        value: 100
+      }
+      experiments {
+        key: "luci.buildbucket.use_bbagent"
+        value: 100
+      }
+      experiments {
+        key: "luci.use_realms"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "gpu_ci_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+    }
+    builders {
       name: "linux-official"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 69a51dbf..9ac3937 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -1684,6 +1684,11 @@
     short_name: "a64-size"
   }
   builders {
+    name: "buildbucket/luci.chrome.ci/fuchsia-builder-perf-fyi"
+    category: "fyi"
+    short_name: "builder-perf"
+  }
+  builders {
     name: "buildbucket/luci.chrome.ci/fuchsia-perf-fyi"
     category: "fyi"
     short_name: "perf"
@@ -12769,14 +12774,20 @@
   refs: "regexp:refs/heads/main"
   manifest_name: "REVISION"
   builders {
+    name: "buildbucket/luci.chromium.ci/linux-control-rel"
+    short_name: "cntrl"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/linux-component-rel"
-    category: "component build"
     short_name: "comp"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/linux-control-rel"
-    category: "control"
-    short_name: "cntrl"
+    name: "buildbucket/luci.chromium.ci/linux-local-ssd-nvme-rel"
+    short_name: "nvme"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/linux-local-ssd-scsi-rel"
+    short_name: "scsi"
   }
   header {
     oncalls {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index bcbac9d6..13840cc 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -5566,7 +5566,6 @@
 job {
   id: "linux-component-rel"
   realm: "ci"
-  schedule: "triggered"
   acl_sets: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
@@ -5577,7 +5576,6 @@
 job {
   id: "linux-control-rel"
   realm: "ci"
-  schedule: "triggered"
   acl_sets: "ci"
   buildbucket {
     server: "cr-buildbucket.appspot.com"
@@ -5695,6 +5693,26 @@
   }
 }
 job {
+  id: "linux-local-ssd-nvme-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-local-ssd-nvme-rel"
+  }
+}
+job {
+  id: "linux-local-ssd-scsi-rel"
+  realm: "ci"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-local-ssd-scsi-rel"
+  }
+}
+job {
   id: "linux-official"
   realm: "ci"
   acl_sets: "ci"
@@ -7157,6 +7175,8 @@
   triggers: "linux-chromeos-dbg"
   triggers: "linux-chromeos-rel"
   triggers: "linux-chromium-tests-staging-builder"
+  triggers: "linux-component-rel"
+  triggers: "linux-control-rel"
   triggers: "linux-extended-tracing-rel"
   triggers: "linux-fieldtrial-rel"
   triggers: "linux-gcc-rel"
@@ -7164,6 +7184,8 @@
   triggers: "linux-lacros-builder-rel"
   triggers: "linux-lacros-code-coverage"
   triggers: "linux-lacros-version-skew-fyi"
+  triggers: "linux-local-ssd-nvme-rel"
+  triggers: "linux-local-ssd-scsi-rel"
   triggers: "linux-official"
   triggers: "linux-ozone-rel"
   triggers: "linux-perfetto-rel"
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index d993a4ed..cbef049e 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -438,6 +438,7 @@
     short_name = short_name,
 ) for name, category, short_name in (
     ("fuchsia-fyi-arm64-size", "fyi", "a64-size"),
+    ("fuchsia-builder-perf-fyi", "fyi", "builder-perf"),
     ("fuchsia-perf-fyi", "fyi", "perf"),
     ("fuchsia-x64", "ci", "x64-chrome"),
 )]
@@ -5516,22 +5517,32 @@
 ci.infra_builder(
     name = "linux-component-rel",
     console_view_entry = consoles.console_view_entry(
-        category = "component build",
         short_name = "comp",
     ),
-    schedule = "triggered",
-    triggered_by = [],
     builderless = False,
 )
 
 ci.infra_builder(
     name = "linux-control-rel",
     console_view_entry = consoles.console_view_entry(
-        category = "control",
         short_name = "cntrl",
     ),
-    schedule = "triggered",
-    triggered_by = [],
+    builderless = False,
+)
+
+ci.infra_builder(
+    name = "linux-local-ssd-nvme-rel",
+    console_view_entry = consoles.console_view_entry(
+        short_name = "nvme",
+    ),
+    builderless = False,
+)
+
+ci.infra_builder(
+    name = "linux-local-ssd-scsi-rel",
+    console_view_entry = consoles.console_view_entry(
+        short_name = "scsi",
+    ),
     builderless = False,
 )
 
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index 1db0f91..b7c0c37 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -802,7 +802,7 @@
     builderless = not settings.is_main,
     main_list_view = "try",
     tryjob = try_.job(
-        experiment_percentage = 1,
+        experiment_percentage = 10,
     ),
     os = os.LINUX_BIONIC_REMOVE,
 )
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index aaadb116a..45486855 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -16,7 +16,6 @@
   TestMsgStart,
   WorkerMsgStart,
   NaClMsgStart,
-  MediaMsgStart,
   PpapiMsgStart,
   ExtensionMsgStart,
   ChromotingMsgStart,
@@ -25,7 +24,6 @@
   GinJavaBridgeMsgStart,
   ExtensionsGuestViewMsgStart,
   GuestViewMsgStart,
-  MediaPlayerDelegateMsgStart,
   ExtensionWorkerMsgStart,
   LastIPCMsgStart  // Must come last.
 };
diff --git a/ipc/trace_ipc_message.cc b/ipc/trace_ipc_message.cc
index a550d78..0a042cd 100644
--- a/ipc/trace_ipc_message.cc
+++ b/ipc/trace_ipc_message.cc
@@ -31,9 +31,6 @@
     case NaClMsgStart:
       message_class = ChromeLegacyIpc::CLASS_NACL;
       break;
-    case MediaMsgStart:
-      message_class = ChromeLegacyIpc::CLASS_MEDIA;
-      break;
     case PpapiMsgStart:
       message_class = ChromeLegacyIpc::CLASS_PPAPI;
       break;
@@ -59,9 +56,6 @@
     case GuestViewMsgStart:
       message_class = ChromeLegacyIpc::CLASS_GUEST_VIEW;
       break;
-    case MediaPlayerDelegateMsgStart:
-      message_class = ChromeLegacyIpc::CLASS_MEDIA_PLAYER_DELEGATE;
-      break;
     case ExtensionWorkerMsgStart:
       message_class = ChromeLegacyIpc::CLASS_EXTENSION_WORKER;
       break;
diff --git a/media/DEPS b/media/DEPS
index dbe6e063..527ae53 100644
--- a/media/DEPS
+++ b/media/DEPS
@@ -30,7 +30,6 @@
   "+ui/ozone",
   "+third_party/widevine/cdm/widevine_cdm_common.h",
   "-ipc",
-  "-media/blink",
   "-media/webrtc",
 ]
 
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 2e0b3628..75c714799 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -186,8 +186,8 @@
 
 // Overrides hardware secure codecs support for testing. If specified, real
 // platform hardware secure codecs check will be skipped. Codecs are separated
-// by comma. Valid video codecs are "vp8", "vp9", "avc1" and "hevc", and the
-// only valid audio codec is "vorbis". For example:
+// by comma. Valid video codecs are "vp8", "vp9", "avc1" and "hevc", and valid
+// audio codecs are "mp4a" and "vorbis". For example:
 //  --override-hardware-secure-codecs-for-testing=vp8,vp9
 //  --override-hardware-secure-codecs-for-testing=avc1
 // CENC encryption scheme is assumed to be supported for the specified codecs.
diff --git a/media/base/timestamp_constants.h b/media/base/timestamp_constants.h
index a38fc446..1e47f8f0f 100644
--- a/media/base/timestamp_constants.h
+++ b/media/base/timestamp_constants.h
@@ -5,21 +5,15 @@
 #ifndef MEDIA_BASE_TIMESTAMP_CONSTANTS_H_
 #define MEDIA_BASE_TIMESTAMP_CONSTANTS_H_
 
-#include <stdint.h>
-
-#include <limits>
-
 #include "base/time/time.h"
 
 namespace media {
 
 // Indicates an invalid or missing timestamp.
-constexpr base::TimeDelta kNoTimestamp =
-    base::TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::min());
+constexpr base::TimeDelta kNoTimestamp = base::TimeDelta::Min();
 
 // Represents an infinite stream duration.
-constexpr base::TimeDelta kInfiniteDuration =
-    base::TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::max());
+constexpr base::TimeDelta kInfiniteDuration = base::TimeDelta::Max();
 
 }  // namespace media
 
diff --git a/media/blink/BUILD.gn b/media/blink/BUILD.gn
deleted file mode 100644
index 9c8f770..0000000
--- a/media/blink/BUILD.gn
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/ui.gni")
-import("//media/media_options.gni")
-import("//testing/test.gni")
-import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
-
-test("media_blink_unittests") {
-  use_xvfb = use_xvfb_in_this_config
-
-  deps = [
-    "//base",
-    "//base/test:test_support",
-    "//cc",
-    "//gin",
-    "//media:test_support",
-    "//media/mojo/mojom",
-    "//media/mojo/services",
-    "//mojo/core/embedder",
-    "//net",
-    "//services/device:test_support",
-    "//services/device/public/mojom",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//third_party/blink/public:blink",
-    "//third_party/blink/public:test_support",
-    "//third_party/blink/public/platform/media",
-    "//third_party/blink/renderer/platform/media",
-    "//third_party/blink/renderer/platform/media:test_support",
-    "//tools/v8_context_snapshot",
-    "//ui/gfx:test_support",
-    "//ui/gfx/geometry",
-    "//url",
-  ]
-
-  data = [ "//media/test/data/" ]
-
-  configs += [
-    "//build/config/compiler:no_size_t_to_int_warning",
-    "//tools/v8_context_snapshot:use_v8_context_snapshot",
-    "//v8:external_startup_data",
-  ]
-
-  sources = [
-    "blink_platform_with_task_environment.cc",
-    "blink_platform_with_task_environment.h",
-    "run_all_unittests.cc",
-    "webmediaplayer_impl_unittest.cc",
-  ]
-
-  if (is_android) {
-    deps += [ "//media/base/android:media_java" ]
-    if (use_v8_context_snapshot) {
-      deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ]
-    } else {
-      deps += [ "//v8:v8_external_startup_data_assets" ]
-    }
-  }
-
-  if (is_fuchsia) {
-    additional_manifest_fragments =
-        [ "//build/config/fuchsia/test/jit_capabilities.test-cmx" ]
-  }
-}
diff --git a/media/blink/DEPS b/media/blink/DEPS
deleted file mode 100644
index 7c71433e..0000000
--- a/media/blink/DEPS
+++ /dev/null
@@ -1,38 +0,0 @@
-include_rules = [
-  "+cc/layers/layer.h",
-  "+cc/layers/surface_layer.h",
-  "+cc/layers/video_frame_provider.h",
-  "+cc/layers/video_layer.h",
-  "+components/scheduler",  # Only allowed in tests.
-  "+components/viz/common/frame_sinks/begin_frame_args.h",
-  "+components/viz/common/gpu/context_provider.h",
-  "+components/viz/common/gpu/raster_context_provider.h",
-  "+components/viz/common/surfaces/frame_sink_id.h",
-  "+gin",
-  "+media",
-  "+mojo/core/embedder",
-  "+mojo/public/cpp/bindings",
-  "+net/base",
-  "+net/http",
-  "+services/media_session/public/cpp",
-  "+services/network/public/cpp",
-  "+services/network/public/mojom",
-  "+services/service_manager/public/cpp",
-  "+third_party/blink/public/common",
-  "+third_party/blink/public/mojom",
-  "+third_party/blink/public/platform",
-  "+third_party/blink/public/strings/grit/blink_strings.h",
-  "+third_party/blink/public/web",
-  # TODO(https://crbug.com/1198341): remove once
-  # webmediaplayer_impl_unittest.cc is moved to Blink.
-  "+third_party/blink/renderer/platform/media",
-
-  # media/mojo is not part of "media" target and should not use MEDIA_EXPORT.
-  "-media/base/media_export.h"
-]
-
-specific_include_rules = {
-  "webmediaplayer_impl_unittest.cc": [
-    "+components/viz/test/test_context_provider.h",
-  ],
-}
diff --git a/media/blink/blink_platform_with_task_environment.cc b/media/blink/blink_platform_with_task_environment.cc
deleted file mode 100644
index 0534e756..0000000
--- a/media/blink/blink_platform_with_task_environment.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/blink/blink_platform_with_task_environment.h"
-
-namespace media {
-
-BlinkPlatformWithTaskEnvironment::BlinkPlatformWithTaskEnvironment()
-    : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
-      main_thread_scheduler_(
-          blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler()) {}
-
-BlinkPlatformWithTaskEnvironment::~BlinkPlatformWithTaskEnvironment() {
-  main_thread_scheduler_->Shutdown();
-}
-
-blink::scheduler::WebThreadScheduler*
-BlinkPlatformWithTaskEnvironment::GetMainThreadScheduler() {
-  return main_thread_scheduler_.get();
-}
-
-// static
-base::test::TaskEnvironment*
-BlinkPlatformWithTaskEnvironment::GetTaskEnvironment() {
-  return &static_cast<BlinkPlatformWithTaskEnvironment*>(
-              blink::Platform::Current())
-              ->task_environment_;
-}
-
-}  // namespace media
diff --git a/media/blink/blink_platform_with_task_environment.h b/media/blink/blink_platform_with_task_environment.h
deleted file mode 100644
index 4ebfff9..0000000
--- a/media/blink/blink_platform_with_task_environment.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_BLINK_BLINK_PLATFORM_WITH_TASK_ENVIRONMENT_H_
-#define MEDIA_BLINK_BLINK_PLATFORM_WITH_TASK_ENVIRONMENT_H_
-
-#include "base/macros.h"
-#include "base/test/task_environment.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
-#include "third_party/blink/public/web/blink.h"
-
-namespace media {
-
-// We must use a custom blink::Platform that ensures the main thread scheduler
-// knows about the TaskEnvironment.
-class BlinkPlatformWithTaskEnvironment : public blink::Platform {
- public:
-  BlinkPlatformWithTaskEnvironment();
-  ~BlinkPlatformWithTaskEnvironment() override;
-
-  blink::scheduler::WebThreadScheduler* GetMainThreadScheduler();
-
-  // Returns |task_environment_| from the current blink::Platform.
-  static base::test::TaskEnvironment* GetTaskEnvironment();
-
- private:
-  base::test::TaskEnvironment task_environment_;
-  std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler_;
-
-  DISALLOW_COPY_AND_ASSIGN(BlinkPlatformWithTaskEnvironment);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_BLINK_BLINK_PLATFORM_WITH_TASK_ENVIRONMENT_H_
diff --git a/media/blink/run_all_unittests.cc b/media/blink/run_all_unittests.cc
deleted file mode 100644
index fa3e4ed..0000000
--- a/media/blink/run_all_unittests.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#include "build/build_config.h"
-#include "media/base/media.h"
-#include "media/blink/blink_platform_with_task_environment.h"
-#include "mojo/public/cpp/bindings/binder_map.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
-#include "third_party/blink/public/web/blink.h"
-
-#if defined(OS_ANDROID)
-#include "media/base/android/media_codec_util.h"
-#endif
-
-#if !defined(OS_IOS)
-#include "mojo/core/embedder/embedder.h"
-#endif
-
-#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
-#include "gin/v8_initializer.h"
-
-using media::BlinkPlatformWithTaskEnvironment;
-
-constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
-#if defined(USE_V8_CONTEXT_SNAPSHOT)
-    gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext;
-#else
-    gin::V8Initializer::V8SnapshotFileType::kDefault;
-#endif  // defined(USE_V8_CONTEXT_SNAPSHOT)
-#endif  // defined(V8_USE_EXTERNAL_STARTUP_DATA)
-
-class MediaBlinkTestSuite : public base::TestSuite {
- public:
-  MediaBlinkTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
-
- private:
-  void Initialize() override {
-    base::TestSuite::Initialize();
-
-#if defined(OS_ANDROID)
-    if (media::MediaCodecUtil::IsMediaCodecAvailable())
-      media::EnablePlatformDecoderSupport();
-#endif
-
-    // Run this here instead of main() to ensure an AtExitManager is already
-    // present.
-    media::InitializeMediaLibrary();
-
-#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
-    gin::V8Initializer::LoadV8Snapshot(kSnapshotType);
-#endif
-
-#if !defined(OS_IOS)
-    // Initialize mojo firstly to enable Blink initialization to use it.
-    mojo::core::Init();
-#endif
-
-    blink::Platform::InitializeBlink();
-    platform_ = std::make_unique<BlinkPlatformWithTaskEnvironment>();
-
-    mojo::BinderMap binders;
-    blink::Initialize(platform_.get(), &binders,
-                      platform_->GetMainThreadScheduler());
-  }
-
-  void Shutdown() override {
-    platform_.reset();
-    base::TestSuite::Shutdown();
-  }
-
-  std::unique_ptr<BlinkPlatformWithTaskEnvironment> platform_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaBlinkTestSuite);
-};
-
-int main(int argc, char** argv) {
-  MediaBlinkTestSuite test_suite(argc, argv);
-  return base::LaunchUnitTests(
-      argc, argv,
-      base::BindOnce(&MediaBlinkTestSuite::Run, base::Unretained(&test_suite)));
-}
diff --git a/mojo/core/broker_win.cc b/mojo/core/broker_win.cc
index 32d10dfc..5014be61 100644
--- a/mojo/core/broker_win.cc
+++ b/mojo/core/broker_win.cc
@@ -58,7 +58,8 @@
   }
 
   Channel::MessagePtr message =
-      Channel::Message::Deserialize(buffer, static_cast<size_t>(bytes_read));
+      Channel::Message::Deserialize(buffer, static_cast<size_t>(bytes_read),
+                                    Channel::HandlePolicy::kAcceptHandles);
   if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) {
     LOG(ERROR) << "Invalid broker message";
 
diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index 24dc374..918ccfd 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -229,6 +229,7 @@
 Channel::MessagePtr Channel::Message::Deserialize(
     const void* data,
     size_t data_num_bytes,
+    HandlePolicy handle_policy,
     base::ProcessHandle from_process) {
   if (data_num_bytes < sizeof(LegacyHeader))
     return nullptr;
@@ -305,6 +306,11 @@
     return nullptr;
   }
 
+  if (num_handles > 0 && handle_policy == HandlePolicy::kRejectHandles) {
+    DLOG(ERROR) << "Rejecting message with unexpected handle attachments.";
+    return nullptr;
+  }
+
   MessagePtr message =
       CreateMessage(payload_size, max_handles, legacy_header->message_type);
   DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
diff --git a/mojo/core/channel.h b/mojo/core/channel.h
index 88761dd..7288dd8 100644
--- a/mojo/core/channel.h
+++ b/mojo/core/channel.h
@@ -188,6 +188,7 @@
     static MessagePtr Deserialize(
         const void* data,
         size_t data_num_bytes,
+        HandlePolicy handle_policy,
         base::ProcessHandle from_process = base::kNullProcessHandle);
 
     virtual const void* data() const = 0;
diff --git a/mojo/core/channel_unittest.cc b/mojo/core/channel_unittest.cc
index e5eee1e..0a377457 100644
--- a/mojo/core/channel_unittest.cc
+++ b/mojo/core/channel_unittest.cc
@@ -136,7 +136,8 @@
 TEST(ChannelTest, LegacyMessageDeserialization) {
   Channel::MessagePtr message = CreateDefaultMessage(true /* legacy_message */);
   Channel::MessagePtr deserialized_message =
-      Channel::Message::Deserialize(message->data(), message->data_num_bytes());
+      Channel::Message::Deserialize(message->data(), message->data_num_bytes(),
+                                    Channel::HandlePolicy::kAcceptHandles);
   TestMessagesAreEqual(message.get(), deserialized_message.get(),
                        true /* legacy_message */);
 }
@@ -145,7 +146,8 @@
   Channel::MessagePtr message =
       CreateDefaultMessage(false /* legacy_message */);
   Channel::MessagePtr deserialized_message =
-      Channel::Message::Deserialize(message->data(), message->data_num_bytes());
+      Channel::Message::Deserialize(message->data(), message->data_num_bytes(),
+                                    Channel::HandlePolicy::kAcceptHandles);
   TestMessagesAreEqual(message.get(), deserialized_message.get(),
                        false /* legacy_message */);
 }
@@ -370,8 +372,10 @@
   header->num_header_bytes = kTotalHeaderSize;
   header->message_type = Channel::Message::MessageType::NORMAL;
   header->num_handles = 0;
-  EXPECT_EQ(nullptr, Channel::Message::Deserialize(&message[0], kMessageSize,
-                                                   base::kNullProcessHandle));
+  EXPECT_EQ(nullptr,
+            Channel::Message::Deserialize(&message[0], kMessageSize,
+                                          Channel::HandlePolicy::kAcceptHandles,
+                                          base::kNullProcessHandle));
 }
 
 #if !defined(OS_WIN) && !defined(OS_APPLE) && !defined(OS_FUCHSIA)
@@ -391,8 +395,10 @@
   header->num_header_bytes = kTotalHeaderSize;
   header->message_type = Channel::Message::MessageType::NORMAL;
   header->num_handles = 0;
-  EXPECT_EQ(nullptr, Channel::Message::Deserialize(&message[0], kMessageSize,
-                                                   base::kNullProcessHandle));
+  EXPECT_EQ(nullptr,
+            Channel::Message::Deserialize(&message[0], kMessageSize,
+                                          Channel::HandlePolicy::kAcceptHandles,
+                                          base::kNullProcessHandle));
 }
 #endif
 
diff --git a/mojo/core/node_channel.cc b/mojo/core/node_channel.cc
index 52fed81f..88d74742 100644
--- a/mojo/core/node_channel.cc
+++ b/mojo/core/node_channel.cc
@@ -734,6 +734,11 @@
         // through the extent of this call because |this| is kept alive and
         // |remote_process_handle_| is never reset once set.
         from_process = remote_process_handle_.Handle();
+
+        // If we don't have a handle to the remote process, we should not be
+        // receiving relay requests from them because we're not the broker.
+        if (from_process == base::kNullProcessHandle)
+          break;
       }
       RelayEventMessageData data;
       if (GetMessagePayload(payload, payload_size, &data)) {
@@ -745,7 +750,7 @@
                                     sizeof(Header) + sizeof(data);
         Channel::MessagePtr message = Channel::Message::Deserialize(
             message_start, payload_size - sizeof(Header) - sizeof(data),
-            from_process);
+            Channel::HandlePolicy::kAcceptHandles, from_process);
         if (!message) {
           DLOG(ERROR) << "Dropping invalid relay message.";
           break;
@@ -764,8 +769,9 @@
       const void* data = static_cast<const void*>(
           reinterpret_cast<const Header*>(payload) + 1);
       Channel::MessagePtr message =
-          Channel::Message::Deserialize(data, payload_size - sizeof(Header));
-      if (!message || message->has_handles()) {
+          Channel::Message::Deserialize(data, payload_size - sizeof(Header),
+                                        Channel::HandlePolicy::kRejectHandles);
+      if (!message) {
         DLOG(ERROR) << "Dropping invalid broadcast message.";
         break;
       }
diff --git a/net/base/host_mapping_rules.cc b/net/base/host_mapping_rules.cc
index 20edf52..a10be8d 100644
--- a/net/base/host_mapping_rules.cc
+++ b/net/base/host_mapping_rules.cc
@@ -8,11 +8,15 @@
 
 #include "base/logging.h"
 #include "base/strings/pattern.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/url_util.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
 
 namespace net {
 
@@ -69,6 +73,36 @@
   return false;
 }
 
+bool HostMappingRules::RewriteUrl(GURL& url) const {
+  // Must be a valid and standard URL. Otherwise, Chrome might not know how to
+  // find/replace the contained host or port.
+  DCHECK(url.is_valid());
+  DCHECK(url.IsStandard());
+  DCHECK(url.has_host());
+
+  HostPortPair host_port_pair = HostPortPair::FromURL(url);
+  if (!RewriteHost(&host_port_pair))
+    return false;
+
+  url::Replacements<char> replacements;
+  std::string port_str = base::NumberToString(host_port_pair.port());
+  replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+  replacements.SetHost(host_port_pair.host().c_str(),
+                       url::Component(0, host_port_pair.host().size()));
+  GURL new_url = url.ReplaceComponents(replacements);
+
+  if (!new_url.is_valid())
+    return false;
+
+  DCHECK(new_url.IsStandard());
+  DCHECK(new_url.has_host());
+  DCHECK_EQ(url.EffectiveIntPort() == url::PORT_UNSPECIFIED,
+            new_url.EffectiveIntPort() == url::PORT_UNSPECIFIED);
+
+  url = std::move(new_url);
+  return true;
+}
+
 bool HostMappingRules::AddRuleFromString(base::StringPiece rule_string) {
   std::vector<base::StringPiece> parts = base::SplitStringPiece(
       base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL), " ",
diff --git a/net/base/host_mapping_rules.h b/net/base/host_mapping_rules.h
index 4d9a765..738219ef 100644
--- a/net/base/host_mapping_rules.h
+++ b/net/base/host_mapping_rules.h
@@ -11,6 +11,8 @@
 #include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 
+class GURL;
+
 namespace net {
 
 class HostPortPair;
@@ -23,10 +25,16 @@
 
   HostMappingRules& operator=(const HostMappingRules& host_mapping_rules);
 
-  // Modifies |*host_port| based on the current rules. Returns true if
-  // |*host_port| was modified, false otherwise.
+  // Modifies `*host_port` based on the current rules. Returns true if
+  // `*host_port` was modified, false otherwise.
   bool RewriteHost(HostPortPair* host_port) const;
 
+  // Modifies the host and port of `url` based on current rules. Returns true if
+  // `url` was modified, false otherwise. May only be called for URLs with a
+  // host and a scheme that is standard, and if the scheme does not allow ports,
+  // only the host will be rewritten.
+  bool RewriteUrl(GURL& url) const;
+
   // Adds a rule to this mapper. The format of the rule can be one of:
   //
   //   "MAP" <hostname_pattern> <replacement_host> [":" <replacement_port>]
diff --git a/net/base/host_mapping_rules_unittest.cc b/net/base/host_mapping_rules_unittest.cc
index 8d8f7b1..272a42b 100644
--- a/net/base/host_mapping_rules_unittest.cc
+++ b/net/base/host_mapping_rules_unittest.cc
@@ -4,8 +4,14 @@
 
 #include "net/base/host_mapping_rules.h"
 
+#include <string.h>
+
 #include "net/base/host_port_pair.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
+#include "url/url_util.h"
 
 namespace net {
 
@@ -81,6 +87,85 @@
   EXPECT_FALSE(rules.AddRuleFromString("INCLUDE x :10"));
 }
 
+TEST(HostMappingRulesTest, RewritesUrl) {
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  GURL url("http://initial.test:111");
+  EXPECT_TRUE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("http://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesUrlPreservingScheme) {
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  GURL url("wss://initial.test:222");
+  EXPECT_TRUE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("wss://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesFileUrl) {
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  // Expect replacement port to be ignored because file URLs do not use port.
+  GURL url("file://initial.test/file.txt");
+  ASSERT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+  EXPECT_TRUE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("file://replacement.test/file.txt"));
+  EXPECT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+}
+
+TEST(HostMappingRulesTest, RewritesAnyStandardUrlWithPort) {
+  const char kScheme[] = "foo";
+  url::ScopedSchemeRegistryForTests scoped_registry;
+  AddStandardScheme(kScheme, url::SCHEME_WITH_HOST_AND_PORT);
+  ASSERT_TRUE(url::IsStandard(kScheme, url::Component(0, strlen(kScheme))));
+
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  GURL url("foo://initial.test:100");
+  EXPECT_TRUE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("foo://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesAnyStandardUrlWithoutPort) {
+  const char kScheme[] = "foo";
+  url::ScopedSchemeRegistryForTests scoped_registry;
+  AddStandardScheme(kScheme, url::SCHEME_WITH_HOST);
+  ASSERT_TRUE(url::IsStandard(kScheme, url::Component(0, strlen(kScheme))));
+
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  // Expect replacement port to be ignored.
+  GURL url("foo://initial.test");
+  ASSERT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+  EXPECT_TRUE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("foo://replacement.test"));
+  EXPECT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+}
+
+TEST(HostMappingRulesTest, IgnoresUnmappedUrls) {
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+  GURL url("http://different.test:111");
+  EXPECT_FALSE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("http://different.test:111"));
+}
+
+TEST(HostMappingRulesTest, IgnoresInvalidReplacementUrls) {
+  HostMappingRules rules;
+  rules.AddRuleFromString("MAP initial.test invalid/url");
+
+  GURL url("http://initial.test");
+  EXPECT_FALSE(rules.RewriteUrl(url));
+  EXPECT_EQ(url, GURL("http://initial.test"));
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc
index f24ac7b0..efa039d3 100644
--- a/net/base/host_port_pair.cc
+++ b/net/base/host_port_pair.cc
@@ -15,13 +15,13 @@
 #include "net/base/parse_number.h"
 #include "net/base/port_util.h"
 #include "url/gurl.h"
+#include "url/scheme_host_port.h"
 
 namespace net {
 
 HostPortPair::HostPortPair() : port_(0) {}
-HostPortPair::HostPortPair(const std::string& in_host, uint16_t in_port)
-    : host_(in_host), port_(in_port) {
-}
+HostPortPair::HostPortPair(base::StringPiece in_host, uint16_t in_port)
+    : host_(in_host), port_(in_port) {}
 
 // static
 HostPortPair HostPortPair::FromURL(const GURL& url) {
@@ -30,6 +30,21 @@
 }
 
 // static
+HostPortPair HostPortPair::FromSchemeHostPort(
+    const url::SchemeHostPort& scheme_host_port) {
+  DCHECK(scheme_host_port.IsValid());
+
+  // HostPortPair assumes hostnames do not have surrounding brackets (as is
+  // commonly used for IPv6 literals), so strip them if present.
+  base::StringPiece host = scheme_host_port.host();
+  if (host.size() >= 2 && host.front() == '[' && host.back() == ']') {
+    host = host.substr(1, host.size() - 2);
+  }
+
+  return HostPortPair(host, scheme_host_port.port());
+}
+
+// static
 HostPortPair HostPortPair::FromIPEndPoint(const IPEndPoint& ipe) {
   return HostPortPair(ipe.ToStringWithoutPort(), ipe.port());
 }
diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h
index 1efb721e..2ac2aaf2 100644
--- a/net/base/host_port_pair.h
+++ b/net/base/host_port_pair.h
@@ -10,10 +10,15 @@
 #include <string>
 #include <tuple>
 
+#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
 
 class GURL;
 
+namespace url {
+class SchemeHostPort;
+}  // namespace url
+
 namespace net {
 
 class IPEndPoint;
@@ -22,11 +27,14 @@
  public:
   HostPortPair();
   // If |in_host| represents an IPv6 address, it should not bracket the address.
-  HostPortPair(const std::string& in_host, uint16_t in_port);
+  HostPortPair(base::StringPiece in_host, uint16_t in_port);
 
   // Creates a HostPortPair for the origin of |url|.
   static HostPortPair FromURL(const GURL& url);
 
+  static HostPortPair FromSchemeHostPort(
+      const url::SchemeHostPort& scheme_host_port);
+
   // Creates a HostPortPair from an IPEndPoint.
   static HostPortPair FromIPEndPoint(const IPEndPoint& ipe);
 
diff --git a/net/base/host_port_pair_unittest.cc b/net/base/host_port_pair_unittest.cc
index 1f9a9f9..99e7c89 100644
--- a/net/base/host_port_pair_unittest.cc
+++ b/net/base/host_port_pair_unittest.cc
@@ -6,6 +6,8 @@
 
 #include "net/test/gtest_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
 
 using std::string;
 
@@ -112,6 +114,36 @@
   EXPECT_FALSE(new_a_10.Equals(b_11));
 }
 
+TEST(HostPortPairTest, ParsesFromUrl) {
+  HostPortPair parsed = HostPortPair::FromURL(GURL("https://foo.test:1250"));
+  HostPortPair expected("foo.test", 1250);
+
+  EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromUrlWithIpv6Brackets) {
+  HostPortPair parsed = HostPortPair::FromURL(GURL("https://[::1]"));
+  HostPortPair expected("::1", 443);
+
+  EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromSchemeHostPort) {
+  HostPortPair parsed = HostPortPair::FromSchemeHostPort(
+      url::SchemeHostPort("ws", "bar.test", 111));
+  HostPortPair expected("bar.test", 111);
+
+  EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromSchemeHostPortWithIpv6Brackets) {
+  HostPortPair parsed = HostPortPair::FromSchemeHostPort(
+      url::SchemeHostPort("wss", "[::1022]", 112));
+  HostPortPair expected("::1022", 112);
+
+  EXPECT_EQ(parsed, expected);
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 4593eb45..e23f3b0 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -479,8 +479,7 @@
         << "These must be in sync via SetResponse and SetAuthResponse.";
     return &auth_response_;
   }
-  DCHECK_EQ(cache_entry_status_, response_.cache_entry_status)
-      << "These must be in sync via SetResponse and SetAuthResponse.";
+  // TODO(https://crbug.com/1219402): This should check in `response_`
   return &response_;
 }
 
@@ -2091,7 +2090,8 @@
   entry_ = nullptr;
   new_entry_ = nullptr;
 
-  SetResponse(HttpResponseInfo());
+  // TODO(https://crbug.com/1219402): This should probably clear `response_`,
+  // too, once things are fixed so it's safe to do so.
 
   // Bypass the cache for timeout scenario.
   if (result == ERR_CACHE_LOCK_TIMEOUT)
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc
index a07072b..03f9754 100644
--- a/net/http/http_stream_factory_job.cc
+++ b/net/http/http_stream_factory_job.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
@@ -24,6 +25,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "net/base/host_port_pair.h"
 #include "net/base/port_util.h"
 #include "net/base/proxy_delegate.h"
 #include "net/base/trace_constants.h"
@@ -55,6 +57,7 @@
 #include "net/spdy/spdy_session.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+#include "url/scheme_host_port.h"
 #include "url/url_constants.h"
 
 namespace net {
@@ -103,7 +106,7 @@
                             const ProxyInfo& proxy_info,
                             const SSLConfig& server_ssl_config,
                             const SSLConfig& proxy_ssl_config,
-                            HostPortPair destination,
+                            url::SchemeHostPort destination,
                             GURL origin_url,
                             NextProto alternative_protocol,
                             quic::ParsedQuicVersion quic_version,
@@ -122,7 +125,7 @@
       connection_(new ClientSocketHandle),
       session_(session),
       next_state_(STATE_NONE),
-      destination_(destination),
+      destination_(std::move(destination)),
       origin_url_(origin_url),
       is_websocket_(is_websocket),
       try_websocket_over_http2_(is_websocket_ &&
@@ -139,12 +142,9 @@
       job_type_(job_type),
       using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) ||
                  origin_url_.SchemeIs(url::kWssScheme)),
-      using_quic_(alternative_protocol == kProtoQUIC ||
-                  (ShouldForceQuic(session,
-                                   destination,
-                                   origin_url,
-                                   proxy_info,
-                                   using_ssl_))),
+      using_quic_(
+          alternative_protocol == kProtoQUIC ||
+          (ShouldForceQuic(session, destination_, proxy_info, using_ssl_))),
       quic_version_(quic_version),
       expect_spdy_(alternative_protocol == kProtoHTTP2 && !using_quic_),
       using_spdy_(false),
@@ -170,6 +170,10 @@
                                           request_info_.secure_dns_policy)),
       stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
       init_connection_already_resumed_(false) {
+  // Websocket `destination` schemes should be converted to HTTP(S).
+  DCHECK(base::LowerCaseEqualsASCII(destination_.scheme(), url::kHttpScheme) ||
+         base::LowerCaseEqualsASCII(destination_.scheme(), url::kHttpsScheme));
+
   // QUIC can only be spoken to servers, never to proxies.
   if (alternative_protocol == kProtoQUIC)
     DCHECK(proxy_info_.is_direct());
@@ -177,8 +181,7 @@
   // The Job is forced to use QUIC without a designated version, try the
   // preferred QUIC version that is supported by default.
   if (quic_version_ == quic::ParsedQuicVersion::Unsupported() &&
-      ShouldForceQuic(session, destination, origin_url, proxy_info,
-                      using_ssl_)) {
+      ShouldForceQuic(session, destination_, proxy_info, using_ssl_)) {
     quic_version_ =
         session->context().quic_context->params()->supported_versions[0];
   }
@@ -345,11 +348,11 @@
 }
 
 // static
-bool HttpStreamFactory::Job::ShouldForceQuic(HttpNetworkSession* session,
-                                             const HostPortPair& destination,
-                                             const GURL& origin_url,
-                                             const ProxyInfo& proxy_info,
-                                             bool using_ssl) {
+bool HttpStreamFactory::Job::ShouldForceQuic(
+    HttpNetworkSession* session,
+    const url::SchemeHostPort& destination,
+    const ProxyInfo& proxy_info,
+    bool using_ssl) {
   if (!session->IsQuicEnabled())
     return false;
   // If this is going through a QUIC proxy, only force QUIC for insecure
@@ -358,10 +361,14 @@
   if (proxy_info.is_quic())
     return !using_ssl;
   const QuicParams* quic_params = session->context().quic_context->params();
+  // TODO(crbug.com/1206799): Consider converting `origins_to_force_quic_on` to
+  // use url::SchemeHostPort.
   return (base::Contains(quic_params->origins_to_force_quic_on,
                          HostPortPair()) ||
-          base::Contains(quic_params->origins_to_force_quic_on, destination)) &&
-         proxy_info.is_direct() && origin_url.SchemeIs(url::kHttpsScheme);
+          base::Contains(quic_params->origins_to_force_quic_on,
+                         HostPortPair::FromSchemeHostPort(destination))) &&
+         proxy_info.is_direct() &&
+         base::LowerCaseEqualsASCII(destination.scheme(), url::kHttpsScheme);
 }
 
 // static
@@ -813,11 +820,13 @@
   if (job_type_ == PRECONNECT) {
     DCHECK(!is_websocket_);
     DCHECK(request_info_.socket_tag == SocketTag());
+    // TODO(crbug.com/1206799): Pass scheme to socket connection.
     return PreconnectSocketsForHttpRequest(
-        GetSocketGroup(), destination_, request_info_.load_flags, priority_,
-        session_, proxy_info_, server_ssl_config_, proxy_ssl_config_,
-        request_info_.privacy_mode, request_info_.network_isolation_key,
-        request_info_.secure_dns_policy, net_log_, num_streams_);
+        GetSocketGroup(), HostPortPair::FromSchemeHostPort(destination_),
+        request_info_.load_flags, priority_, session_, proxy_info_,
+        server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode,
+        request_info_.network_isolation_key, request_info_.secure_dns_policy,
+        net_log_, num_streams_);
   }
 
   ClientSocketPool::ProxyAuthCallback proxy_auth_callback =
@@ -828,19 +837,23 @@
     DCHECK_EQ(SecureDnsPolicy::kAllow, request_info_.secure_dns_policy);
     SSLConfig websocket_server_ssl_config = server_ssl_config_;
     websocket_server_ssl_config.alpn_protos.clear();
+    // TODO(crbug.com/1206799): Pass scheme to socket connection.
     return InitSocketHandleForWebSocketRequest(
-        GetSocketGroup(), destination_, request_info_.load_flags, priority_,
-        session_, proxy_info_, websocket_server_ssl_config, proxy_ssl_config_,
+        GetSocketGroup(), HostPortPair::FromSchemeHostPort(destination_),
+        request_info_.load_flags, priority_, session_, proxy_info_,
+        websocket_server_ssl_config, proxy_ssl_config_,
         request_info_.privacy_mode, request_info_.network_isolation_key,
         net_log_, connection_.get(), io_callback_, proxy_auth_callback);
   }
 
+  // TODO(crbug.com/1206799): Pass scheme to socket connection.
   return InitSocketHandleForHttpRequest(
-      GetSocketGroup(), destination_, request_info_.load_flags, priority_,
-      session_, proxy_info_, server_ssl_config_, proxy_ssl_config_,
-      request_info_.privacy_mode, request_info_.network_isolation_key,
-      request_info_.secure_dns_policy, request_info_.socket_tag, net_log_,
-      connection_.get(), io_callback_, proxy_auth_callback);
+      GetSocketGroup(), HostPortPair::FromSchemeHostPort(destination_),
+      request_info_.load_flags, priority_, session_, proxy_info_,
+      server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode,
+      request_info_.network_isolation_key, request_info_.secure_dns_policy,
+      request_info_.socket_tag, net_log_, connection_.get(), io_callback_,
+      proxy_auth_callback);
 }
 
 int HttpStreamFactory::Job::DoInitConnectionImplQuic() {
@@ -867,12 +880,15 @@
     // The certificate of a QUIC alternative server is expected to be valid
     // for the origin of the request (in addition to being valid for the
     // server itself).
-    destination = destination_;
+    destination = HostPortPair::FromSchemeHostPort(destination_);
     ssl_config = &server_ssl_config_;
   }
+  DCHECK(url.SchemeIs(url::kHttpsScheme));
+
+  // TODO(crbug.com/1206799): Pass scheme to QUIC request.
   int rv = quic_request_.Request(
-      destination, quic_version_, request_info_.privacy_mode, priority_,
-      request_info_.socket_tag, request_info_.network_isolation_key,
+      std::move(destination), quic_version_, request_info_.privacy_mode,
+      priority_, request_info_.socket_tag, request_info_.network_isolation_key,
       request_info_.secure_dns_policy, proxy_info_.is_direct(),
       ssl_config->GetCertVerifyFlags(), url, net_log_, &net_error_details_,
       base::BindOnce(&Job::OnFailedOnDefaultNetwork, ptr_factory_.GetWeakPtr()),
@@ -1270,14 +1286,14 @@
     const ProxyInfo& proxy_info,
     const SSLConfig& server_ssl_config,
     const SSLConfig& proxy_ssl_config,
-    HostPortPair destination,
+    url::SchemeHostPort destination,
     GURL origin_url,
     bool is_websocket,
     bool enable_ip_based_pooling,
     NetLog* net_log) {
   return std::make_unique<HttpStreamFactory::Job>(
       delegate, job_type, session, request_info, priority, proxy_info,
-      server_ssl_config, proxy_ssl_config, destination, origin_url,
+      server_ssl_config, proxy_ssl_config, std::move(destination), origin_url,
       kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), is_websocket,
       enable_ip_based_pooling, net_log);
 }
@@ -1292,7 +1308,7 @@
     const ProxyInfo& proxy_info,
     const SSLConfig& server_ssl_config,
     const SSLConfig& proxy_ssl_config,
-    HostPortPair destination,
+    url::SchemeHostPort destination,
     GURL origin_url,
     NextProto alternative_protocol,
     quic::ParsedQuicVersion quic_version,
@@ -1301,7 +1317,7 @@
     NetLog* net_log) {
   return std::make_unique<HttpStreamFactory::Job>(
       delegate, job_type, session, request_info, priority, proxy_info,
-      server_ssl_config, proxy_ssl_config, destination, origin_url,
+      server_ssl_config, proxy_ssl_config, std::move(destination), origin_url,
       alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling,
       net_log);
 }
diff --git a/net/http/http_stream_factory_job.h b/net/http/http_stream_factory_job.h
index e75520d..579818b7 100644
--- a/net/http/http_stream_factory_job.h
+++ b/net/http/http_stream_factory_job.h
@@ -34,6 +34,7 @@
 #include "net/spdy/spdy_session_key.h"
 #include "net/spdy/spdy_session_pool.h"
 #include "net/ssl/ssl_config_service.h"
+#include "url/scheme_host_port.h"
 
 namespace net {
 
@@ -156,7 +157,7 @@
       const ProxyInfo& proxy_info,
       const SSLConfig& server_ssl_config,
       const SSLConfig& proxy_ssl_config,
-      HostPortPair destination,
+      url::SchemeHostPort destination,
       GURL origin_url,
       NextProto alternative_protocol,
       quic::ParsedQuicVersion quic_version,
@@ -314,8 +315,7 @@
 
   // Called in Job constructor: should Job be forced to use QUIC.
   static bool ShouldForceQuic(HttpNetworkSession* session,
-                              const HostPortPair& destination,
-                              const GURL& origin_url,
+                              const url::SchemeHostPort& destination,
                               const ProxyInfo& proxy_info,
                               bool using_ssl);
 
@@ -363,7 +363,7 @@
 
   // The server we are trying to reach, could be that of the origin or of the
   // alternative service (after applying host mapping rules).
-  const HostPortPair destination_;
+  const url::SchemeHostPort destination_;
 
   // The origin url we're trying to reach. This url may be different from the
   // original request when host mapping rules are set-up.
@@ -483,7 +483,7 @@
       const ProxyInfo& proxy_info,
       const SSLConfig& server_ssl_config,
       const SSLConfig& proxy_ssl_config,
-      HostPortPair destination,
+      url::SchemeHostPort destination,
       GURL origin_url,
       bool is_websocket,
       bool enable_ip_based_pooling,
@@ -498,7 +498,7 @@
       const ProxyInfo& proxy_info,
       const SSLConfig& server_ssl_config,
       const SSLConfig& proxy_ssl_config,
-      HostPortPair destination,
+      url::SchemeHostPort destination,
       GURL origin_url,
       NextProto alternative_protocol,
       quic::ParsedQuicVersion quic_version,
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc
index 4c34611..9a96bf8 100644
--- a/net/http/http_stream_factory_job_controller.cc
+++ b/net/http/http_stream_factory_job_controller.cc
@@ -28,6 +28,10 @@
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_resolution_request.h"
 #include "net/spdy/spdy_session.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
 #include "url/url_constants.h"
 
 namespace net {
@@ -45,6 +49,36 @@
   return dict;
 }
 
+GURL CreateAltSvcUrl(const GURL& origin_url,
+                     const HostPortPair& alternative_destination) {
+  DCHECK(origin_url.is_valid());
+  DCHECK(origin_url.IsStandard());
+
+  url::Replacements<char> replacements;
+  std::string port_str = base::NumberToString(alternative_destination.port());
+  replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+  replacements.SetHost(
+      alternative_destination.host().c_str(),
+      url::Component(0, alternative_destination.host().size()));
+
+  return origin_url.ReplaceComponents(replacements);
+}
+
+void ConvertWsToHttp(url::SchemeHostPort& input) {
+  if (base::EqualsCaseInsensitiveASCII(input.scheme(), url::kHttpScheme) ||
+      base::EqualsCaseInsensitiveASCII(input.scheme(), url::kHttpsScheme)) {
+    return;
+  }
+
+  if (base::EqualsCaseInsensitiveASCII(input.scheme(), url::kWsScheme)) {
+    input = url::SchemeHostPort(url::kHttpScheme, input.host(), input.port());
+    return;
+  }
+
+  DCHECK(base::EqualsCaseInsensitiveASCII(input.scheme(), url::kWssScheme));
+  input = url::SchemeHostPort(url::kHttpsScheme, input.host(), input.port());
+}
+
 }  // namespace
 
 // The maximum time to wait for the alternate job to complete before resuming
@@ -105,6 +139,15 @@
           session->net_log(),
           NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)) {
   DCHECK(factory);
+  DCHECK(base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+                                          url::kHttpScheme) ||
+         base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+                                          url::kHttpsScheme) ||
+         base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+                                          url::kWsScheme) ||
+         base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+                                          url::kWssScheme));
+
   net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, [&] {
     return NetLogJobControllerParams(request_info.url, is_preconnect);
   });
@@ -613,8 +656,8 @@
     return OK;
   }
 
-  HostPortPair destination(HostPortPair::FromURL(request_info_.url));
-  GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
+  GURL origin_url = request_info_.url;
+  RewriteUrlWithHostMappingRules(origin_url);
 
   CompletionOnceCallback io_callback =
       base::BindOnce(&JobController::OnIOComplete, base::Unretained(this));
@@ -658,9 +701,15 @@
 int HttpStreamFactory::JobController::DoCreateJobs() {
   DCHECK(!main_job_);
   DCHECK(!alternative_job_);
+  DCHECK(request_info_.url.is_valid());
+  DCHECK(request_info_.url.IsStandard());
 
-  HostPortPair destination(HostPortPair::FromURL(request_info_.url));
-  GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
+  GURL origin_url = request_info_.url;
+  RewriteUrlWithHostMappingRules(origin_url);
+
+  url::SchemeHostPort destination(origin_url);
+  DCHECK(destination.IsValid());
+  ConvertWsToHttp(destination);
 
   // Create an alternative job if alternative service is set up for this domain,
   // but only if we'll be speaking directly to the server, since QUIC through
@@ -682,27 +731,33 @@
     // preconnects is currently ignored (see RequestSocketsForPool()), but could
     // be used at some point for proxy resolution or something.
     if (alternative_service_info_.protocol() != kProtoUnknown) {
-      HostPortPair alternative_destination(
-          alternative_service_info_.host_port_pair());
-      ignore_result(
-          ApplyHostMappingRules(request_info_.url, &alternative_destination));
+      GURL alternative_url = CreateAltSvcUrl(
+          origin_url, alternative_service_info_.host_port_pair());
+      RewriteUrlWithHostMappingRules(alternative_url);
+
+      url::SchemeHostPort alternative_destination =
+          url::SchemeHostPort(alternative_url);
+      ConvertWsToHttp(alternative_destination);
+
       main_job_ = job_factory_->CreateAltSvcJob(
           this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
-          server_ssl_config_, proxy_ssl_config_, alternative_destination,
-          origin_url, alternative_service_info_.protocol(), quic_version,
-          is_websocket_, enable_ip_based_pooling_, session_->net_log());
+          server_ssl_config_, proxy_ssl_config_,
+          std::move(alternative_destination), origin_url,
+          alternative_service_info_.protocol(), quic_version, is_websocket_,
+          enable_ip_based_pooling_, session_->net_log());
     } else {
       main_job_ = job_factory_->CreateMainJob(
           this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
-          server_ssl_config_, proxy_ssl_config_, destination, origin_url,
-          is_websocket_, enable_ip_based_pooling_, session_->net_log());
+          server_ssl_config_, proxy_ssl_config_, std::move(destination),
+          origin_url, is_websocket_, enable_ip_based_pooling_,
+          session_->net_log());
     }
     main_job_->Preconnect(num_streams_);
     return OK;
   }
   main_job_ = job_factory_->CreateMainJob(
       this, MAIN, session_, request_info_, priority_, proxy_info_,
-      server_ssl_config_, proxy_ssl_config_, destination, origin_url,
+      server_ssl_config_, proxy_ssl_config_, std::move(destination), origin_url,
       is_websocket_, enable_ip_based_pooling_, net_log_.net_log());
   // Alternative Service can only be set for HTTPS requests while Alternative
   // Proxy is set for HTTP requests.
@@ -713,15 +768,20 @@
              << " port: " << alternative_service_info_.host_port_pair().port()
              << " version: " << quic_version << ")";
 
-    HostPortPair alternative_destination(
-        alternative_service_info_.host_port_pair());
-    ignore_result(
-        ApplyHostMappingRules(request_info_.url, &alternative_destination));
+    GURL alternative_url =
+        CreateAltSvcUrl(origin_url, alternative_service_info_.host_port_pair());
+    RewriteUrlWithHostMappingRules(alternative_url);
+
+    url::SchemeHostPort alternative_destination =
+        url::SchemeHostPort(alternative_url);
+    ConvertWsToHttp(alternative_destination);
+
     alternative_job_ = job_factory_->CreateAltSvcJob(
         this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_,
-        server_ssl_config_, proxy_ssl_config_, alternative_destination,
-        origin_url, alternative_service_info_.protocol(), quic_version,
-        is_websocket_, enable_ip_based_pooling_, net_log_.net_log());
+        server_ssl_config_, proxy_ssl_config_,
+        std::move(alternative_destination), origin_url,
+        alternative_service_info_.protocol(), quic_version, is_websocket_,
+        enable_ip_based_pooling_, net_log_.net_log());
 
     main_job_is_blocked_ = true;
     alternative_job_->Start(request_->stream_type());
@@ -892,18 +952,9 @@
                             ProxyInfo(), ResolveErrorInfo());
 }
 
-GURL HttpStreamFactory::JobController::ApplyHostMappingRules(
-    const GURL& url,
-    HostPortPair* endpoint) {
-  if (session_->params().host_mapping_rules.RewriteHost(endpoint)) {
-    url::Replacements<char> replacements;
-    const std::string port_str = base::NumberToString(endpoint->port());
-    replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
-    replacements.SetHost(endpoint->host().c_str(),
-                         url::Component(0, endpoint->host().size()));
-    return url.ReplaceComponents(replacements);
-  }
-  return url;
+void HttpStreamFactory::JobController::RewriteUrlWithHostMappingRules(
+    GURL& url) {
+  session_->params().host_mapping_rules.RewriteUrl(url);
 }
 
 AlternativeServiceInfo
@@ -949,12 +1000,12 @@
   if (!original_url.SchemeIs(url::kHttpsScheme))
     return AlternativeServiceInfo();
 
-  url::SchemeHostPort origin(original_url);
   HttpServerProperties& http_server_properties =
       *session_->http_server_properties();
   const AlternativeServiceInfoVector alternative_service_info_vector =
       http_server_properties.GetAlternativeServiceInfos(
-          origin, request_info.network_isolation_key);
+          url::SchemeHostPort(original_url),
+          request_info.network_isolation_key);
   if (alternative_service_info_vector.empty())
     return AlternativeServiceInfo();
 
@@ -997,7 +1048,7 @@
     if (!session_->params().enable_user_alternate_protocol_ports &&
         (alternative_service_info.alternative_service().port >=
              kUnrestrictedPort &&
-         origin.port() < kUnrestrictedPort))
+         original_url.EffectiveIntPort() < kUnrestrictedPort))
       continue;
 
     if (alternative_service_info.protocol() == kProtoHTTP2) {
@@ -1032,21 +1083,24 @@
       continue;
 
     // Check whether there is an existing QUIC session to use for this origin.
-    HostPortPair mapped_origin(origin.host(), origin.port());
-    ignore_result(ApplyHostMappingRules(original_url, &mapped_origin));
+    GURL mapped_origin = original_url;
+    RewriteUrlWithHostMappingRules(mapped_origin);
     QuicSessionKey session_key(
-        mapped_origin, request_info.privacy_mode, request_info.socket_tag,
-        request_info.network_isolation_key, request_info.secure_dns_policy);
+        HostPortPair::FromURL(mapped_origin), request_info.privacy_mode,
+        request_info.socket_tag, request_info.network_isolation_key,
+        request_info.secure_dns_policy);
 
-    HostPortPair destination(alternative_service_info.host_port_pair());
-    if (session_key.host() != destination.host() &&
+    GURL destination = CreateAltSvcUrl(
+        original_url, alternative_service_info.host_port_pair());
+    if (session_key.host() != destination.host_piece() &&
         !session_->context().quic_context->params()->allow_remote_alt_svc) {
       continue;
     }
-    ignore_result(ApplyHostMappingRules(original_url, &destination));
+    RewriteUrlWithHostMappingRules(destination);
 
-    if (session_->quic_stream_factory()->CanUseExistingSession(session_key,
-                                                               destination))
+    // TODO(crbug.com/1206799): Pass scheme to CanUseExistingSession().
+    if (session_->quic_stream_factory()->CanUseExistingSession(
+            session_key, HostPortPair::FromURL(destination)))
       return alternative_service_info;
 
     if (!IsQuicAllowedForHost(destination.host()))
diff --git a/net/http/http_stream_factory_job_controller.h b/net/http/http_stream_factory_job_controller.h
index abc7eef..53292b72 100644
--- a/net/http/http_stream_factory_job_controller.h
+++ b/net/http/http_stream_factory_job_controller.h
@@ -49,7 +49,7 @@
   const Job* main_job() const { return main_job_.get(); }
   const Job* alternative_job() const { return alternative_job_.get(); }
 
-  GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
+  void RewriteUrlWithHostMappingRules(GURL& url);
 
   // Methods below are called by HttpStreamFactory only.
   // Creates request and hands out to HttpStreamFactory, this will also create
diff --git a/net/http/http_stream_factory_test_util.cc b/net/http/http_stream_factory_test_util.cc
index 95c0ab0..3da68eec 100644
--- a/net/http/http_stream_factory_test_util.cc
+++ b/net/http/http_stream_factory_test_util.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "net/proxy_resolution/proxy_info.h"
+#include "url/scheme_host_port.h"
 
 using ::testing::_;
 
@@ -24,7 +25,7 @@
     ProxyInfo proxy_info,
     const SSLConfig& server_ssl_config,
     const SSLConfig& proxy_ssl_config,
-    HostPortPair destination,
+    url::SchemeHostPort destination,
     GURL origin_url,
     NextProto alternative_protocol,
     quic::ParsedQuicVersion quic_version,
@@ -39,7 +40,7 @@
                              proxy_info,
                              server_ssl_config,
                              proxy_ssl_config,
-                             destination,
+                             std::move(destination),
                              origin_url,
                              alternative_protocol,
                              quic_version,
@@ -67,7 +68,7 @@
     const ProxyInfo& proxy_info,
     const SSLConfig& server_ssl_config,
     const SSLConfig& proxy_ssl_config,
-    HostPortPair destination,
+    url::SchemeHostPort destination,
     GURL origin_url,
     bool is_websocket,
     bool enable_ip_based_pooling,
@@ -77,8 +78,8 @@
 
   auto main_job = std::make_unique<MockHttpStreamFactoryJob>(
       delegate, job_type, session, request_info, priority, proxy_info,
-      SSLConfig(), SSLConfig(), destination, origin_url, kProtoUnknown,
-      quic::ParsedQuicVersion::Unsupported(), is_websocket,
+      SSLConfig(), SSLConfig(), std::move(destination), origin_url,
+      kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), is_websocket,
       enable_ip_based_pooling, net_log);
 
   // Keep raw pointer to Job but pass ownership.
@@ -96,7 +97,7 @@
     const ProxyInfo& proxy_info,
     const SSLConfig& server_ssl_config,
     const SSLConfig& proxy_ssl_config,
-    HostPortPair destination,
+    url::SchemeHostPort destination,
     GURL origin_url,
     NextProto alternative_protocol,
     quic::ParsedQuicVersion quic_version,
@@ -105,8 +106,9 @@
     NetLog* net_log) {
   auto alternative_job = std::make_unique<MockHttpStreamFactoryJob>(
       delegate, job_type, session, request_info, priority, proxy_info,
-      SSLConfig(), SSLConfig(), destination, origin_url, alternative_protocol,
-      quic_version, is_websocket, enable_ip_based_pooling, net_log);
+      SSLConfig(), SSLConfig(), std::move(destination), origin_url,
+      alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling,
+      net_log);
 
   // Keep raw pointer to Job but pass ownership.
   alternative_job_ = alternative_job.get();
diff --git a/net/http/http_stream_factory_test_util.h b/net/http/http_stream_factory_test_util.h
index e352f36..d94b2420 100644
--- a/net/http/http_stream_factory_test_util.h
+++ b/net/http/http_stream_factory_test_util.h
@@ -16,6 +16,7 @@
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/socket/next_proto.h"
 #include "testing/gmock/include/gmock/gmock.h"
+#include "url/scheme_host_port.h"
 
 using testing::_;
 using testing::Invoke;
@@ -109,7 +110,7 @@
                            ProxyInfo proxy_info,
                            const SSLConfig& server_ssl_config,
                            const SSLConfig& proxy_ssl_config,
-                           HostPortPair destination,
+                           url::SchemeHostPort destination,
                            GURL origin_url,
                            NextProto alternative_protocol,
                            quic::ParsedQuicVersion quic_version,
@@ -139,7 +140,7 @@
       const ProxyInfo& proxy_info,
       const SSLConfig& server_ssl_config,
       const SSLConfig& proxy_ssl_config,
-      HostPortPair destination,
+      url::SchemeHostPort destination,
       GURL origin_url,
       bool is_websocket,
       bool enable_ip_based_pooling,
@@ -154,7 +155,7 @@
       const ProxyInfo& proxy_info,
       const SSLConfig& server_ssl_config,
       const SSLConfig& proxy_ssl_config,
-      HostPortPair destination,
+      url::SchemeHostPort destination,
       GURL origin_url,
       NextProto alternative_protocol,
       quic::ParsedQuicVersion quic_version,
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 6aac0a16..7428f4dd 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -1102,27 +1102,6 @@
   return this;
 }
 
-void OutOfProcessInstance::DocumentHasUnsupportedFeature(
-    const std::string& feature) {
-  DCHECK(!feature.empty());
-  std::string metric("PDF_Unsupported_");
-  metric += feature;
-  if (!unsupported_features_reported_.count(metric)) {
-    unsupported_features_reported_.insert(metric);
-    UserMetricsRecordAction(metric);
-  }
-
-  // Since we use an info bar, only do this for full frame plugins..
-  if (!full_frame())
-    return;
-
-  if (told_browser_about_unsupported_feature_)
-    return;
-  told_browser_about_unsupported_feature_ = true;
-
-  pp::PDF::HasUnsupportedFeature(this);
-}
-
 void OutOfProcessInstance::ResetRecentlySentFindUpdate(int32_t /* unused */) {
   recently_sent_find_update_ = false;
 }
@@ -1315,6 +1294,11 @@
   pp::PDF::SetContentRestriction(this, content_restrictions);
 }
 
+void OutOfProcessInstance::NotifyUnsupportedFeature() {
+  DCHECK(full_frame());
+  pp::PDF::HasUnsupportedFeature(this);
+}
+
 void OutOfProcessInstance::UserMetricsRecordAction(const std::string& action) {
   // TODO(raymes): Move this function to PPB_UMA_Private.
   pp::PDF::UserMetricsRecordAction(this, pp::Var(action));
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h
index 0bd9eb5..b6596f5 100644
--- a/pdf/out_of_process_instance.h
+++ b/pdf/out_of_process_instance.h
@@ -9,7 +9,6 @@
 #include <string.h>
 
 #include <memory>
-#include <set>
 #include <string>
 #include <utility>
 #include <vector>
@@ -111,7 +110,6 @@
                                                const char16_t* term,
                                                bool case_sensitive) override;
   pp::Instance* GetPluginInstance() override;
-  void DocumentHasUnsupportedFeature(const std::string& feature) override;
   bool IsPrintPreview() override;
   void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
   void SetSelectedText(const std::string& selected_text) override;
@@ -156,6 +154,7 @@
   void DidStartLoading() override;
   void DidStopLoading() override;
   void OnPrintPreviewLoaded() override;
+  void NotifyUnsupportedFeature() override;
   void UserMetricsRecordAction(const std::string& action) override;
 
  private:
@@ -206,14 +205,6 @@
 
   DocumentLoadState preview_document_load_state_ = DocumentLoadState::kComplete;
 
-  // Used so that we only tell the browser once about an unsupported feature, to
-  // avoid the infobar going up more than once.
-  bool told_browser_about_unsupported_feature_ = false;
-
-  // Keeps track of which unsupported features we reported, so we avoid spamming
-  // the stats if a feature shows up many times per document.
-  std::set<std::string> unsupported_features_reported_;
-
   // True if the plugin is loaded in print preview, otherwise false.
   bool is_print_preview_ = false;
 
diff --git a/pdf/pdf_view_plugin_base.cc b/pdf/pdf_view_plugin_base.cc
index e45430d..346e529e 100644
--- a/pdf/pdf_view_plugin_base.cc
+++ b/pdf/pdf_view_plugin_base.cc
@@ -17,6 +17,7 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/containers/fixed_flat_map.h"
+#include "base/containers/flat_set.h"
 #include "base/containers/span.h"
 #include "base/feature_list.h"
 #include "base/i18n/time_formatting.h"
@@ -314,6 +315,22 @@
   paint_manager_.InvalidateRect(gfx::Rect(plugin_rect_.size()));
 }
 
+void PdfViewPluginBase::DocumentHasUnsupportedFeature(
+    const std::string& feature) {
+  DCHECK(!feature.empty());
+  const std::string metric = "PDF_Unsupported_" + feature;
+  if (!unsupported_features_reported_.count(metric)) {
+    unsupported_features_reported_.insert(metric);
+    UserMetricsRecordAction(metric);
+  }
+
+  if (!full_frame() || notified_browser_about_unsupported_feature_)
+    return;
+
+  NotifyUnsupportedFeature();
+  notified_browser_about_unsupported_feature_ = true;
+}
+
 void PdfViewPluginBase::DocumentLoadProgress(uint32_t available,
                                              uint32_t doc_size) {
   double progress = 0.0;
diff --git a/pdf/pdf_view_plugin_base.h b/pdf/pdf_view_plugin_base.h
index 8ab4c32..12822e4e 100644
--- a/pdf/pdf_view_plugin_base.h
+++ b/pdf/pdf_view_plugin_base.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/containers/flat_set.h"
 #include "base/memory/weak_ptr.h"
 #include "pdf/paint_manager.h"
 #include "pdf/pdf_engine.h"
@@ -92,6 +93,7 @@
   std::unique_ptr<UrlLoader> CreateUrlLoader() override;
   void DocumentLoadComplete() override;
   void DocumentLoadFailed() override;
+  void DocumentHasUnsupportedFeature(const std::string& feature) override;
   void DocumentLoadProgress(uint32_t available, uint32_t doc_size) override;
   void FormTextFieldFocusChange(bool in_focus) override;
   SkColor GetBackgroundColor() override;
@@ -296,6 +298,10 @@
   // Performs tasks necessary when the document is loaded in print preview mode.
   virtual void OnPrintPreviewLoaded() = 0;
 
+  // Notifies the user about unsupported feature if the PDF Viewer occupies the
+  // full frame.
+  virtual void NotifyUnsupportedFeature() = 0;
+
   // Records user actions.
   virtual void UserMetricsRecordAction(const std::string& action) = 0;
 
@@ -501,6 +507,14 @@
   // reconstructing the tree for new document layouts.
   int32_t next_accessibility_page_index_ = 0;
 
+  // Keeps track of which unsupported features have been reported to avoid
+  // spamming the metrics if a feature shows up many times per document.
+  base::flat_set<std::string> unsupported_features_reported_;
+
+  // Indicates whether the browser has been notified about an unsupported
+  // feature once, which helps prevent the infobar from going up more than once.
+  bool notified_browser_about_unsupported_feature_ = false;
+
   // Whether the document is in edit mode.
   bool edit_mode_ = false;
 
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc
index c01eeea..dff39a4 100644
--- a/pdf/pdf_view_plugin_base_unittest.cc
+++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -157,6 +157,8 @@
 
   MOCK_METHOD(void, OnPrintPreviewLoaded, (), (override));
 
+  MOCK_METHOD(void, NotifyUnsupportedFeature, (), (override));
+
   MOCK_METHOD(void, UserMetricsRecordAction, (const std::string&), (override));
 
   const base::Value& sent_message() const { return sent_message_; }
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc
index 450b1e05..4b099a0f 100644
--- a/pdf/pdf_view_web_plugin.cc
+++ b/pdf/pdf_view_web_plugin.cc
@@ -480,9 +480,6 @@
   return nullptr;
 }
 
-void PdfViewWebPlugin::DocumentHasUnsupportedFeature(
-    const std::string& feature) {}
-
 bool PdfViewWebPlugin::IsPrintPreview() {
   return false;
 }
@@ -658,6 +655,11 @@
   NOTIMPLEMENTED();
 }
 
+void PdfViewWebPlugin::NotifyUnsupportedFeature() {
+  DCHECK(full_frame());
+  GetPdfService()->HasUnsupportedFeature();
+}
+
 void PdfViewWebPlugin::UserMetricsRecordAction(const std::string& action) {
   base::RecordAction(base::UserMetricsAction(action.c_str()));
 }
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h
index c8e2c1cf..05e551c 100644
--- a/pdf/pdf_view_web_plugin.h
+++ b/pdf/pdf_view_web_plugin.h
@@ -148,7 +148,6 @@
                                                const char16_t* term,
                                                bool case_sensitive) override;
   pp::Instance* GetPluginInstance() override;
-  void DocumentHasUnsupportedFeature(const std::string& feature) override;
   bool IsPrintPreview() override;
   void SelectionChanged(const gfx::Rect& left, const gfx::Rect& right) override;
   void SetSelectedText(const std::string& selected_text) override;
@@ -205,6 +204,7 @@
   void DidStartLoading() override;
   void DidStopLoading() override;
   void OnPrintPreviewLoaded() override;
+  void NotifyUnsupportedFeature() override;
   void UserMetricsRecordAction(const std::string& action) override;
 
  private:
diff --git a/remoting/host/backoff_timer.cc b/remoting/host/backoff_timer.cc
index ce3f7382..4d855d5 100644
--- a/remoting/host/backoff_timer.cc
+++ b/remoting/host/backoff_timer.cc
@@ -3,14 +3,15 @@
 // found in the LICENSE file.
 
 #include "remoting/host/backoff_timer.h"
-#include "base/bind.h"
 
 #include <memory>
 #include <utility>
 
+#include "base/bind.h"
+
 namespace remoting {
 
-BackoffTimer::BackoffTimer() : timer_(new base::OneShotTimer()) {}
+BackoffTimer::BackoffTimer() = default;
 
 BackoffTimer::~BackoffTimer() = default;
 
@@ -30,17 +31,13 @@
 }
 
 void BackoffTimer::Stop() {
-  timer_->Stop();
+  timer_.Stop();
   user_task_.Reset();
   backoff_entry_.reset();
 }
 
-void BackoffTimer::SetTimerForTest(std::unique_ptr<base::OneShotTimer> timer) {
-  timer_ = std::move(timer);
-}
-
 void BackoffTimer::StartTimer() {
-  timer_->Start(
+  timer_.Start(
       posted_from_, backoff_entry_->GetTimeUntilRelease(),
       base::BindOnce(&BackoffTimer::OnTimerFired, base::Unretained(this)));
 }
diff --git a/remoting/host/backoff_timer.h b/remoting/host/backoff_timer.h
index 9fab9a3..672cfc1 100644
--- a/remoting/host/backoff_timer.h
+++ b/remoting/host/backoff_timer.h
@@ -34,13 +34,11 @@
   // Returns true if the user task may be invoked in the future.
   bool IsRunning() const { return !!backoff_entry_; }
 
-  void SetTimerForTest(std::unique_ptr<base::OneShotTimer> timer);
-
  private:
   void StartTimer();
   void OnTimerFired();
 
-  std::unique_ptr<base::OneShotTimer> timer_;
+  base::OneShotTimer timer_;
   base::RepeatingClosure user_task_;
   base::Location posted_from_;
   net::BackoffEntry::Policy backoff_policy_ = {};
diff --git a/remoting/host/backoff_timer_unittest.cc b/remoting/host/backoff_timer_unittest.cc
index 05b1d3e..d62361b 100644
--- a/remoting/host/backoff_timer_unittest.cc
+++ b/remoting/host/backoff_timer_unittest.cc
@@ -5,58 +5,77 @@
 #include "remoting/host/backoff_timer.h"
 
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/timer/mock_timer.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace remoting {
 
-namespace {
+class BackoffTimerTest : public testing::Test {
+ public:
+  BackoffTimerTest()
+      : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+  ~BackoffTimerTest() override = default;
 
-void IncrementCounter(int* counter) {
-  ++(*counter);
-}
+  void IncrementCounter() { ++counter_; }
 
-}  // namespace
+  void AssertNextDelayAndFastForwardBy(base::TimeDelta delay) {
+    ASSERT_EQ(task_environment_.NextMainThreadPendingTaskDelay(), delay);
+    task_environment_.FastForwardBy(delay);
+  }
 
-TEST(BackoffTimer, Basic) {
-  base::MockOneShotTimer* mock_timer = new base::MockOneShotTimer();
+  int counter() const { return counter_; }
+
+ private:
+  base::test::TaskEnvironment task_environment_;
+
+  int counter_ = 0;
+};
+
+TEST_F(BackoffTimerTest, Basic) {
   BackoffTimer backoff_timer;
-  backoff_timer.SetTimerForTest(base::WrapUnique(mock_timer));
   ASSERT_FALSE(backoff_timer.IsRunning());
 
-  int counter = 0;
-  backoff_timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
-                      base::TimeDelta::FromMilliseconds(50),
-                      base::BindRepeating(&IncrementCounter, &counter));
-  ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(0, counter);
-  ASSERT_NEAR(0, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  constexpr base::TimeDelta initial_delay =
+      base::TimeDelta::FromMilliseconds(10);
+  constexpr base::TimeDelta max_delay = base::TimeDelta::FromMilliseconds(50);
 
-  mock_timer->Fire();
+  backoff_timer.Start(FROM_HERE, initial_delay, max_delay,
+                      base::BindRepeating(&BackoffTimerTest::IncrementCounter,
+                                          base::Unretained(this)));
   ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(1, counter);
-  EXPECT_NEAR(10, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  ASSERT_EQ(0, counter());
 
-  mock_timer->Fire();
+  // The backoff timer always immediately fires without delay.
+  AssertNextDelayAndFastForwardBy(base::TimeDelta());
   ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(2, counter);
-  EXPECT_NEAR(20, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  ASSERT_EQ(1, counter());
 
-  mock_timer->Fire();
+  // The next delay is equal to the initial delay.
+  AssertNextDelayAndFastForwardBy(initial_delay);
   ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(3, counter);
-  EXPECT_NEAR(40, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  ASSERT_EQ(2, counter());
 
-  mock_timer->Fire();
+  // The next delay is doubled.
+  AssertNextDelayAndFastForwardBy(2 * initial_delay);
   ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(4, counter);
-  EXPECT_NEAR(50, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  ASSERT_EQ(3, counter());
 
-  mock_timer->Fire();
+  // The next delay is doubled again.
+  AssertNextDelayAndFastForwardBy(4 * initial_delay);
   ASSERT_TRUE(backoff_timer.IsRunning());
-  ASSERT_EQ(5, counter);
-  EXPECT_NEAR(50, mock_timer->GetCurrentDelay().InMillisecondsF(), 1);
+  ASSERT_EQ(4, counter());
+
+  // The next delay is clamped to the max delay. Otherwise, it would exceed it.
+  ASSERT_GT(8 * initial_delay, max_delay);
+  AssertNextDelayAndFastForwardBy(max_delay);
+  ASSERT_TRUE(backoff_timer.IsRunning());
+  ASSERT_EQ(5, counter());
+
+  // The delay remains constant at the max delay.
+  AssertNextDelayAndFastForwardBy(max_delay);
+  ASSERT_TRUE(backoff_timer.IsRunning());
+  ASSERT_EQ(6, counter());
 
   backoff_timer.Stop();
   ASSERT_FALSE(backoff_timer.IsRunning());
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 0b1183e..e62028a 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -3863,25 +3863,6 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04",
-              "pool": "chrome.tests",
-              "ssd": "0"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -5748,25 +5729,6 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04",
-              "pool": "chrome.tests",
-              "ssd": "0"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 77064c32..d0e5812 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -2986,75 +2986,6 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android30.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android30",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_30_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "avd_generic_android30"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android30.textpb",
           "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.media_unittests.filter"
         ],
@@ -5193,7 +5124,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5279,7 +5210,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5451,7 +5382,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -5537,7 +5468,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index dae79b1..a03801a 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -4231,56 +4231,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY48M|LMY48I",
-              "device_os_type": "userdebug",
-              "device_type": "hammerhead",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7893,56 +7843,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 21600,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -11562,55 +11462,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -15196,56 +15047,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -20215,55 +20016,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -26542,55 +26294,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY48M",
-              "device_os_type": "userdebug",
-              "device_type": "hammerhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -29476,56 +29179,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -33629,57 +33282,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests_default"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "media_blink_unittests_default",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests_default"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -39143,75 +38745,6 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android23",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_23_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "avd_generic_android23"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android23.textpb",
           "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_m.media_unittests.filter"
         ],
@@ -43076,55 +42609,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "NJH47F",
-              "device_os_type": "userdebug",
-              "device_type": "sailfish",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -46868,57 +46352,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -52543,75 +51976,6 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "device_os": null,
-              "device_type": null,
-              "machine_type": "n1-standard-4",
-              "os": "Ubuntu-16.04|Ubuntu-18.04",
-              "pool": "chromium.tests.avd"
-            }
-          ],
-          "named_caches": [
-            {
-              "name": "avd_generic_android28",
-              "path": ".android"
-            },
-            {
-              "name": "system_images_android_28_google_apis_x86",
-              "path": ".emulator_sdk"
-            }
-          ],
-          "optional_dimensions": {
-            "60": [
-              {
-                "caches": "avd_generic_android28"
-              }
-            ]
-          },
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices",
           "--avd-config=../../tools/android/avd/proto/generic_android28.textpb",
           "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_p.media_unittests.filter"
         ],
@@ -54888,7 +54252,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -54975,7 +54339,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55149,7 +54513,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55236,7 +54600,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55482,7 +54846,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55568,7 +54932,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55740,7 +55104,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -55826,7 +55190,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56072,7 +55436,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56158,7 +55522,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56330,7 +55694,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M91",
-              "revision": "version:91.0.4472.111"
+              "revision": "version:91.0.4472.113"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -56416,7 +55780,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M92",
-              "revision": "version:92.0.4515.59"
+              "revision": "version:92.0.4515.60"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 5f010725..54cc986e 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -2389,23 +2389,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -4110,24 +4093,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -5969,23 +5934,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index abee6a9..f7b89dcd 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -917,23 +917,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -2697,24 +2680,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -4462,24 +4427,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -7284,55 +7231,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY48M",
-              "device_os_type": "userdebug",
-              "device_type": "hammerhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -9527,27 +9425,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -11123,28 +11000,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -12061,28 +11916,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -12556,23 +12389,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -13799,29 +13615,6 @@
       },
       {
         "args": [
-          "--enable-features=ProcessHostOnUI",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "merge": {
@@ -14358,26 +14151,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -15654,28 +15427,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16149,23 +15900,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -17281,28 +17015,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -17776,23 +17488,6 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -18912,28 +18607,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -19390,23 +19063,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -20541,28 +20197,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -21036,23 +20670,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -22657,24 +22274,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -24679,27 +24278,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -26249,24 +25827,6 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -27922,18 +27482,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -29216,18 +28764,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -30478,18 +30014,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -32068,23 +31592,6 @@
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64"
-            }
-          ],
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -33926,24 +33433,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -35828,24 +35317,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -37384,18 +36855,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -38663,18 +38122,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -39942,18 +39389,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -41236,18 +40671,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -44531,23 +43954,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 507beeb8..42098eb4 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -1292,17 +1292,6 @@
         "swarming": {
           "can_use_on_swarming_builders": false
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -3971,56 +3960,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -7384,56 +7323,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -11100,57 +10989,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests_default"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "media_blink_unittests_default",
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests_default"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -15223,57 +15061,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "PQ3A.190801.002",
-              "device_os_flavor": "google",
-              "device_os_type": "userdebug",
-              "device_type": "walleye",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -18058,26 +17845,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--ram-size-mb=16384",
-          "--code-coverage",
-          "--code-coverage-dir=${ISOLATED_OUTDIR}",
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
           "shards": 3
         },
         "test": "media_unittests",
@@ -19226,28 +18993,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -20486,29 +20231,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--device=aemu",
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -22153,28 +21875,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-20.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -23315,27 +23015,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -44239,8 +43918,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44289,8 +43968,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44339,8 +44018,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44389,8 +44068,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44439,8 +44118,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44489,8 +44168,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44539,8 +44218,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44589,8 +44268,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44639,8 +44318,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44689,8 +44368,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44739,8 +44418,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44789,8 +44468,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44839,8 +44518,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44889,8 +44568,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44939,8 +44618,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -44989,8 +44668,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45039,8 +44718,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45089,8 +44768,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45139,8 +44818,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45189,8 +44868,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45239,8 +44918,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45289,8 +44968,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45339,8 +45018,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45389,8 +45068,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45439,8 +45118,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45489,8 +45168,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45539,8 +45218,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45589,8 +45268,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45639,8 +45318,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45689,8 +45368,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45739,8 +45418,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45789,8 +45468,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45839,8 +45518,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45889,8 +45568,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45940,8 +45619,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -45991,8 +45670,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46042,8 +45721,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46093,8 +45772,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46144,8 +45823,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46195,8 +45874,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46246,8 +45925,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46298,8 +45977,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46350,8 +46029,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46402,8 +46081,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46454,8 +46133,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46506,8 +46185,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46558,8 +46237,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46610,8 +46289,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46662,8 +46341,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46714,8 +46393,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46766,8 +46445,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46818,8 +46497,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46870,8 +46549,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46921,8 +46600,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -46972,8 +46651,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47023,8 +46702,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47074,8 +46753,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47125,8 +46804,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47176,8 +46855,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47227,8 +46906,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47278,8 +46957,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47329,8 +47008,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47380,8 +47059,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47431,8 +47110,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47482,8 +47161,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47534,8 +47213,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47586,8 +47265,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47638,8 +47317,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47690,8 +47369,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47742,8 +47421,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47793,8 +47472,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47843,8 +47522,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47893,8 +47572,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47943,8 +47622,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -47993,8 +47672,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48043,8 +47722,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48093,8 +47772,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48143,8 +47822,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48194,8 +47873,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48245,8 +47924,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48296,8 +47975,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48347,8 +48026,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48398,8 +48077,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48449,8 +48128,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48499,8 +48178,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48549,8 +48228,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48599,8 +48278,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48649,8 +48328,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48699,8 +48378,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48749,8 +48428,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48800,8 +48479,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48851,8 +48530,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48902,8 +48581,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -48953,8 +48632,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49004,8 +48683,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49055,8 +48734,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49105,8 +48784,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49155,8 +48834,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49205,8 +48884,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49255,8 +48934,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49305,8 +48984,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49355,8 +49034,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49405,8 +49084,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49455,8 +49134,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49505,8 +49184,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49555,8 +49234,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49606,8 +49285,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49657,8 +49336,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49708,8 +49387,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49759,8 +49438,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49810,8 +49489,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49861,8 +49540,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49911,8 +49590,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -49961,8 +49640,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50011,8 +49690,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50061,8 +49740,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50111,8 +49790,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50161,8 +49840,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50211,8 +49890,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50261,8 +49940,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50311,8 +49990,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50361,8 +50040,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50411,8 +50090,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50461,8 +50140,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50511,8 +50190,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50561,8 +50240,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50611,8 +50290,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50661,8 +50340,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50711,8 +50390,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50761,8 +50440,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50811,8 +50490,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50861,8 +50540,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50911,8 +50590,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -50961,8 +50640,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51011,8 +50690,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51061,8 +50740,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51111,8 +50790,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51161,8 +50840,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51211,8 +50890,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51261,8 +50940,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51311,8 +50990,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51361,8 +51040,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51411,8 +51090,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51461,8 +51140,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51511,8 +51190,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51561,8 +51240,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51611,8 +51290,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51661,8 +51340,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51711,8 +51390,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51761,8 +51440,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51811,8 +51490,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51861,8 +51540,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51911,8 +51590,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -51961,8 +51640,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52011,8 +51690,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52061,8 +51740,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52111,8 +51790,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52161,8 +51840,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52211,8 +51890,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -52261,8 +51940,8 @@
           ],
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
+              "cpu": "arm64",
+              "os": "Mac-11"
             }
           ],
           "named_caches": [
@@ -69211,29 +68890,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -69735,24 +69391,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -70982,23 +70620,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -71879,26 +71500,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--enable-features=BlinkHeapConcurrentMarking"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -72703,23 +72304,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -73597,23 +73181,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -74890,24 +74457,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -76144,28 +75693,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -76639,23 +76166,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -78163,29 +77673,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -78687,24 +78174,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -80590,19 +80059,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -81964,24 +81420,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04",
-              "ssd": "0"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -83651,25 +83089,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "os": "Mac-11",
-              "pool": "chromium.tests.mac-arm64"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -85513,25 +84932,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.13.6"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -87122,26 +86522,6 @@
           "expiration": 21600,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "gpu": "8086:0a2e",
-              "os": "Mac-11.3"
-            }
-          ],
-          "expiration": 21600,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -88726,24 +88106,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -89710,24 +89072,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -91371,24 +90715,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -93225,24 +92551,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -94871,19 +94179,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index a83a411..a031536 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -628,23 +628,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -1601,23 +1584,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -2650,28 +2616,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "arm64",
-              "inside_docker": "1",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -3861,27 +3805,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--runner-logs-dir=${ISOLATED_OUTDIR}/runner_logs"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "kvm": "1",
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -6793,30 +6716,6 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "media_blink_unittests_wayland",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--no-xvfb",
-          "--use-weston",
-          "--ozone-platform=wayland",
-          "--enable-features=UseOzonePlatform"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
         "name": "media_unittests_wayland",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8907,28 +8806,6 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "media_blink_unittests_x11",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--ozone-platform=x11",
-          "--enable-features=UseOzonePlatform"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
         "name": "media_unittests_x11",
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10287,29 +10164,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -10811,24 +10665,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -12339,28 +12175,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -12834,23 +12648,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -14363,28 +14160,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -14858,23 +14633,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -16406,28 +16164,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -16901,23 +16637,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-14.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -18431,28 +18150,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18926,23 +18623,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 73646046..eeeb87e 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -923,24 +923,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.11"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -2653,25 +2635,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "gpu": "8086:0a2e",
-              "os": "Mac-10.12.6"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -4450,24 +4413,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.13.6"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -6214,24 +6159,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.14.6"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -8031,25 +7958,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -9838,24 +9746,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -11540,24 +11430,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-11|Mac-10.16"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index a29a496..87f4376 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -1097,26 +1097,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -2930,23 +2910,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -4703,26 +4666,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -6699,27 +6642,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -8667,27 +8589,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-16.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -10599,26 +10500,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -12475,26 +12356,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -14301,27 +14162,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Mac-10.15"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -17010,55 +16850,6 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
-            "media_blink_unittests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "resultdb": {
-          "enable": true
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MMB29Q",
-              "device_os_type": "userdebug",
-              "device_type": "bullhead",
-              "os": "Android"
-            }
-          ],
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "args": [
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -18522,28 +18313,6 @@
         "test_id_prefix": "ninja://content/test:content_browsertests/"
       },
       {
-        "args": [
-          "--enable-features=ProcessHostOnUI"
-        ],
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "name": "process_host_on_ui_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 10
-        },
-        "test": "content_browsertests",
-        "test_id_prefix": "ninja://content/test:content_browsertests/"
-      },
-      {
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -19017,23 +18786,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -20734,23 +20486,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-15063"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 26cbcc1..b53fb1f1 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -755,18 +755,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -2744,25 +2732,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "isolate_profile_data": true,
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -4996,24 +4965,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -6822,18 +6773,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
@@ -8337,18 +8276,6 @@
           "can_use_on_swarming_builders": true,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "media_unittests",
         "test_id_prefix": "ninja://media:media_unittests/"
       },
diff --git a/testing/buildbot/client.v8.chromium.json b/testing/buildbot/client.v8.chromium.json
index 912ec5b5..15f410c 100644
--- a/testing/buildbot/client.v8.chromium.json
+++ b/testing/buildbot/client.v8.chromium.json
@@ -361,23 +361,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "nacl_loader_unittests",
         "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/"
       },
@@ -963,23 +946,6 @@
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test": "media_blink_unittests",
-        "test_id_prefix": "ninja://media/blink:media_blink_unittests/"
-      },
-      {
-        "merge": {
-          "args": [],
-          "script": "//testing/merge_scripts/standard_gtest_merge.py"
-        },
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-18.04"
-            }
-          ],
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
-        },
         "test": "nacl_loader_unittests",
         "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/"
       },
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json
index 5ad6ae8c..5fc9da353 100644
--- a/testing/buildbot/client.v8.fyi.json
+++ b/testing/buildbot/client.v8.fyi.json
@@ -1828,7 +1828,6 @@
       "ipc_tests",
       "jingle_unittests",
       "media_unittests",
-      "media_blink_unittests",
       "mojo_unittests",
       "nacl_loader_unittests",
       "net_unittests",
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index f8fd08a..ef6290c 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1182,10 +1182,6 @@
     "label": "//media/base/android:media_base_junit_tests",
     "type": "junit_test",
   },
-  "media_blink_unittests": {
-    "label": "//media/blink:media_blink_unittests",
-    "type": "windowed_test_launcher",
-  },
   "media_perftests": {
     "args": [
       "media_perftests",
diff --git a/testing/buildbot/infra.json b/testing/buildbot/infra.json
index 3fbba302..7e6c2aa8b 100644
--- a/testing/buildbot/infra.json
+++ b/testing/buildbot/infra.json
@@ -10,5 +10,15 @@
     "additional_compile_targets": [
       "chrome"
     ]
+  },
+  "linux-local-ssd-nvme-rel": {
+    "additional_compile_targets": [
+      "chrome"
+    ]
+  },
+  "linux-local-ssd-scsi-rel": {
+    "additional_compile_targets": [
+      "chrome"
+    ]
   }
 }
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 62b1506d6..066ea49 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -667,6 +667,14 @@
       },
     },
   },
+  'mac_11_arm64': {
+    'swarming': {
+      'dimensions': {
+        'cpu': 'arm64',
+        'os': 'Mac-11',
+      },
+    },
+  },
   'mac_11_beta_x64': {
     'swarming': {
       'dimensions': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 0ac249b..6f9a842e 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1919,15 +1919,6 @@
       },
     },
   },
-  'media_blink_unittests': {
-    'modifications': {
-      'fuchsia-code-coverage': {
-        'swarming': {
-          'shards': 2,
-        },
-      },
-    },
-  },
   'media_unittests': {
     'modifications': {
       'android-11-x86-fyi-rel': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 6096927..01a23b0 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -793,7 +793,6 @@
       'latency_unittests': {},
       'libjingle_xmpp_unittests': {},
       'liburlpattern_unittests': {},
-      'media_blink_unittests': {},
       'media_unittests': {},
       'midi_unittests': {},
       'mojo_unittests': {},
@@ -1137,7 +1136,6 @@
       'headless_unittests': {},
       'interactive_ui_tests': {},
       'jingle_unittests': {},
-      'media_blink_unittests': {},
       'nacl_loader_unittests': {},
       'net_unittests': {},
       'pdf_unittests': {},
@@ -1524,9 +1522,6 @@
       'latency_unittests': {
         'mixins': ['fuchsia_runner_logs'],
       },
-      'media_blink_unittests': {
-        'mixins': ['fuchsia_runner_logs'],
-      },
       'media_unittests': {
         'mixins': ['fuchsia_runner_logs'],
       },
@@ -4572,7 +4567,6 @@
       'latency_unittests': {},
       'libjingle_xmpp_unittests': {},
       'liburlpattern_unittests': {},
-      'media_blink_unittests': {},
       'media_unittests': {},
       'midi_unittests': {},
       'mojo_unittests': {},
@@ -4639,18 +4633,6 @@
       },
     },
 
-    'process_host_on_ui_gtests': {
-      'process_host_on_ui_content_browsertests': {
-        'args': [
-          '--enable-features=ProcessHostOnUI',
-        ],
-        'swarming': {
-          'shards': 10,
-        },
-        'test': 'content_browsertests',
-      },
-    },
-
     # TODO(dpranke): These are run on the p/chromium waterfall; they should
     # probably be run on other builders, and we should get rid of the p/chromium
     # waterfall.
@@ -5780,7 +5762,6 @@
       'linux_specific_xr_gtests',
       'non_android_and_cast_and_chromeos_chromium_gtests',
       'non_android_chromium_gtests',
-      'process_host_on_ui_gtests',
       'vr_platform_specific_chromium_gtests',
       'weblayer_gtests',
     ],
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index d4a2f2a9b..897c748 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -436,7 +436,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.59',
+          'revision': 'version:92.0.4515.60',
         }
       ],
     },
@@ -460,7 +460,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.111',
+          'revision': 'version:91.0.4472.113',
         }
       ],
     },
@@ -508,7 +508,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.59',
+          'revision': 'version:92.0.4515.60',
         }
       ],
     },
@@ -532,7 +532,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.111',
+          'revision': 'version:91.0.4472.113',
         }
       ],
     },
@@ -580,7 +580,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M92',
-          'revision': 'version:92.0.4515.59',
+          'revision': 'version:92.0.4515.60',
         }
       ],
     },
@@ -604,7 +604,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M91',
-          'revision': 'version:91.0.4472.111',
+          'revision': 'version:91.0.4472.113',
         }
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 3b1d881..bf78afe 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2919,7 +2919,7 @@
         ],
         'mixins': [
           'enable_resultdb',
-          'mac_11_x64',
+          'mac_11_arm64',
           'mac_toolchain',
           'out_dir_arg',
           'xcode_12e262',
@@ -6220,7 +6220,6 @@
           'ipc_tests',
           'jingle_unittests',
           'media_unittests',
-          'media_blink_unittests',
           'mojo_unittests',
           'nacl_loader_unittests',
           'net_unittests',
@@ -6269,6 +6268,16 @@
           'chrome',
         ],
       },
+      'linux-local-ssd-nvme-rel': {
+        'additional_compile_targets': [
+          'chrome',
+        ],
+      },
+      'linux-local-ssd-scsi-rel': {
+        'additional_compile_targets': [
+          'chrome',
+        ],
+      },
     }
   },
   {
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index ba0b377..7691e1e 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -601,7 +601,7 @@
   // Whether zoom for dsf is enabled. When true, inputs to blink would all be
   // scaled by the device scale factor so that layout is done in device pixel
   // space.
-  virtual bool IsUseZoomForDSFEnabled() { return false; }
+  virtual bool IsUseZoomForDSFEnabled() { return true; }
 
   // Whether LCD text is enabled.
   virtual bool IsLcdTextEnabled() { return false; }
diff --git a/third_party/blink/public/platform/web_code_cache_loader.h b/third_party/blink/public/platform/web_code_cache_loader.h
index 67e0ea1..daf84d36 100644
--- a/third_party/blink/public/platform/web_code_cache_loader.h
+++ b/third_party/blink/public/platform/web_code_cache_loader.h
@@ -24,19 +24,8 @@
       base::OnceCallback<void(base::Time, mojo_base::BigBuffer)>;
   virtual ~WebCodeCacheLoader() = default;
 
-  static std::unique_ptr<WebCodeCacheLoader> CreateForFrame(
+  static std::unique_ptr<WebCodeCacheLoader> Create(
       blink::mojom::CodeCacheHost* code_cache_host);
-  static std::unique_ptr<WebCodeCacheLoader> CreateForWorker(
-      blink::mojom::CodeCacheHost* code_cache_host,
-      base::WaitableEvent* terminate_sync_load_event);
-
-  // Fetched code cache corresponding to |url| synchronously and returns
-  // response in |response_time_out| and |data_out|. |response_time_out| and
-  // |data_out| cannot be nullptrs.
-  virtual void FetchFromCodeCacheSynchronously(
-      const WebURL& url,
-      base::Time* response_time_out,
-      mojo_base::BigBuffer* data_out) = 0;
   virtual void FetchFromCodeCache(blink::mojom::CodeCacheType cache_type,
                                   const WebURL& url,
                                   FetchCodeCacheCallback) = 0;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 4e49698..1850d0e 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -131,7 +131,10 @@
       break;
     case EContentVisibility::kHidden:
       UseCounter::Count(document_, WebFeature::kContentVisibilityHidden);
-      RequestLock(0u);
+      RequestLock(
+          for_details_element_
+              ? static_cast<uint16_t>(DisplayLockActivationReason::kFindInPage)
+              : 0u);
       break;
     case EContentVisibility::kHiddenMatchable:
       UseCounter::Count(document_,
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index f665a7a..31ee6b69 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -219,6 +219,10 @@
   // We unlock auto locks for printing, which is set here.
   void SetShouldUnlockAutoForPrint(bool);
 
+  void SetForDetailsElement(bool for_details_element) {
+    for_details_element_ = for_details_element;
+  }
+
  private:
   // Give access to |NotifyForcedUpdateScopeStarted()| and
   // |NotifyForcedUpdateScopeEnded()|.
@@ -430,6 +434,10 @@
   bool set_requested_state_scope_ = false;
 
   absl::optional<ScrollOffset> stashed_scroll_offset_;
+
+  // When we use content-visibility:hidden for a <details> element, it should be
+  // activatable by find-in-page, element fragments, and text fragments.
+  bool for_details_element_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/element_inner_text.cc b/third_party/blink/renderer/core/editing/element_inner_text.cc
index a067358..8dd6ef42 100644
--- a/third_party/blink/renderer/core/editing/element_inner_text.cc
+++ b/third_party/blink/renderer/core/editing/element_inner_text.cc
@@ -268,11 +268,8 @@
 
   // 2. If the node is display locked, then we should not process it or its
   // children, since they are not visible or accessible via innerText.
-  if (auto* element = DynamicTo<Element>(node)) {
-    auto* context = element->GetDisplayLockContext();
-    if (context && context->IsLocked())
-      return;
-  }
+  if (DisplayLockUtilities::NearestLockedInclusiveAncestor(node))
+    return;
 
   // 3. If node's computed value of 'visibility' is not 'visible', then return
   // items.
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc
index 13dd10f..cb8e8e22 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder.cc
+++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -58,6 +58,7 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/html/html_details_element.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -105,6 +106,43 @@
         &first_node, DocumentUpdateReason::kFindInPage);
   }
 
+  // If the active match is hidden inside a <details> element, then we should
+  // expand it so find-in-page can scroll to it.
+  if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+    bool details_opened = false;
+
+    for (Node& parent : FlatTreeTraversal::AncestorsOf(first_node)) {
+      if (HTMLDetailsElement* details = DynamicTo<HTMLDetailsElement>(parent)) {
+        // If the active match is inside the <summary> of a <details>, then we
+        // shouldn't expand the <details> because the active match is already
+        // visible.
+        bool inside_summary = false;
+        Element& summary = *details->FindMainSummary();
+        for (Node& ancestor : FlatTreeTraversal::AncestorsOf(first_node)) {
+          if (&ancestor == &summary) {
+            inside_summary = true;
+            break;
+          }
+        }
+
+        if (!inside_summary &&
+            !details->FastHasAttribute(html_names::kOpenAttr)) {
+          details->setAttribute(html_names::kOpenAttr, g_empty_atom);
+          details_opened = true;
+        }
+      }
+    }
+
+    if (details_opened) {
+      // If we opened any details elements, we need to update style and layout
+      // to account for the new content to render inside the now-expanded
+      // details element before we scroll to it. The added open attribute may
+      // also affect style.
+      first_node.GetDocument().UpdateStyleAndLayoutForNode(
+          &first_node, DocumentUpdateReason::kFindInPage);
+    }
+  }
+
   // We don't always have a LayoutObject for the node we're trying to scroll to
   // after the async step: crbug.com/1129341
   if (!first_node.GetLayoutObject())
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index d578250..016d1e3 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -1497,9 +1497,19 @@
       ->SetDeviceScaleFactorForTesting(2.f);
   web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
 
-  EXPECT_EQ(
-      2,
-      web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+    EXPECT_EQ(
+        1,
+        web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+    auto* frame =
+        To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+    DCHECK(frame);
+    EXPECT_EQ(2, frame->DevicePixelRatio());
+  } else {
+    EXPECT_EQ(
+        2,
+        web_view_helper.GetWebView()->GetPage()->DeviceScaleFactorDeprecated());
+  }
 
   // Device scale factor should be independent of page scale.
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(1, 2);
@@ -2627,6 +2637,7 @@
     web_view_helper.InitializeAndLoad(
         base_url_ + "viewport-target-densitydpi-device.html", nullptr, nullptr,
         ConfigureAndroid);
+    web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
     web_view_helper.GetWebView()
         ->MainFrameWidget()
         ->SetDeviceScaleFactorForTesting(device_scale_factors[i]);
@@ -2635,7 +2646,6 @@
     web_view_helper.GetWebView()
         ->GetSettings()
         ->SetSupportDeprecatedTargetDensityDPI(true);
-    web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
 
     EXPECT_NEAR(viewport_width * device_scale_factors[i],
                 web_view_helper.GetWebView()
@@ -2651,8 +2661,16 @@
                     ->GetLayoutSize()
                     .Height(),
                 1.0f);
-    EXPECT_NEAR(1.0f / device_scale_factors[i],
-                web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+    if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+      EXPECT_NEAR(1.0f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+      auto* frame =
+          To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+      DCHECK(frame);
+      EXPECT_EQ(device_scale_factors[i], frame->DevicePixelRatio());
+    } else {
+      EXPECT_NEAR(1.0f / device_scale_factors[i],
+                  web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+    }
   }
 }
 
@@ -2710,6 +2728,7 @@
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, nullptr,
       ConfigureAndroid);
+  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
   web_view_helper.GetWebView()
       ->MainFrameWidget()
       ->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2719,7 +2738,6 @@
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
-  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
 
   EXPECT_NEAR(viewport_width * device_scale_factor,
               web_view_helper.GetWebView()
@@ -2735,8 +2753,16 @@
                   ->GetLayoutSize()
                   .Height(),
               1.0f);
-  EXPECT_NEAR(1.0f / device_scale_factor,
-              web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+    EXPECT_NEAR(0.25f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+    auto* frame =
+        To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+    DCHECK(frame);
+    EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+  } else {
+    EXPECT_NEAR(1.0f / device_scale_factor,
+                web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+  }
 }
 
 TEST_F(WebFrameTest, NoWideViewportAndScaleLessThanOneWithDeviceWidth) {
@@ -2751,6 +2777,7 @@
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-less-than-1-device-width.html",
       nullptr, nullptr, ConfigureAndroid);
+  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
   web_view_helper.GetWebView()
       ->MainFrameWidget()
       ->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2760,8 +2787,8 @@
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
-  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
 
+  // We use 4.0f in EXPECT_NEAR to account for a rounding error.
   const float kPageZoom = 0.25f;
   EXPECT_NEAR(viewport_width * device_scale_factor / kPageZoom,
               web_view_helper.GetWebView()
@@ -2769,16 +2796,25 @@
                   ->GetFrameView()
                   ->GetLayoutSize()
                   .Width(),
-              1.0f);
+              4.0f);
   EXPECT_NEAR(viewport_height * device_scale_factor / kPageZoom,
               web_view_helper.GetWebView()
                   ->MainFrameImpl()
                   ->GetFrameView()
                   ->GetLayoutSize()
                   .Height(),
-              1.0f);
-  EXPECT_NEAR(1.0f / device_scale_factor,
-              web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+              4.0f);
+  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+    EXPECT_NEAR(kPageZoom, web_view_helper.GetWebView()->PageScaleFactor(),
+                0.01f);
+    auto* frame =
+        To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+    DCHECK(frame);
+    EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+  } else {
+    EXPECT_NEAR(1.0f / device_scale_factor,
+                web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+  }
 }
 
 TEST_F(WebFrameTest, NoWideViewportAndNoViewportWithInitialPageScaleOverride) {
@@ -2861,6 +2897,7 @@
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
       nullptr, ConfigureAndroid);
+  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
   web_view_helper.GetWebView()
       ->MainFrameWidget()
       ->SetDeviceScaleFactorForTesting(device_scale_factor);
@@ -2873,7 +2910,6 @@
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
-  web_view_helper.Resize(gfx::Size(viewport_width, viewport_height));
 
   EXPECT_NEAR(viewport_width * device_scale_factor,
               web_view_helper.GetWebView()
@@ -2889,8 +2925,16 @@
                   ->GetLayoutSize()
                   .Height(),
               1.0f);
-  EXPECT_NEAR(1.0f / device_scale_factor,
-              web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+  if (Platform::Current()->IsUseZoomForDSFEnabled()) {
+    EXPECT_NEAR(2.0f, web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+    auto* frame =
+        To<LocalFrame>(web_view_helper.GetWebView()->GetPage()->MainFrame());
+    DCHECK(frame);
+    EXPECT_EQ(device_scale_factor, frame->DevicePixelRatio());
+  } else {
+    EXPECT_NEAR(1.0f / device_scale_factor,
+                web_view_helper.GetWebView()->PageScaleFactor(), 0.01f);
+  }
 }
 
 TEST_F(WebFrameTest, NoUserScalableQuirkIgnoresViewportScaleForWideViewport) {
diff --git a/third_party/blink/renderer/core/html/html_details_element.cc b/third_party/blink/renderer/core/html/html_details_element.cc
index 011742c0..1b8de6b 100644
--- a/third_party/blink/renderer/core/html/html_details_element.cc
+++ b/third_party/blink/renderer/core/html/html_details_element.cc
@@ -92,8 +92,16 @@
   HTMLSlotElement* content_slot =
       HTMLSlotElement::CreateUserAgentDefaultSlot(GetDocument());
   content_slot->SetIdAttribute(shadow_element_names::kIdDetailsContent);
-  content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
-                                       CSSValueID::kNone);
+  if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+    content_slot->SetInlineStyleProperty(CSSPropertyID::kContentVisibility,
+                                         CSSValueID::kHidden);
+    content_slot->EnsureDisplayLockContext().SetForDetailsElement(true);
+    content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+                                         CSSValueID::kBlock);
+  } else {
+    content_slot->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+                                         CSSValueID::kNone);
+  }
   root.AppendChild(content_slot);
 
   auto* default_summary_style = MakeGarbageCollected<HTMLStyleElement>(
@@ -143,11 +151,25 @@
     Element* content = EnsureUserAgentShadowRoot().getElementById(
         shadow_element_names::kIdDetailsContent);
     DCHECK(content);
-    if (is_open_) {
-      content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+
+    if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) {
+      if (is_open_) {
+        content->RemoveInlineStyleProperty(CSSPropertyID::kContentVisibility);
+        content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+      } else {
+        content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+                                        CSSValueID::kBlock);
+        content->SetInlineStyleProperty(CSSPropertyID::kContentVisibility,
+                                        CSSValueID::kHidden);
+        content->EnsureDisplayLockContext().SetForDetailsElement(true);
+      }
     } else {
-      content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
-                                      CSSValueID::kNone);
+      if (is_open_) {
+        content->RemoveInlineStyleProperty(CSSPropertyID::kDisplay);
+      } else {
+        content->SetInlineStyleProperty(CSSPropertyID::kDisplay,
+                                        CSSValueID::kNone);
+      }
     }
 
     return;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 4d53dd7..50996bb 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -699,29 +699,46 @@
   // We only calculate the range placement if the line was not defined as 'auto'
   // and it is within the bounds of the grid, since an out of flow item cannot
   // create grid lines.
+  const wtf_size_t range_count = track_collection.RangeCount();
   auto& start_range_index = track_collection.IsForColumns()
                                 ? column_placement.start_range_index
                                 : row_placement.start_range_index;
   if (start_offset != kNotFound) {
-    // If a start line of an out of flow item is the last line of the grid, we
-    // can just subtract one unit to the range count.
-    start_range_index =
-        (start_offset < track_collection.EndLineOfImplicitGrid())
-            ? track_collection.RangeIndexFromTrackNumber(start_offset)
-            : track_collection.RangeCount() - 1;
-    start_offset -= track_collection.RangeTrackNumber(start_range_index);
+    if (!range_count) {
+      // An undefined and empty grid has a single start/end grid line and no
+      // ranges. Therefore, if the start offset isn't 'auto', the only valid
+      // offset is zero.
+      DCHECK_EQ(start_offset, 0u);
+      start_range_index = 0;
+    } else {
+      // If the start line of an out of flow item is the last line of the grid,
+      // we can just subtract one unit to the range count.
+      start_range_index =
+          (start_offset < track_collection.EndLineOfImplicitGrid())
+              ? track_collection.RangeIndexFromTrackNumber(start_offset)
+              : range_count - 1;
+      start_offset -= track_collection.RangeTrackNumber(start_range_index);
+    }
   }
 
   auto& end_range_index = track_collection.IsForColumns()
                               ? column_placement.end_range_index
                               : row_placement.end_range_index;
   if (end_offset != kNotFound) {
-    // If an end line of an out of flow item is the first line of the grid, then
-    // |last_spanned_range| is set to zero.
-    end_range_index =
-        end_offset ? track_collection.RangeIndexFromTrackNumber(end_offset - 1)
-                   : 0;
-    end_offset -= track_collection.RangeTrackNumber(end_range_index);
+    if (!range_count) {
+      // Similarly to the start offset, if we have an undefined, empty grid and
+      // the end offset isn't 'auto', the only valid offset is zero.
+      DCHECK_EQ(end_offset, 0u);
+      end_range_index = 0;
+    } else {
+      // If the end line of an out of flow item is the first line of the grid,
+      // then |last_spanned_range| is set to zero.
+      end_range_index =
+          end_offset
+              ? track_collection.RangeIndexFromTrackNumber(end_offset - 1)
+              : 0;
+      end_offset -= track_collection.RangeTrackNumber(end_range_index);
+    }
   }
 }
 
@@ -3529,8 +3546,6 @@
     const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
     const wtf_size_t range_index,
     const wtf_size_t offset_in_range) {
-  LayoutUnit track_offset;
-
   const wtf_size_t range_starting_set_index =
       track_collection.RangeStartingSetIndex(range_index);
   const wtf_size_t range_track_count =
@@ -3538,6 +3553,7 @@
   const wtf_size_t range_set_count =
       track_collection.RangeSetCount(range_index);
 
+  LayoutUnit track_offset;
   if (offset_in_range == range_track_count) {
     DCHECK(snap_to_end_of_track);
     track_offset =
@@ -3567,6 +3583,14 @@
     const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
     const wtf_size_t range_index,
     const wtf_size_t offset_in_range) {
+  if (!track_collection.RangeCount()) {
+    // If the start line of an out of flow item is not 'auto' in an empty and
+    // undefined grid, start offset is the start border scrollbar padding.
+    DCHECK_EQ(range_index, 0u);
+    DCHECK_EQ(offset_in_range, 0u);
+    return set_geometry.sets[0].offset;
+  }
+
   const wtf_size_t range_track_count =
       track_collection.RangeTrackCount(range_index);
 
@@ -3589,6 +3613,14 @@
     const NGGridLayoutAlgorithm::SetGeometry& set_geometry,
     const wtf_size_t range_index,
     const wtf_size_t offset_in_range) {
+  if (!track_collection.RangeCount()) {
+    // If the end line of an out of flow item is not 'auto' in an empty and
+    // undefined grid, end offset is the start border scrollbar padding.
+    DCHECK_EQ(range_index, 0u);
+    DCHECK_EQ(offset_in_range, 0u);
+    return set_geometry.sets[0].offset;
+  }
+
   if (!offset_in_range && !range_index) {
     // Only allow the offset to be 0 for the first range in the collection,
     // which is the start line of the implicit grid; don't snap to the end.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
index 9c62f69..5f2e292 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -900,6 +900,9 @@
             2);
         break;
     }
+    baseline_shift += ComputeAlignmentBaselineShift(
+        parent_box.font->PrimaryFont()->GetFontMetrics(), baseline_type,
+        style.AlignmentBaseline());
     if (!box->metrics.IsEmpty())
       box->metrics.Move(baseline_shift);
     line_box->MoveInBlockDirection(baseline_shift, box->fragment_start,
@@ -962,6 +965,51 @@
   return kPositionNotPending;
 }
 
+// static
+LayoutUnit NGInlineLayoutStateStack::ComputeAlignmentBaselineShift(
+    const FontMetrics& metrics,
+    FontBaseline baseline_type,
+    EAlignmentBaseline alignment_baseline) {
+  FontBaseline alignment_type = baseline_type;
+  switch (alignment_baseline) {
+    case EAlignmentBaseline::kAuto:
+    case EAlignmentBaseline::kBaseline:
+      break;
+    case EAlignmentBaseline::kBeforeEdge:
+    case EAlignmentBaseline::kTextBeforeEdge:
+      alignment_type = FontBaseline::kTextOverBaseline;
+      break;
+    case EAlignmentBaseline::kMiddle:
+      alignment_type = FontBaseline::kXMiddleBaseline;
+      break;
+    case EAlignmentBaseline::kCentral:
+      alignment_type = FontBaseline::kCentralBaseline;
+      break;
+    case EAlignmentBaseline::kAfterEdge:
+    case EAlignmentBaseline::kTextAfterEdge:
+      alignment_type = FontBaseline::kTextUnderBaseline;
+      break;
+    case EAlignmentBaseline::kIdeographic:
+      alignment_type = FontBaseline::kIdeographicUnderBaseline;
+      break;
+    case EAlignmentBaseline::kAlphabetic:
+      alignment_type = FontBaseline::kAlphabeticBaseline;
+      break;
+    case EAlignmentBaseline::kHanging:
+      alignment_type = FontBaseline::kHangingBaseline;
+      break;
+    case EAlignmentBaseline::kMathematical:
+      alignment_type = FontBaseline::kMathBaseline;
+      break;
+  }
+
+  if (baseline_type == alignment_type)
+    return LayoutUnit(0);
+
+  return metrics.FixedAscent(baseline_type) -
+         metrics.FixedAscent(alignment_type);
+}
+
 FontHeight NGInlineLayoutStateStack::MetricsForTopAndBottomAlign(
     const NGInlineBoxState& box,
     const NGLogicalLineItems& line_box) const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
index c7babe8c..186908f 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -234,6 +234,13 @@
                                      NGLogicalLineItems*,
                                      FontBaseline);
 
+  // Computes the difference between the 'dominant-baseline' and the
+  // 'alignment-baseline'.
+  static LayoutUnit ComputeAlignmentBaselineShift(
+      const FontMetrics& metrics,
+      FontBaseline baseline_type,
+      EAlignmentBaseline alignment_type);
+
   // Compute the metrics for when 'vertical-align' is 'top' and 'bottom' from
   // |pending_descendants|.
   FontHeight MetricsForTopAndBottomAlign(const NGInlineBoxState&,
diff --git a/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc b/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
index ee9a42c..35fc3d7 100644
--- a/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/loader_factory_for_frame.cc
@@ -143,7 +143,7 @@
   if (document_loader_->GetCodeCacheHost() == nullptr) {
     return nullptr;
   }
-  return blink::WebCodeCacheLoader::CreateForFrame(
+  return blink::WebCodeCacheLoader::Create(
       document_loader_->GetCodeCacheHost());
 }
 
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
index 0328a32..4bb9ac94 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
+++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_SCRIPT_LOADER_H_
 
 #include "base/dcheck_is_on.h"
-#include "base/macros.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
@@ -48,6 +47,8 @@
                      const ScriptFetchOptions&,
                      ModuleScriptLoaderRegistry*,
                      ModuleScriptLoaderClient*);
+  ModuleScriptLoader(const ModuleScriptLoader&) = delete;
+  ModuleScriptLoader& operator=(const ModuleScriptLoader&) = delete;
   ~ModuleScriptLoader();
 
   static void Fetch(const ModuleScriptFetchRequest&,
@@ -99,8 +100,6 @@
 #if DCHECK_IS_ON()
   KURL url_;
 #endif
-
-  DISALLOW_COPY_AND_ASSIGN(ModuleScriptLoader);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
index f1d340ca..3943ae5 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc
@@ -115,10 +115,10 @@
 }  // namespace
 
 class ModuleScriptLoaderTest : public PageTestBase {
-  DISALLOW_COPY_AND_ASSIGN(ModuleScriptLoaderTest);
-
  public:
   ModuleScriptLoaderTest();
+  ModuleScriptLoaderTest(const ModuleScriptLoaderTest&) = delete;
+  ModuleScriptLoaderTest& operator=(const ModuleScriptLoaderTest&) = delete;
   void SetUp() override;
 
   void InitializeForDocument();
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
index eafd48a..fff822d4c6 100644
--- a/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
+++ b/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
@@ -178,10 +178,10 @@
 }
 
 class ModuleTreeLinkerTest : public PageTestBase {
-  DISALLOW_COPY_AND_ASSIGN(ModuleTreeLinkerTest);
-
  public:
   ModuleTreeLinkerTest() = default;
+  ModuleTreeLinkerTest(const ModuleTreeLinkerTest&) = delete;
+  ModuleTreeLinkerTest& operator=(const ModuleTreeLinkerTest&) = delete;
   void SetUp() override;
 
   ModuleTreeLinkerTestModulator* GetModulator() { return modulator_.Get(); }
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
index 574a098..f8c48793 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_MESSAGING_PROXY_H_
 
 #include <memory>
-#include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
@@ -34,6 +33,9 @@
     : public ThreadedMessagingProxyBase {
  public:
   DedicatedWorkerMessagingProxy(ExecutionContext*, DedicatedWorker*);
+  DedicatedWorkerMessagingProxy(const DedicatedWorkerMessagingProxy&) = delete;
+  DedicatedWorkerMessagingProxy& operator=(
+      const DedicatedWorkerMessagingProxy&) = delete;
   ~DedicatedWorkerMessagingProxy() override;
 
   // These methods should only be used on the parent context thread.
@@ -105,8 +107,6 @@
   // Passed to DedicatedWorkerThread on worker thread creation.
   mojo::PendingRemote<mojom::blink::DedicatedWorkerHost>
       pending_dedicated_worker_host_;
-
-  DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerMessagingProxy);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
index f8e4eaf..2bafa083 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
@@ -32,7 +32,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_DEDICATED_WORKER_OBJECT_PROXY_H_
 
 #include <memory>
-#include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -59,6 +58,9 @@
   DedicatedWorkerObjectProxy(DedicatedWorkerMessagingProxy*,
                              ParentExecutionContextTaskRunners*,
                              const DedicatedWorkerToken&);
+  DedicatedWorkerObjectProxy(const DedicatedWorkerObjectProxy&) = delete;
+  DedicatedWorkerObjectProxy& operator=(const DedicatedWorkerObjectProxy&) =
+      delete;
   ~DedicatedWorkerObjectProxy() override;
 
   void PostMessageToWorkerObject(BlinkTransferableMessage);
@@ -89,8 +91,6 @@
   // the tasks.
   CrossThreadWeakPersistent<DedicatedWorkerMessagingProxy>
       messaging_proxy_weak_ptr_;
-
-  DISALLOW_COPY_AND_ASSIGN(DedicatedWorkerObjectProxy);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
index 018cacda..478ad29a 100644
--- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h
+++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_GLOBAL_SCOPE_CREATION_PARAMS_H_
 
 #include <memory>
-#include "base/macros.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -72,6 +71,9 @@
           absl::nullopt,
       bool parent_cross_origin_isolated_capability = false,
       bool parent_direct_socket_capability = false);
+  GlobalScopeCreationParams(const GlobalScopeCreationParams&) = delete;
+  GlobalScopeCreationParams& operator=(const GlobalScopeCreationParams&) =
+      delete;
 
   ~GlobalScopeCreationParams() = default;
 
@@ -186,8 +188,6 @@
   //
   // TODO(mkwst): We need a specification for this capability.
   const bool parent_direct_socket_capability;
-
-  DISALLOW_COPY_AND_ASSIGN(GlobalScopeCreationParams);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/installed_scripts_manager.h b/third_party/blink/renderer/core/workers/installed_scripts_manager.h
index 44a5b2b..d3a0e3c1 100644
--- a/third_party/blink/renderer/core/workers/installed_scripts_manager.h
+++ b/third_party/blink/renderer/core/workers/installed_scripts_manager.h
@@ -33,6 +33,8 @@
                String source_text,
                std::unique_ptr<Vector<uint8_t>> meta_data,
                std::unique_ptr<CrossThreadHTTPHeaderMapData>);
+    ScriptData(const ScriptData&) = delete;
+    ScriptData& operator=(const ScriptData&) = delete;
     ScriptData(ScriptData&& other) = default;
     ScriptData& operator=(ScriptData&& other) = default;
 
@@ -56,8 +58,6 @@
     std::unique_ptr<Vector<uint8_t>> meta_data_;
     HTTPHeaderMap headers_;
     network::mojom::IPAddressSpace response_address_space_;
-
-    DISALLOW_COPY_AND_ASSIGN(ScriptData);
   };
 
   // Used on the main or worker thread. Returns true if the script has been
diff --git a/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h b/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
index 97fa92c..7eff879b 100644
--- a/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
+++ b/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_PARENT_EXECUTION_CONTEXT_TASK_RUNNERS_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_PARENT_EXECUTION_CONTEXT_TASK_RUNNERS_H_
 
-#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/thread_annotations.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -37,6 +36,11 @@
   // particular context.
   explicit ParentExecutionContextTaskRunners(ExecutionContext*);
 
+  ParentExecutionContextTaskRunners(const ParentExecutionContextTaskRunners&) =
+      delete;
+  ParentExecutionContextTaskRunners& operator=(
+      const ParentExecutionContextTaskRunners&) = delete;
+
   // Might return nullptr for unsupported task types. This can be called from
   // any threads.
   scoped_refptr<base::SingleThreadTaskRunner> Get(TaskType)
@@ -54,8 +58,6 @@
 
   Mutex mutex_;
   TaskRunnerHashMap task_runners_ GUARDED_BY(mutex_);
-
-  DISALLOW_COPY_AND_ASSIGN(ParentExecutionContextTaskRunners);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/shared_worker_client_holder.h b/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
index 433e7ca..da73e6b 100644
--- a/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
+++ b/third_party/blink/renderer/core/workers/shared_worker_client_holder.h
@@ -31,7 +31,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_CLIENT_HOLDER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_CLIENT_HOLDER_H_
 
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -68,6 +67,8 @@
   static SharedWorkerClientHolder* From(LocalDOMWindow&);
 
   explicit SharedWorkerClientHolder(LocalDOMWindow&);
+  SharedWorkerClientHolder(const SharedWorkerClientHolder&) = delete;
+  SharedWorkerClientHolder& operator=(const SharedWorkerClientHolder&) = delete;
   virtual ~SharedWorkerClientHolder() = default;
 
   // Establishes a connection with SharedWorkerHost in the browser process.
@@ -85,8 +86,6 @@
   HeapMojoUniqueReceiverSet<mojom::blink::SharedWorkerClient> client_receivers_;
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(SharedWorkerClientHolder);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
index c4ee20b..6811b34 100644
--- a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
+++ b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_REPORTING_PROXY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_REPORTING_PROXY_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
 #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -23,6 +22,9 @@
  public:
   SharedWorkerReportingProxy(WebSharedWorkerImpl*,
                              ParentExecutionContextTaskRunners*);
+  SharedWorkerReportingProxy(const SharedWorkerReportingProxy&) = delete;
+  SharedWorkerReportingProxy& operator=(const SharedWorkerReportingProxy&) =
+      delete;
   ~SharedWorkerReportingProxy() override;
 
   // WorkerReportingProxy methods:
@@ -49,7 +51,6 @@
 
   Member<ParentExecutionContextTaskRunners>
       parent_execution_context_task_runners_;
-  DISALLOW_COPY_AND_ASSIGN(SharedWorkerReportingProxy);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
index 6d462da..a53ed42 100644
--- a/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
+++ b/third_party/blink/renderer/core/workers/threaded_object_proxy_base.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_OBJECT_PROXY_BASE_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_OBJECT_PROXY_BASE_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/messaging/message_port.h"
@@ -24,6 +23,8 @@
 class CORE_EXPORT ThreadedObjectProxyBase : public WorkerReportingProxy {
   USING_FAST_MALLOC(ThreadedObjectProxyBase);
  public:
+  ThreadedObjectProxyBase(const ThreadedObjectProxyBase&) = delete;
+  ThreadedObjectProxyBase& operator=(const ThreadedObjectProxyBase&) = delete;
   ~ThreadedObjectProxyBase() override = default;
 
   void ReportPendingActivity(bool has_pending_activity);
@@ -48,7 +49,6 @@
   // thread.
   CrossThreadPersistent<ParentExecutionContextTaskRunners>
       parent_execution_context_task_runners_;
-  DISALLOW_COPY_AND_ASSIGN(ThreadedObjectProxyBase);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h b/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
index 6d492a79..00c0f0a 100644
--- a/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_WORKLET_OBJECT_PROXY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_THREADED_WORKLET_OBJECT_PROXY_H_
 
-#include "base/macros.h"
 #include "base/single_thread_task_runner.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -34,6 +33,10 @@
   static std::unique_ptr<ThreadedWorkletObjectProxy> Create(
       ThreadedWorkletMessagingProxy*,
       ParentExecutionContextTaskRunners*);
+
+  ThreadedWorkletObjectProxy(const ThreadedWorkletObjectProxy&) = delete;
+  ThreadedWorkletObjectProxy& operator=(const ThreadedWorkletObjectProxy&) =
+      delete;
   ~ThreadedWorkletObjectProxy() override;
 
   void FetchAndInvokeScript(
@@ -59,7 +62,6 @@
   // the tasks.
   CrossThreadWeakPersistent<ThreadedWorkletMessagingProxy>
       messaging_proxy_weak_ptr_;
-  DISALLOW_COPY_AND_ASSIGN(ThreadedWorkletObjectProxy);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worker_clients.h b/third_party/blink/renderer/core/workers/worker_clients.h
index d63263b..067dad3 100644
--- a/third_party/blink/renderer/core/workers/worker_clients.h
+++ b/third_party/blink/renderer/core/workers/worker_clients.h
@@ -31,7 +31,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_CLIENTS_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_CLIENTS_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -46,13 +45,12 @@
                                         public Supplementable<WorkerClients> {
  public:
   WorkerClients() = default;
+  WorkerClients(const WorkerClients&) = delete;
+  WorkerClients& operator=(const WorkerClients&) = delete;
 
   void Trace(Visitor* visitor) const override {
     Supplementable<WorkerClients>::Trace(visitor);
   }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WorkerClients);
 };
 
 extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<WorkerClients>;
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index 13420144..314dc76 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -115,6 +115,9 @@
     return base::AdoptRef<RefCountedWaitableEvent>(new RefCountedWaitableEvent);
   }
 
+  RefCountedWaitableEvent(const RefCountedWaitableEvent&) = delete;
+  RefCountedWaitableEvent& operator=(const RefCountedWaitableEvent&) = delete;
+
   void Wait() { event_.Wait(); }
   void Signal() { event_.Signal(); }
 
@@ -122,8 +125,6 @@
   RefCountedWaitableEvent() = default;
 
   base::WaitableEvent event_;
-
-  DISALLOW_COPY_AND_ASSIGN(RefCountedWaitableEvent);
 };
 
 // A class that is passed into V8 Interrupt and via a PostTask. Once both have
@@ -134,6 +135,8 @@
  public:
   InterruptData(WorkerThread* worker_thread, mojom::FrameLifecycleState state)
       : worker_thread_(worker_thread), state_(state) {}
+  InterruptData(const InterruptData&) = delete;
+  InterruptData& operator=(const InterruptData&) = delete;
 
   bool ShouldRemoveFromList() { return seen_interrupt_ && seen_post_task_; }
   void MarkPostTaskCalled() { seen_post_task_ = true; }
@@ -147,8 +150,6 @@
   mojom::FrameLifecycleState state_;
   bool seen_interrupt_ = false;
   bool seen_post_task_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(InterruptData);
 };
 
 WorkerThread::~WorkerThread() {
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index 0924cdd2..f574dec 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/macros.h"
 #include "base/synchronization/waitable_event.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
 #include "services/network/public/mojom/ip_address_space.mojom-blink.h"
diff --git a/third_party/blink/renderer/core/workers/worklet.h b/third_party/blink/renderer/core/workers/worklet.h
index f648cde..52e26f0 100644
--- a/third_party/blink/renderer/core/workers/worklet.h
+++ b/third_party/blink/renderer/core/workers/worklet.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKLET_H_
 
-#include "base/macros.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
@@ -29,6 +28,8 @@
   USING_PRE_FINALIZER(Worklet, Dispose);
 
  public:
+  Worklet(const Worklet&) = delete;
+  Worklet& operator=(const Worklet&) = delete;
   ~Worklet() override;
 
   void Dispose();
@@ -94,8 +95,6 @@
 
   // Keeps track of pending tasks from addModule() call.
   HeapHashSet<Member<WorkletPendingTasks>> pending_tasks_set_;
-
-  DISALLOW_COPY_AND_ASSIGN(Worklet);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index d32fd76..9a645d0 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -2591,10 +2591,31 @@
   ]
 
   deps = [
+    ":platform",
     ":test_support",
+    "//base",
+    "//base/test:test_support",
+    "//cc",
+    "//components/viz/test:test_support",
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/blink/public:test_headers",
   ]
   public_deps = [ "//gpu:raster" ]
+
+  if (media_use_ffmpeg || !is_android) {
+    sources += [ "media/web_media_player_impl_unittest.cc" ]
+    data = [ "//media/test/data/" ]
+    deps += [
+      "//media",
+      "//media:test_support",
+      "//media/mojo/services",
+      "//third_party/blink/public:blink",
+      "//third_party/blink/public:test_support",
+      "//third_party/blink/public/common/tokens:tokens_headers",
+      "//third_party/blink/public/platform/media",
+      "//third_party/blink/renderer/platform/media",
+      "//ui/gfx/geometry",
+    ]
+  }
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
index 0d1e64b..6220a8a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_defer_loading_test.cc
@@ -39,10 +39,6 @@
   ~TestCodeCacheLoader() override = default;
 
   // WebCodeCacheLoader methods:
-  void FetchFromCodeCacheSynchronously(
-      const WebURL& url,
-      base::Time* response_time_out,
-      mojo_base::BigBuffer* buffer_out) override {}
   void FetchFromCodeCache(
       blink::mojom::CodeCacheType cache_type,
       const WebURL& url,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc
index 2866518..a3dfe454 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.cc
@@ -4,141 +4,37 @@
 
 #include "third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h"
 
-#include "base/bind.h"
-#include "base/task/post_task.h"
-#include "base/task/thread_pool.h"
 #include "mojo/public/cpp/base/big_buffer.h"
 #include "third_party/blink/public/mojom/loader/code_cache.mojom.h"
 #include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/url_conversion.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "url/gurl.h"
 
 namespace blink {
 
-CodeCacheLoader::CodeCacheLoader() : CodeCacheLoader(nullptr, nullptr) {}
-
-CodeCacheLoader::CodeCacheLoader(mojom::CodeCacheHost* code_cache_host,
-                                 base::WaitableEvent* terminate_sync_load_event)
-    : code_cache_host_(code_cache_host),
-      terminate_sync_load_event_(terminate_sync_load_event) {}
+CodeCacheLoader::CodeCacheLoader(mojom::CodeCacheHost* code_cache_host)
+    : code_cache_host_(code_cache_host) {}
 
 CodeCacheLoader::~CodeCacheLoader() = default;
 
-void CodeCacheLoader::FetchFromCodeCacheSynchronously(
-    const WebURL& url,
-    base::Time* response_time_out,
-    mojo_base::BigBuffer* data_out) {
-  base::WaitableEvent fetch_code_cache_event(
-      base::WaitableEvent::ResetPolicy::AUTOMATIC,
-      base::WaitableEvent::InitialState::NOT_SIGNALED);
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-      base::ThreadPool::CreateSingleThreadTaskRunner({});
-
-  // Also watch for terminate requests from the main thread when running on
-  // worker threads.
-  if (terminate_sync_load_event_) {
-    terminate_watcher_.StartWatching(
-        terminate_sync_load_event_,
-        base::BindOnce(&CodeCacheLoader::OnTerminate,
-                       weak_ptr_factory_.GetWeakPtr(),
-                       base::Unretained(&fetch_code_cache_event)),
-        task_runner);
-  }
-
-  FetchCodeCacheCallback callback =
-      base::BindOnce(&CodeCacheLoader::ReceiveDataForSynchronousFetch,
-                     weak_ptr_factory_.GetWeakPtr());
-
-  // It is Ok to pass |fetch_code_cache_event| with base::Unretained. Since
-  // this thread is stalled, the fetch_code_cache_event will be kept alive.
-  task_runner->PostTask(
-      FROM_HERE, base::BindOnce(&CodeCacheLoader::FetchFromCodeCacheImpl,
-                                weak_ptr_factory_.GetWeakPtr(),
-                                mojom::CodeCacheType::kJavascript, url,
-                                std::move(callback),
-                                base::Unretained(&fetch_code_cache_event)));
-
-  // Wait for the fetch from code cache to finish.
-  fetch_code_cache_event.Wait();
-
-  // Set the output data
-  *response_time_out = response_time_for_sync_load_;
-  *data_out = std::move(data_for_sync_load_);
-}
-
 void CodeCacheLoader::FetchFromCodeCache(mojom::CodeCacheType cache_type,
                                          const WebURL& url,
                                          FetchCodeCacheCallback callback) {
-  FetchFromCodeCacheImpl(cache_type, url, std::move(callback), nullptr);
-}
-
-void CodeCacheLoader::FetchFromCodeCacheImpl(mojom::CodeCacheType cache_type,
-                                             const WebURL& url,
-                                             FetchCodeCacheCallback callback,
-                                             base::WaitableEvent* fetch_event) {
-  // This may run on a different thread for synchronous events. It is Ok to pass
-  // fetch_event, because the thread is stalled and it will keep the fetch_event
-  // alive.
-  auto receive_callback = base::BindOnce(&CodeCacheLoader::OnReceiveCachedCode,
-                                         weak_ptr_factory_.GetWeakPtr(),
-                                         std::move(callback), fetch_event);
   if (code_cache_host_) {
-    code_cache_host_->FetchCachedCode(
-        cache_type, WebStringToGURL(url.GetString()),
-        base::BindOnce(
-            [](Platform::FetchCachedCodeCallback callback, base::Time time,
-               mojo_base::BigBuffer data) {
-              std::move(callback).Run(time, std::move(data));
-            },
-            std::move(receive_callback)));
+    code_cache_host_->FetchCachedCode(cache_type,
+                                      static_cast<GURL>(static_cast<KURL>(url)),
+                                      std::move(callback));
   } else {
     // TODO(mythria): This path is required for workers currently. Once we
     // update worker requests to go through WorkerHost remove this path.
-    Platform::Current()->FetchCachedCode(cache_type, url,
-                                         std::move(receive_callback));
+    Platform::Current()->FetchCachedCode(cache_type, url, std::move(callback));
   }
 }
 
-void CodeCacheLoader::OnReceiveCachedCode(FetchCodeCacheCallback callback,
-                                          base::WaitableEvent* fetch_event,
-                                          base::Time response_time,
-                                          mojo_base::BigBuffer data) {
-  // The loader would be destroyed once the fetch has completed. On terminate
-  // the fetch event would be signalled and the fetch should complete and hence
-  // we should not see this callback anymore.
-  DCHECK(!terminated_);
-  std::move(callback).Run(response_time, std::move(data));
-  if (fetch_event)
-    fetch_event->Signal();
-}
-
-void CodeCacheLoader::ReceiveDataForSynchronousFetch(
-    base::Time response_time,
-    mojo_base::BigBuffer data) {
-  response_time_for_sync_load_ = response_time;
-  data_for_sync_load_ = std::move(data);
-}
-
-void CodeCacheLoader::OnTerminate(base::WaitableEvent* fetch_event,
-                                  base::WaitableEvent* terminate_event) {
-  DCHECK(!terminated_);
-  terminated_ = true;
-  DCHECK(fetch_event);
-  fetch_event->Signal();
-}
-
 // static
-std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::CreateForFrame(
+std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::Create(
     mojom::CodeCacheHost* code_cache_host) {
-  return std::make_unique<CodeCacheLoader>(
-      code_cache_host, /*terminate_sync_load_event*/ nullptr);
-}
-
-// static
-std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::CreateForWorker(
-    mojom::CodeCacheHost* code_cache_host,
-    base::WaitableEvent* terminate_sync_load_event) {
-  return std::make_unique<CodeCacheLoader>(code_cache_host,
-                                           terminate_sync_load_event);
+  return std::make_unique<CodeCacheLoader>(code_cache_host);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h
index 0f442295..9cee969 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/code_cache_loader.h
@@ -5,12 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_LOADER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_URL_LOADER_CODE_CACHE_LOADER_H_
 
-#include "base/containers/span.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/synchronization/waitable_event_watcher.h"
 #include "third_party/blink/public/platform/web_code_cache_loader.h"
-#include "url/gurl.h"
 
 namespace blink {
 
@@ -20,52 +15,21 @@
 // cache backend to avoid cross-origin contamination.
 class BLINK_PLATFORM_EXPORT CodeCacheLoader : public WebCodeCacheLoader {
  public:
-  CodeCacheLoader();
   // |code_cache_host| is the per-frame mojo interface that should be used when
   // fetching code cache. If this value is nullptr it uses per-process
   // interface.
   // TODO(mythria): Remove the per-process interface and only expect non nullptr
   // for |code_cache_host|.
-  // |terminate_sync_load_event| is required on worker threads to monitor for
-  // any terminate requests from main thread.
-  CodeCacheLoader(mojom::CodeCacheHost* code_cache_host,
-                  base::WaitableEvent* terminate_sync_load_event);
+  explicit CodeCacheLoader(mojom::CodeCacheHost* code_cache_host);
 
   ~CodeCacheLoader() override;
 
-  // Fetches code cache corresponding to |url| and returns response in
-  // |response_time_out| and |data_out|.  |response_time_out| and |data_out|
-  // cannot be nullptrs. This only fetches from the Javascript cache.
-  void FetchFromCodeCacheSynchronously(const WebURL& url,
-                                       base::Time* response_time_out,
-                                       mojo_base::BigBuffer* data_out) override;
-
   void FetchFromCodeCache(mojom::CodeCacheType cache_type,
                           const WebURL& url,
                           FetchCodeCacheCallback callback) override;
 
  private:
-  void FetchFromCodeCacheImpl(mojom::CodeCacheType cache_type,
-                              const WebURL& url,
-                              FetchCodeCacheCallback callback,
-                              base::WaitableEvent* event);
-
-  void OnReceiveCachedCode(FetchCodeCacheCallback callback,
-                           base::WaitableEvent* event,
-                           base::Time response_time,
-                           mojo_base::BigBuffer data);
-  void ReceiveDataForSynchronousFetch(base::Time response_time,
-                                      mojo_base::BigBuffer data);
-  void OnTerminate(base::WaitableEvent* fetch_event,
-                   base::WaitableEvent* terminate_event);
-
-  base::Time response_time_for_sync_load_;
-  mojo_base::BigBuffer data_for_sync_load_;
-  bool terminated_ = false;
-  base::WaitableEventWatcher terminate_watcher_;
-  mojom::CodeCacheHost* code_cache_host_;
-  base::WaitableEvent* terminate_sync_load_event_ = nullptr;
-  base::WeakPtrFactory<CodeCacheLoader> weak_ptr_factory_{this};
+  mojom::CodeCacheHost* const code_cache_host_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
index f3dc7c444..f8da181 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
@@ -395,8 +395,7 @@
 std::unique_ptr<WebCodeCacheLoader>
 DedicatedOrSharedWorkerFetchContextImpl::CreateCodeCacheLoader(
     blink::mojom::CodeCacheHost* code_cache_host) {
-  return blink::WebCodeCacheLoader::CreateForWorker(code_cache_host,
-                                                    terminate_sync_load_event_);
+  return WebCodeCacheLoader::Create(code_cache_host);
 }
 
 void DedicatedOrSharedWorkerFetchContextImpl::WillSendRequest(
diff --git a/third_party/blink/renderer/platform/media/BUILD.gn b/third_party/blink/renderer/platform/media/BUILD.gn
index 551d579..609706b 100644
--- a/third_party/blink/renderer/platform/media/BUILD.gn
+++ b/third_party/blink/renderer/platform/media/BUILD.gn
@@ -8,9 +8,6 @@
 # ported to Blink code conventions.
 component("media") {
   visibility = [
-    # TODO(https://crbug.com/1198341): remove once
-    # webmediaplayer_impl_unittest.cc is moved to Blink.
-    "//media/blink:*",
     "//third_party/blink/public/platform/media",
     "//third_party/blink/renderer/platform/*",
   ]
@@ -148,12 +145,7 @@
 }
 
 source_set("test_support") {
-  visibility = [
-    # TODO(https://crbug.com/1198341): remove once
-    # webmediaplayer_impl_unittest.cc is moved to Blink.
-    "//media/blink:*",
-    "//third_party/blink/renderer/platform:test_support",
-  ]
+  visibility = [ "//third_party/blink/renderer/platform:test_support" ]
   testonly = true
   configs += [
     "//third_party/blink/renderer:non_test_config",
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc
similarity index 98%
rename from media/blink/webmediaplayer_impl_unittest.cc
rename to third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc
index 36943368..21c339ce 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc
@@ -74,8 +74,9 @@
 #include "third_party/blink/renderer/platform/media/testing/mock_web_associated_url_loader.h"
 #include "third_party/blink/renderer/platform/media/video_decode_stats_reporter.h"
 #include "third_party/blink/renderer/platform/media/web_content_decryption_module_impl.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "ui/gfx/geometry/size.h"
-#include "url/gurl.h"
 
 using ::base::test::RunClosure;
 using ::base::test::RunOnceCallback;
@@ -515,13 +516,15 @@
     wmpi_->pipeline_metadata_.has_audio = has_audio;
     wmpi_->pipeline_metadata_.has_video = has_video;
 
-    if (has_video)
+    if (has_video) {
       wmpi_->pipeline_metadata_.video_decoder_config =
           TestVideoConfig::Normal();
+    }
 
-    if (has_audio)
+    if (has_audio) {
       wmpi_->pipeline_metadata_.audio_decoder_config =
           TestAudioConfig::Normal();
+    }
   }
 
   void SetError(PipelineStatus status = PIPELINE_ERROR_DECODE) {
@@ -692,8 +695,9 @@
     // the resource is fully buffered locally. We can use a fake one here since
     // we're injecting the response artificially. It's value is unknown to the
     // underlying demuxer.
-    const GURL kTestURL(std::string(is_streaming ? "http" : "file") +
-                        "://example.com/sample.webm");
+    const blink::KURL kTestURL(
+        String::FromUTF8(std::string(is_streaming ? "http" : "file") +
+                         "://example.com/sample.webm"));
 
     // This block sets up a fetch context which ultimately provides us a pointer
     // to the WebAssociatedURLLoaderClient handed out by the DataSource after it
@@ -920,7 +924,7 @@
   EXPECT_FALSE(IsSuspended());
   wmpi_->SetPreload(blink::WebMediaPlayer::kPreloadAuto);
 
-  const GURL kMp3DataUrl(
+  const blink::KURL kMp3DataUrl(
       "data://audio/mp3;base64,SUQzAwAAAAAAFlRFTkMAAAAMAAAAQW1hZGV1cyBQcm//"
       "+5DEAAAAAAAAAAAAAAAAAAAAAABYaW5nAAAADwAAAAwAAAftABwcHBwcHBwcMTExMTExMTFG"
       "RkZGRkZGRlpaWlpaWlpaWm9vb29vb29vhISEhISEhISYmJiYmJiYmJitra2tra2trcLCwsLC"
@@ -1106,7 +1110,7 @@
   InitializeWebMediaPlayerImpl();
   EXPECT_CALL(client_, CouldPlayIfEnoughData()).WillRepeatedly(Return(false));
   wmpi_->SetPreload(blink::WebMediaPlayer::kPreloadMetaData);
-  wmpi_->SetPoster(blink::WebURL(GURL("file://example.com/sample.jpg")));
+  wmpi_->SetPoster(blink::WebURL(blink::KURL("file://example.com/sample.jpg")));
 
   LoadAndWaitForReadyState(kVideoOnlyTestFile,
                            blink::WebMediaPlayer::kReadyStateHaveMetadata);
@@ -2175,10 +2179,11 @@
   InitializeWebMediaPlayerImplInternal(std::move(demuxer));
 
   EXPECT_FALSE(IsSuspended());
-  wmpi_->Load(blink::WebMediaPlayer::kLoadTypeURL,
-              blink::WebMediaPlayerSource(blink::WebURL(GURL("data://test"))),
-              blink::WebMediaPlayer::kCorsModeUnspecified,
-              /*is_cache_disabled=*/false);
+  wmpi_->Load(
+      blink::WebMediaPlayer::kLoadTypeURL,
+      blink::WebMediaPlayerSource(blink::WebURL(blink::KURL("data://test"))),
+      blink::WebMediaPlayer::kCorsModeUnspecified,
+      /*is_cache_disabled=*/false);
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(IsSuspended());
 }
diff --git a/third_party/blink/renderer/platform/network/DEPS b/third_party/blink/renderer/platform/network/DEPS
index d89e72da..2ae0d9d 100644
--- a/third_party/blink/renderer/platform/network/DEPS
+++ b/third_party/blink/renderer/platform/network/DEPS
@@ -7,7 +7,7 @@
 
     # Dependencies.
     "+media",
-    "-media/blink",
+
     # net/ includes should be allowed only in a limited set of directories,
     # so we have separate DEPS from platform's one.
     "+net/base",
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 19c7c73..36a5689 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -209,6 +209,10 @@
       status: "experimental",
     },
     {
+      name: "AutoExpandDetailsElement",
+      status: "experimental",
+    },
+    {
       name: "AutofillShadowDOM",
       status: "experimental",
     },
diff --git a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
index dd55c90..df5ba5e 100644
--- a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
+++ b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.cc
@@ -6,14 +6,6 @@
 
 namespace blink {
 
-void CodeCacheLoaderMock::FetchFromCodeCacheSynchronously(
-    const WebURL& url,
-    base::Time* response_time_out,
-    mojo_base::BigBuffer* buffer_out) {
-  *response_time_out = base::Time();
-  *buffer_out = mojo_base::BigBuffer();
-}
-
 void CodeCacheLoaderMock::FetchFromCodeCache(
     blink::mojom::CodeCacheType cache_type,
     const WebURL& url,
diff --git a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
index 3b764b66..2f0e4b9 100644
--- a/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
+++ b/third_party/blink/renderer/platform/testing/code_cache_loader_mock.h
@@ -20,10 +20,6 @@
   ~CodeCacheLoaderMock() override = default;
 
   // CodeCacheLoader methods:
-  void FetchFromCodeCacheSynchronously(
-      const WebURL& url,
-      base::Time* response_time_out,
-      mojo_base::BigBuffer* buffer_out) override;
   void FetchFromCodeCache(
       blink::mojom::CodeCacheType cache_type,
       const WebURL& url,
diff --git a/third_party/blink/renderer/platform/testing/testing_platform_support.h b/third_party/blink/renderer/platform/testing/testing_platform_support.h
index dfdddac..c60029c 100644
--- a/third_party/blink/renderer/platform/testing/testing_platform_support.h
+++ b/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -96,7 +96,7 @@
 
  private:
   bool is_threaded_animation_enabled_ = false;
-  bool is_zoom_for_dsf_enabled_ = false;
+  bool is_zoom_for_dsf_enabled_ = true;
 };
 
 // ScopedTestingPlatformSupport<MyTestingPlatformSupport> can be used to
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index dee3bcc7..2c45d97 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -4055,7 +4055,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/rendering/order/z-index.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/shapes/reftests/pathlength-003.svg [ Failure Pass ]
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/struct/reftests/use-inheritance-001.svg [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/text/reftests/dominant-baseline-hanging-small-font-size.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/text/reftests/text-complex-001.svg [ Failure Pass ]
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/text/reftests/text-complex-002.svg [ Failure Pass ]
 crbug.com/1179585 virtual/layout_ng_svg_text/external/wpt/svg/text/reftests/text-inline-size-001.svg [ Failure Pass ]
@@ -4088,7 +4087,7 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/js-late-gradient-and-object-creation.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/js-late-gradient-creation.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/js-late-pattern-and-object-creation.svg [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/js-late-pattern-creation.svg [ Failure ]
+crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/paint/invalidation/svg/js-late-pattern-creation.svg [ Failure ]
 crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/paint/invalidation/svg/modify-transferred-listitem-different-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/outline-offset-text.html [ Failure ]
 crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/paint/invalidation/svg/repaint-non-scaling-stroke-text.html [ Failure ]
@@ -4100,7 +4099,7 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/text-viewbox-rescale.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/transform-text-element.html [ Pass Failure ]
 crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/paint/invalidation/svg/tspan-dynamic-positioning.svg [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/paint/invalidation/svg/use-detach.svg [ Failure ]
+crbug.com/1179585 [ Mac ] virtual/layout_ng_svg_text/paint/invalidation/svg/use-detach.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/animations/animate-text-nested-transforms.html [ Timeout ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/batik/text/smallFonts.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/batik/text/textDecoration.svg [ Failure ]
@@ -4116,7 +4115,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/clip-path/clip-path-use-referencing-text.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/clip-path/clip-path-with-text-clipped.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/css/text-shadow-multiple.xhtml [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/alignment-baseline-modes.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/empty-mask.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/focus-ring.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/focus-ring-text.svg [ Failure ]
@@ -4131,7 +4129,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/text-match-highlight.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/transformed-outlines.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/visibility-collapse.html [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/svg/custom/zoomed-alignment-baseline.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dom/undefined-null.html [ Pass Crash ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-lengthAdjust-attr.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/dynamic-updates/SVGTextElement-dom-transform-attr.html [ Pass Failure ]
@@ -4143,7 +4140,6 @@
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/rotated-text.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/singular-transform-3.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/svg-pointer-events-bbox.html [ Failure ]
-crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/text-dominant-baseline-hanging.svg [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/text-fill-none-with-nested-tspan.html [ Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/text-multiple-dx-values.svg [ Pass Failure ]
 crbug.com/1179585 virtual/layout_ng_svg_text/svg/hittest/text-small-font-size.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 9d45dba..e70aa81 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -1069,7 +1069,9 @@
               "external/wpt/accessibility/crashtests/included-descendant-dom-removal.html",
               "external/wpt/accessibility/crashtests/included-descendant-layout-removal.html",
               "external/wpt/accessibility/crashtests/slot-assignment-lockup.html",
-              "external/wpt/accessibility/crashtests/validation-message.html"],
+              "external/wpt/accessibility/crashtests/validation-message.html",
+              "editing/text-iterator/auto-expand-details.html",
+              "editing/text-iterator/auto-expand-details-shadowdom.html"],
     "args": ["--force-renderer-accessibility"]
   },
   {
diff --git a/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-on-summary.html b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-on-summary.html
new file mode 100644
index 0000000..c04e3e33
--- /dev/null
+++ b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-on-summary.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div style="height:2000px"></div>
+
+<details id=detailselement>
+  <summary>summary</summary>
+  details
+</details>
+
+<script>
+async_test(t => {
+  assert_false(detailselement.open, `details should be closed at the start of the test.`);
+
+  detailselement.addEventListener('toggle',
+    t.unreached_func(`The details element shouldn't be toggled opened when the target text is in the summary.`));
+
+  testRunner.findString('summary', ['Async']);
+
+  requestAnimationFrame(t.step_func(() => {
+    requestAnimationFrame(t.step_func(() => {
+      requestAnimationFrame(t.step_func_done(() => {
+        assert_false(detailselement.open, `The details shouldn't be open at the end of the test.`);
+      }));
+    }));
+  }));
+}, `Verifies that find-in-page does not expands details elements when the target text is inside of their already visible summary.`);
+</script>
diff --git a/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-shadowdom.html b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-shadowdom.html
new file mode 100644
index 0000000..d1d29fb
--- /dev/null
+++ b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details-shadowdom.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div style="height:2000px"></div>
+
+<div id=shadowhost>
+  <template shadowroot=open>
+    <details id=detailselement>
+      <summary>summary</summary>
+      details
+    </details>
+  </template>
+</div>
+
+<script>
+async_test(t => {
+  const detailselement = shadowhost.shadowRoot.getElementById('detailselement');
+  assert_false(detailselement.open, `details should be closed at the start of the test.`);
+  assert_equals(window.pageYOffset, 0, `page should be scrolled to the top at the start of the test.`);
+
+  detailselement.addEventListener('toggle', t.step_func_done(() => {
+    assert_true(detailselement.open, `find-in-page should open the details element.`);
+    assert_not_equals(window.pageYOffset, 0, `find-in-page should scroll to the details element.`);
+  }));
+
+  testRunner.findString('details', ['Async']);
+}, `Verifies that find-in-page expands details elements in shadow dom when the target text is inside of them.`);
+</script>
diff --git a/third_party/blink/web_tests/editing/text-iterator/auto-expand-details.html b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details.html
new file mode 100644
index 0000000..01ef2a5
--- /dev/null
+++ b/third_party/blink/web_tests/editing/text-iterator/auto-expand-details.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+
+<div style="height:2000px"></div>
+
+<details id=detailselement>
+  <summary>summary</summary>
+  details
+</details>
+
+<script>
+async_test(t => {
+  assert_false(detailselement.open, `details should be closed at the start of the test.`);
+  assert_equals(window.pageYOffset, 0, `page should be scrolled to the top at the start of the test.`);
+
+  detailselement.addEventListener('toggle', t.step_func_done(() => {
+    assert_true(detailselement.open, `find-in-page should open the details element.`);
+    assert_not_equals(window.pageYOffset, 0, `find-in-page should scroll to the details element.`);
+  }));
+
+  testRunner.findString('details', ['Async']);
+}, `Verifies that find-in-page expands details elements when the target text is inside of them.`);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-019.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-019.html
index b26729f1..b0aeac3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-019.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-019.html
@@ -2,6 +2,7 @@
 <meta charset="utf-8">
 <title>CSS Grid Layout Test: Fixed positioned element in grid.</title>
 <link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="match" href="positioned-grid-items-019-ref.html">
 <meta name="assert" content="This test checks the behavior of the fixed positioned elements with a grid container as parent.">
 <style>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022-ref.html
new file mode 100644
index 0000000..0b2cfda
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Positioned grid items reference file</title>
+<style>
+  #grid {
+    width: 100px;
+    height: 100px;
+    background-color: blue;
+    position: relative;
+    padding: 5px;
+  }
+
+  .abspos {
+    position: absolute;
+    bottom: 0px; right: 0px;
+    background-color: hotpink;
+  }
+
+  #start {
+    top: 0px; left: 0px;
+    width: 5px;
+    height: 5px;
+  }
+
+  #end {
+    top: 5px; left: 5px;
+    width: 105px;
+    height: 105px;
+  }
+
+</style>
+
+  <p>The test passes if it has the same output than the reference.</p>
+
+  <div id="grid">
+    <div class="abspos" id="start"></div>
+    <div class="abspos" id="end"></div>
+  </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022.html
new file mode 100644
index 0000000..df35b546
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-022.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Positioned grid items</title>
+<link rel="help" href="https://drafts.csswg.org/css-grid/#abspos" title="9. Absolute Positioning">
+<link rel="match" href="positioned-grid-items-022-ref.html">
+<meta name="assert" content="Checks that absolutely positioned grid items are properly placed in an undefined grid.">
+<style>
+  #grid {
+    display: grid;
+    width: 100px;
+    height: 100px;
+    background-color: blue;
+    position: relative;
+    padding: 5px;
+  }
+
+  .abspos {
+    position: absolute;
+    top: 0px; bottom: 0px; left: 0px; right: 0px;
+    width: 100%;
+    height: 100%;
+    background-color: hotpink;
+  }
+
+  #start {
+    grid-area: 1/1/auto/auto;
+  }
+
+  #end {
+    grid-area: auto/auto/1/1;
+  }
+
+</style>
+
+  <p>The test passes if it has the same output than the reference.</p>
+
+  <div id="grid">
+    <div class="abspos" id="start"></div>
+    <div class="abspos" id="end"></div>
+  </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/closed-details-layout-apis.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/closed-details-layout-apis.tentative.html
new file mode 100644
index 0000000..1936cdb6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/closed-details-layout-apis.tentative.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/pull/6466">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<details id=details>
+  <div style="width:100px; height:100px; background-color:red" id=innerdiv></div>
+</details>
+
+<script>
+test(() => {
+  assert_not_equals(innerdiv.getBoundingClientRect().x, 0, 'x before open');
+  assert_not_equals(innerdiv.getBoundingClientRect().y, 0, 'y before open');
+  assert_not_equals(innerdiv.getBoundingClientRect().width, 0, 'width before open');
+  assert_not_equals(innerdiv.getBoundingClientRect().height, 0, 'height before open');
+  details.open = true;
+  assert_not_equals(innerdiv.getBoundingClientRect().x, 0, 'x after open');
+  assert_not_equals(innerdiv.getBoundingClientRect().y, 0, 'y after open');
+  assert_not_equals(innerdiv.getBoundingClientRect().width, 0, 'width after open');
+  assert_not_equals(innerdiv.getBoundingClientRect().height, 0, 'height after open');
+  details.open = false;
+  assert_not_equals(innerdiv.getBoundingClientRect().x, 0, 'x after close');
+  assert_not_equals(innerdiv.getBoundingClientRect().y, 0, 'y after close');
+  assert_not_equals(innerdiv.getBoundingClientRect().width, 0, 'width after close');
+  assert_not_equals(innerdiv.getBoundingClientRect().height, 0, 'height after close');
+}, `Verifies the layout results of elements inside a closed <details> based on the usage of content-visibility:hidden.`);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary-ref.html
new file mode 100644
index 0000000..14f2be2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<details>
+  <summary>new summary</summary>
+  details
+</details>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary.html
new file mode 100644
index 0000000..1b0062e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/details-add-summary.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel=match href="details-add-summary-ref.html">
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://github.com/whatwg/html/pull/6466">
+
+<!-- This test makes sure that new <summary> elements get rendered correctly
+  when added to a <details> element. I ran into it when adding
+  content-visibility:hidden to the second slot of <details>. -->
+
+<script>
+onload = () => {
+  const newsummary = document.createElement('summary');
+  newsummary.textContent = 'new summary';
+  document.getElementById('detailsid').insertBefore(newsummary,
+    document.getElementById('oldsummary'));
+
+  document.documentElement.classList.remove('reftest-wait');
+};
+</script>
+
+<details id=detailsid>
+  <summary id=oldsummary>old summary</summary>
+  details
+</details>
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-clone-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-clone-expected.png
new file mode 100644
index 0000000..b25eb8d
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-clone-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-marker-style-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-marker-style-expected.png
index b16c55f..2122f7b 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-marker-style-expected.png
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/html/details_summary/details-marker-style-expected.png
Binary files differ
diff --git a/third_party/widevine/cdm/BUILD.gn b/third_party/widevine/cdm/BUILD.gn
index 94e3073..d389a4df 100644
--- a/third_party/widevine/cdm/BUILD.gn
+++ b/third_party/widevine/cdm/BUILD.gn
@@ -19,7 +19,6 @@
     "ENABLE_WIDEVINE=$enable_widevine",
     "BUNDLE_WIDEVINE_CDM=$bundle_widevine_cdm",
     "ENABLE_WIDEVINE_CDM_COMPONENT=$enable_widevine_cdm_component",
-    "ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM=$enable_media_foundation_widevine_cdm",
   ]
 }
 
@@ -79,7 +78,6 @@
     ":buildflags",
     ":version_h",  # Forward permission to use version header.
     "//base",
-    "//media:media_buildflags",
   ]
 }
 
diff --git a/third_party/widevine/cdm/DEPS b/third_party/widevine/cdm/DEPS
index f7cd23d..0d6a1d5 100644
--- a/third_party/widevine/cdm/DEPS
+++ b/third_party/widevine/cdm/DEPS
@@ -1,4 +1,4 @@
 include_rules = [
   "+base/token.h",
-  "+media/media_buildflags.h",
+  "+build/build_config.h",
 ]
diff --git a/third_party/widevine/cdm/widevine.gni b/third_party/widevine/cdm/widevine.gni
index e94b477..3f73a13 100644
--- a/third_party/widevine/cdm/widevine.gni
+++ b/third_party/widevine/cdm/widevine.gni
@@ -44,13 +44,6 @@
     enable_library_widevine_cdm &&
     (is_win || is_mac || is_linux || is_chromeos_lacros)
 
-# Enable (Windows) Media Foundation Widevine CDM. Desabled by default for test.
-declare_args() {
-  enable_media_foundation_widevine_cdm = false
-}
-assert(!enable_media_foundation_widevine_cdm || enable_widevine)
-assert(!enable_media_foundation_widevine_cdm || is_win)
-
 declare_args() {
   # Widevine CDM is bundled as part of Google Chrome builds.
   bundle_widevine_cdm = enable_library_widevine_cdm && is_chrome_branded
diff --git a/third_party/widevine/cdm/widevine_cdm_common.h b/third_party/widevine/cdm/widevine_cdm_common.h
index 718f8e3..12b7dbb 100644
--- a/third_party/widevine/cdm/widevine_cdm_common.h
+++ b/third_party/widevine/cdm/widevine_cdm_common.h
@@ -6,7 +6,7 @@
 #define WIDEVINE_CDM_WIDEVINE_CDM_COMMON_H_
 
 #include "base/token.h"
-#include "third_party/widevine/cdm/buildflags.h"
+#include "build/build_config.h"
 
 // Default constants common to all Widevine CDMs.
 
@@ -37,12 +37,12 @@
 const char kWidevineCdmFileSystemId[] = "application_x-ppapi-widevine-cdm";
 
 // Constants specific to Windows MediaFoundation-based Widevine CDM library.
-#if BUILDFLAG(ENABLE_MEDIA_FOUNDATION_WIDEVINE_CDM)
+#if defined(OS_WIN)
 const char kMediaFoundationWidevineCdmLibraryName[] = "Google.Widevine.CDM";
 const char kMediaFoundationWidevineCdmDisplayName[] =
     "Google Widevine Windows CDM";
 const base::Token kMediaFoundationWidevineCdmGuid{0x8e73dec793bf5adcull,
                                                   0x27e572c9a1fd930eull};
-#endif
+#endif  // defined(OS_WIN)
 
 #endif  // WIDEVINE_CDM_WIDEVINE_CDM_COMMON_H_
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index a8ee502..bd796773 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env vpython
 # 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.
@@ -79,8 +79,6 @@
 import shlex
 import shutil
 import subprocess
-import urllib2
-
 import six
 
 if six.PY2:
@@ -349,7 +347,7 @@
     output_file_path = os.path.join(_GetLogsDirectoryPath(), output_file_name)
 
     profdata_file_path = None
-    for _ in xrange(MERGE_RETRIES):
+    for _ in range(MERGE_RETRIES):
       logging.info('Running command: "%s", the output is redirected to "%s".',
                    command, output_file_path)
 
@@ -631,7 +629,7 @@
   export_output = subprocess.check_output(subprocess_cmd)
 
   # Write output on the disk to be used by code coverage bot.
-  with open(_GetSummaryFilePath(), 'w') as f:
+  with open(_GetSummaryFilePath(), 'wb') as f:
     f.write(export_output)
 
   return export_output
diff --git a/tools/code_coverage/coverage_utils.py b/tools/code_coverage/coverage_utils.py
index 5284178..038fc5e 100644
--- a/tools/code_coverage/coverage_utils.py
+++ b/tools/code_coverage/coverage_utils.py
@@ -224,6 +224,8 @@
         table_entry_type=self._table_entry_type)
     html_footer = self._footer_template.render()
 
+    if not os.path.exists(os.path.dirname(self._output_path)):
+      os.makedirs(os.path.dirname(self._output_path))
     with open(self._output_path, 'w') as html_file:
       html_file.write(html_header + html_table + html_footer)
 
@@ -540,21 +542,6 @@
                           src_root_html_report_path)
     logging.debug('Finished generating directory view html index file.')
 
-  def RenameDefaultCoverageDirectory(self):
-    """Rename the default coverage directory into platform specific name."""
-    # llvm-cov creates "coverage" subdir in the output dir. We would like to use
-    # the platform name instead, as it simplifies the report dir structure when
-    # the same report is generated for different platforms.
-    default_report_subdir_path = os.path.join(self.output_dir, 'coverage')
-    if not os.path.exists(default_report_subdir_path):
-      logging.error('Default coverage report dir does not exist: %s.',
-                    default_report_subdir_path)
-
-    if not os.path.exists(self.report_root_dir):
-      os.mkdir(self.report_root_dir)
-
-    MergeTwoDirectories(default_report_subdir_path, self.report_root_dir)
-
   def OverwriteHtmlReportsIndexFile(self):
     """Overwrites the root index file to redirect to the default view."""
     html_index_file_path = self.html_index_path
@@ -569,8 +556,6 @@
       os.remove(index_path)
 
   def PrepareHtmlReport(self):
-    self.RenameDefaultCoverageDirectory()
-
     per_file_coverage_summary = self.GeneratePerFileCoverageSummary()
 
     if not self.no_file_view:
@@ -722,16 +707,6 @@
   return shared_libraries
 
 
-def MergeTwoDirectories(src_dir_path, dst_dir_path):
-  """Merge src_dir_path directory into dst_path directory."""
-  for filename in os.listdir(src_dir_path):
-    dst_path = os.path.join(dst_dir_path, filename)
-    if os.path.exists(dst_path):
-      shutil.rmtree(dst_path)
-    os.rename(os.path.join(src_dir_path, filename), dst_path)
-  shutil.rmtree(src_dir_path)
-
-
 def WriteRedirectHtmlFile(from_html_path, to_html_path):
   """Writes a html file that redirects to another html file."""
   to_html_relative_path = GetRelativePathToDirectoryOfFile(
diff --git a/tools/code_coverage/test_suite.txt b/tools/code_coverage/test_suite.txt
index 1a20847..7ad2a4d 100644
--- a/tools/code_coverage/test_suite.txt
+++ b/tools/code_coverage/test_suite.txt
@@ -46,7 +46,6 @@
 jingle_unittests
 latency_unittests
 libjingle_xmpp_unittests
-media_blink_unittests
 media_mojo_unittests
 media_service_unittests
 media_unittests
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 2aa0f69..de8182f 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -711,6 +711,8 @@
     'infra': {
       'linux-control-rel': 'release_bot',
       'linux-component-rel': 'shared_release_bot',
+      'linux-local-ssd-nvme-rel': 'release_bot',
+      'linux-local-ssd-scsi-rel': 'release_bot',
     },
 
     'internal.chrome.fyi': {
diff --git a/tools/mb/mb_config_expectations/infra.json b/tools/mb/mb_config_expectations/infra.json
index 989cb58f..6a7d0cb 100644
--- a/tools/mb/mb_config_expectations/infra.json
+++ b/tools/mb/mb_config_expectations/infra.json
@@ -12,5 +12,19 @@
       "is_debug": false,
       "use_goma": true
     }
+  },
+  "linux-local-ssd-nvme-rel": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "use_goma": true
+    }
+  },
+  "linux-local-ssd-scsi-rel": {
+    "gn_args": {
+      "is_component_build": false,
+      "is_debug": false,
+      "use_goma": true
+    }
   }
 }
\ No newline at end of file
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b5f2a2f6..0c048039 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -47848,6 +47848,7 @@
   <int value="222055978" label="OsFeedback:disabled"/>
   <int value="222184258"
       label="AutofillEnforceMinRequiredFieldsForHeuristics:disabled"/>
+  <int value="223573347" label="BentoBar:disabled"/>
   <int value="223591010" label="CastMediaRouteProvider:enabled"/>
   <int value="223662457" label="BackgroundLoadingForDownloads:enabled"/>
   <int value="224019823" label="CompositeAfterPaint:enabled"/>
@@ -49434,6 +49435,7 @@
       label="ChromeHomePersonalizedOmniboxSuggestions:disabled"/>
   <int value="1568172566"
       label="OmniboxOnDeviceHeadProviderNonIncognito:disabled"/>
+  <int value="1569982806" label="BentoBar:enabled"/>
   <int value="1570178909" label="NewOverviewLayout:enabled"/>
   <int value="1571998166" label="DetectingHeavyPages:disabled"/>
   <int value="1573860827" label="EnableImeSandbox:enabled"/>
@@ -71075,6 +71077,12 @@
   <int value="11" label="(gesture) ScheduledPageBlock"/>
 </enum>
 
+<enum name="ScheduledTaskInvokedReason">
+  <int value="0" label="Stopped"/>
+  <int value="1" label="Rescheduled"/>
+  <int value="2" label="Ready"/>
+</enum>
+
 <enum name="SchedulerThreadType">
   <int value="0" label="BrowserUIThread"/>
   <int value="1" label="BrowserIOThread"/>
@@ -77083,7 +77091,8 @@
   <int value="4" label="Max number is missing"/>
   <int value="5" label="Rolled a non-zero number"/>
   <int value="6" label="User selected for survey"/>
-  <int value="7" label="Survey already exists"/>
+  <int value="7" label="Survey already exists [removed]"/>
+  <int value="8" label="First time user"/>
 </enum>
 
 <enum name="SuspendAttempt">
diff --git a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
index ba2d45ba..e29bfbf 100644
--- a/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/crostini/histograms.xml
@@ -401,6 +401,18 @@
   </summary>
 </histogram>
 
+<histogram name="Crostini.SetUpLxdContainerUser.UnknownResult"
+    enum="BooleanYesNo" expires_after="2021-12-31">
+  <owner>davidmunro@google.com</owner>
+  <owner>clumptini@google.com</owner>
+  <summary>
+    Yes if we got an unknown result for the SetUpLxdContainerUser step, No
+    otherwise. Recorded by CrostiniManager after getting the result for the the
+    SetUpLxdContainerUser step so we can check if our hypothesis to the root
+    cause of crbug/1216305 is correct, and to measure how widespread it is.
+  </summary>
+</histogram>
+
 <histogram name="Crostini.SetupResult" enum="CrostiniSetupResult"
     expires_after="2022-01-06">
   <owner>clumptini@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml
index e555804..9614389 100644
--- a/tools/metrics/histograms/histograms_xml/media/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -5361,7 +5361,10 @@
 </histogram>
 
 <histogram name="MediaRouter.Provider.Version" enum="MediaRouteProviderVersion"
-    expires_after="2022-02-01">
+    expires_after="M93">
+  <obsolete>
+    Removed in M93.
+  </obsolete>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -5371,7 +5374,10 @@
 </histogram>
 
 <histogram name="MediaRouter.Provider.WakeReason"
-    enum="MediaRouteProviderWakeReason" expires_after="2022-02-01">
+    enum="MediaRouteProviderWakeReason" expires_after="M93">
+  <obsolete>
+    Removed in M93.
+  </obsolete>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -5380,7 +5386,10 @@
 </histogram>
 
 <histogram name="MediaRouter.Provider.Wakeup" enum="MediaRouteProviderWakeup"
-    expires_after="2022-02-01">
+    expires_after="M93">
+  <obsolete>
+    Removed in M93.
+  </obsolete>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index b7200f27..abe1f4f 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -18725,6 +18725,9 @@
 
 <histogram name="WebApp.Shortcuts.Deletion.Success" enum="BooleanSuccess"
     expires_after="M93">
+  <obsolete>
+    Removed on M93. Not needed anymore.
+  </obsolete>
   <owner>phillis@chromium.org</owner>
   <owner>dmurph@chromium.org</owner>
   <owner>sunggch@microsoft.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml b/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
index 92de06e..3860b6a 100644
--- a/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/sb_client/histograms.xml
@@ -264,6 +264,8 @@
     page. By combining the shown and bypassed metrics for a specific danger
     type, we can calculate whether the bypass rate is different between
     user-initiated and automatically triggered downloads.
+
+    This metric is used to populate a dashboard on go/crsb-site.
   </summary>
   <token key="DangerType" variants="DownloadDangerTypeForBypassMetrics"/>
   <token key="Action" variants="DownloadWarningAction"/>
@@ -281,6 +283,8 @@
     combining the shown and bypassed metrics for a specific danger type, we can
     calculate whether the bypass rate is different between HTTPS downloads and
     non-HTTPS downloads.
+
+    This metric is used to populate a dashboard on go/crsb-site.
   </summary>
   <token key="DangerType" variants="DownloadDangerTypeForBypassMetrics"/>
   <token key="Action" variants="DownloadWarningAction"/>
@@ -296,6 +300,8 @@
     bypassed from the download shelf or from the downloads page. By combining
     the shown and bypassed metrics for a specific danger type, we can calculate
     the bypass rate of different file types.
+
+    This metric is used to populate a dashboard on go/crsb-site.
   </summary>
   <token key="DangerType" variants="DownloadDangerTypeForBypassMetrics"/>
   <token key="Action" variants="DownloadWarningAction"/>
@@ -584,6 +590,29 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientPhishing.MainFrameRemoteConnected"
+    enum="BooleanConnected" expires_after="2021-12-07">
+  <owner>drubery@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether we the mojo::Remote for the main frame's PhishingDetector is
+    connected. This is recorded on every classification (a large fraction of
+    navigations) where the mojo::Remote exists (see
+    SBClientPhishing.MainFrameRemoteExists).
+  </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.MainFrameRemoteExists" enum="BooleanExists"
+    expires_after="2021-12-07">
+  <owner>drubery@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
+  <summary>
+    Records whether we have a mojo::Remote for the main frame's
+    PhishingDetector. This is recorded on every classification (a large fraction
+    of navigations).
+  </summary>
+</histogram>
+
 <histogram name="SBClientPhishing.ModelDynamicUpdateSuccess"
     enum="BooleanSuccess" expires_after="2022-03-08">
   <owner>drubery@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/scheduler/histograms.xml b/tools/metrics/histograms/histograms_xml/scheduler/histograms.xml
index 335897b..8a2d9f42 100644
--- a/tools/metrics/histograms/histograms_xml/scheduler/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/scheduler/histograms.xml
@@ -137,6 +137,24 @@
   </summary>
 </histogram>
 
+<histogram name="Scheduler.TimerBase.ScheduledTaskInvokedReason"
+    enum="ScheduledTaskInvokedReason" expires_after="M95">
+  <owner>pmonette@chromium.org</owner>
+  <owner>chrome-catan@google.com</owner>
+  <summary>
+    Records the reason that a timer's scheduled task was invoked.
+
+    To avoid a degenerate case where a timer could flood the task queue by
+    repeatedly stopping and starting, the scheduled task is kept active in the
+    task queue even if the timer is not running anymore. The issue with this is
+    that the scheduled task can now cause unnecessary wake-ups just to do
+    nothing. This histogram records how many times the timer's task was run
+    unnecessarily.
+
+    Not recorded on Fuchsia.
+  </summary>
+</histogram>
+
 <histogram name="Scheduling.BeginImplFrameLatency2" units="microseconds"
     expires_after="M85">
   <owner>stanisc@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index ab2d132..e7b0998 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "022c89621a6149a651525df62d68cac5a55bf68e",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/bb16fa2cc0a03db867a1977c68d87efe7d7e26be/trace_processor_shell.exe"
+            "hash": "d2f2258393e317714f24253d5c00e974cd868328",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/d57b60b2a95fa369db906eaaeadc4623dab6eb90/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "ed0346b59fb7f24b052b52e199cfd5525028dded",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/8b07d9bbd00bbc938dc5e81bea6f4e99087b54fe/trace_processor_shell"
+            "hash": "ba398d7eef9faab8ab8905a1aa8613fffd6d7bbc",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/d57b60b2a95fa369db906eaaeadc4623dab6eb90/trace_processor_shell"
         },
         "linux": {
             "hash": "2f603ae27a8ffa6005dd43b0d0dd4f5e75b9bc97",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/731dcf8b1cbead0b4ab422d5d119644fb5ab60d8/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/d57b60b2a95fa369db906eaaeadc4623dab6eb90/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/style_variable_generator/colors_test_dark_only_expected.css b/tools/style_variable_generator/colors_test_dark_only_expected.css
index 1cf89b1..6213811 100644
--- a/tools/style_variable_generator/colors_test_dark_only_expected.css
+++ b/tools/style_variable_generator/colors_test_dark_only_expected.css
@@ -19,5 +19,5 @@
 
   --cros-disabled-opacity: 0.38;
 
-  --cros-reference-opacity: var(--cros-disabled-opacity);
+  --cros-reference-opacity: 1;
 }
diff --git a/tools/style_variable_generator/css_generator.py b/tools/style_variable_generator/css_generator.py
index 9f76465d..ac6d0e2 100644
--- a/tools/style_variable_generator/css_generator.py
+++ b/tools/style_variable_generator/css_generator.py
@@ -22,14 +22,20 @@
         if self.generate_single_mode:
             resolved_colors = self.model[VariableType.COLOR].Flatten(
                 resolve_missing=True)
+            resolved_opacities = self.model[VariableType.OPACITY].Flatten(
+                resolve_missing=True)
             colors = {
                 Modes.DEFAULT: resolved_colors[self.generate_single_mode]
             }
+            opacities = {
+                Modes.DEFAULT: resolved_opacities[self.generate_single_mode]
+            }
         else:
             colors = self.model[VariableType.COLOR].Flatten()
+            opacities = self.model[VariableType.OPACITY].Flatten()
 
         return {
-            'opacities': self.model[VariableType.OPACITY].Flatten(),
+            'opacities': opacities,
             'colors': colors,
         }
 
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml
index 142e434..0754ee3 100644
--- a/ui/android/java/res/values/color_palette.xml
+++ b/ui/android/java/res/values/color_palette.xml
@@ -5,13 +5,18 @@
      found in the LICENSE file.
 -->
 <resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- 2021 color palette -->
+    <color name="modern_blue_200">#A8C7FA</color>
+    <color name="modern_blue_600">#0B57D0</color>
+    <color name="modern_grey_100_alpha_12">#1EE3E3E3</color>
+    <color name="modern_grey_900_alpha_12">#1E1F1F1F</color>
+
     <!-- Modern color palette -->
     <color name="modern_white">@android:color/white</color>
     <color name="modern_blue_300">#8AB4F8</color>
     <color name="modern_blue_300_alpha_10" tools:ignore="UnusedResources">#198AB4F8</color>
     <color name="modern_blue_300_alpha_50">#808AB4F8</color>
     <color name="modern_blue_300_alpha_55" tools:ignore="UnusedResources">#5A7198</color>
-    <color name="modern_blue_600">#1A73E8</color>
     <color name="modern_blue_600_alpha_6">#0F1A73E8</color>
     <color name="modern_blue_600_alpha_10">#191A73E8</color>
     <color name="modern_blue_600_alpha_12">#1F1A73E8</color>
diff --git a/ui/android/java/res/values/dimens.xml b/ui/android/java/res/values/dimens.xml
index 696fc2e5..f6e14a4 100644
--- a/ui/android/java/res/values/dimens.xml
+++ b/ui/android/java/res/values/dimens.xml
@@ -31,7 +31,7 @@
 
     <!-- Button default measures -->
     <dimen name="button_min_width">88dp</dimen>
-    <dimen name="button_bg_vertical_inset">6dp</dimen>
+    <dimen name="button_bg_vertical_inset">4dp</dimen>
 
     <!-- Chips default measures -->
     <item name="chip_background_selected_alpha_light" format="float" type="dimen">0.06</item>
@@ -72,7 +72,10 @@
     <dimen name="dropdown_vertical_margin">4dp</dimen>
     <dimen name="dropdown_elevation">2dp</dimen>
 
-    <dimen name="button_compat_corner_radius">4dp</dimen>
+    <!-- Use arbitrary high number so that if the button text spans multiple
+     lines with XL text, the corners will still look fully rounded
+     TODO(crbug/1217139): Determine the corner radius based on button height-->
+    <dimen name="button_compat_corner_radius">500dp</dimen>
 
     <dimen name="chrome_bullet_gap">12dp</dimen>
     <dimen name="chrome_bullet_leading_offset">1dp</dimen>
diff --git a/ui/android/java/res/values/semantic_colors_non_adaptive.xml b/ui/android/java/res/values/semantic_colors_non_adaptive.xml
index fdb47aa5a..afe5ce4 100644
--- a/ui/android/java/res/values/semantic_colors_non_adaptive.xml
+++ b/ui/android/java/res/values/semantic_colors_non_adaptive.xml
@@ -99,9 +99,9 @@
 
     <!--  Filled Button  -->
     <color name="filled_button_bg_color_dark">@color/modern_blue_600</color>
-    <color name="filled_button_bg_color_light">@color/modern_blue_300</color>
-    <color name="filled_button_bg_color_disabled_dark">@color/modern_grey_800_alpha_38</color>
-    <color name="filled_button_bg_color_disabled_light">@color/white_alpha_38</color>
+    <color name="filled_button_bg_color_light">@color/modern_blue_200</color>
+    <color name="filled_button_bg_color_disabled_dark">@color/modern_grey_900_alpha_12</color>
+    <color name="filled_button_bg_color_disabled_light">@color/modern_grey_100_alpha_12</color>
 
     <!--  Dropdown divier  -->
     <color name="dropdown_divider_color">@color/modern_grey_300</color>
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc
index 3ad5dada..cf849cf5 100644
--- a/ui/base/ime/chromeos/input_method_chromeos.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -476,8 +476,7 @@
   const bool was_composing = composing_text_;
 
   pending_composition_ = absl::nullopt;
-  result_text_.clear();
-  result_text_cursor_ = 0;
+  pending_commit_ = absl::nullopt;
   composing_text_ = false;
   composition_changed_ = false;
 
@@ -606,26 +605,29 @@
   TextInputClient* client = GetTextInputClient();
   DCHECK(client);
 
-  if (result_text_.length()) {
+  if (pending_commit_) {
     if (handled && NeedInsertChar()) {
-      for (std::u16string::const_iterator i = result_text_.begin();
-           i != result_text_.end(); ++i) {
+      for (const auto& ch : pending_commit_->text) {
         KeyEvent ch_event(ET_KEY_PRESSED, VKEY_UNKNOWN, EF_NONE);
-        ch_event.set_character(*i);
+        ch_event.set_character(ch);
         client->InsertChar(ch_event);
       }
+    } else if (pending_commit_->text.empty()) {
+      client->InsertText(
+          u"", TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
+      composing_text_ = false;
     } else {
-      // Split |result_text_| into two separate commits, one for the substring
-      // before |result_text_cursor_| and one for the substring after.
+      // Split the commit into two separate commits, one for the substring
+      // before the cursor and one for the substring after.
       const std::u16string before_cursor =
-          result_text_.substr(0, result_text_cursor_);
+          pending_commit_->text.substr(0, pending_commit_->cursor);
       if (!before_cursor.empty()) {
         client->InsertText(
             before_cursor,
             TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
       }
       const std::u16string after_cursor =
-          result_text_.substr(result_text_cursor_);
+          pending_commit_->text.substr(pending_commit_->cursor);
       if (!after_cursor.empty()) {
         client->InsertText(
             after_cursor,
@@ -633,7 +635,7 @@
       }
       composing_text_ = false;
     }
-    typing_session_manager_.CommitCharacters(result_text_.length());
+    typing_session_manager_.CommitCharacters(pending_commit_->text.length());
   }
 
   // TODO(https://crbug.com/952757): Refactor this code to be clearer and less
@@ -647,7 +649,7 @@
     if (pending_composition_) {
       composing_text_ = true;
       client->SetCompositionText(*pending_composition_);
-    } else if (result_text_.empty() && !pending_composition_range_) {
+    } else if (!pending_commit_ && !pending_composition_range_) {
       client->ClearCompositionText();
     }
 
@@ -662,20 +664,19 @@
 
   // We should not clear composition text here, as it may belong to the next
   // composition session.
-  result_text_.clear();
-  result_text_cursor_ = 0;
+  pending_commit_ = absl::nullopt;
   composition_changed_ = false;
 }
 
 bool InputMethodChromeOS::NeedInsertChar() const {
   return GetTextInputClient() &&
-         (IsTextInputTypeNone() ||
-          (!composing_text_ && result_text_.length() == 1 &&
-           result_text_cursor_ == 1));
+         (IsTextInputTypeNone() || (!composing_text_ && pending_commit_ &&
+                                    pending_commit_->text.length() == 1 &&
+                                    pending_commit_->cursor == 1));
 }
 
 bool InputMethodChromeOS::HasInputMethodResult() const {
-  return result_text_.length() || composition_changed_;
+  return pending_commit_ || composition_changed_;
 }
 
 void InputMethodChromeOS::CommitText(
@@ -694,10 +695,13 @@
 
   // Append the text to the buffer, because commit signal might be fired
   // multiple times when processing a key event.
-  result_text_.insert(result_text_cursor_, text);
+  if (!pending_commit_) {
+    pending_commit_ = PendingCommit();
+  }
+  pending_commit_->text.insert(pending_commit_->cursor, text);
   if (cursor_behavior ==
       TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText) {
-    result_text_cursor_ += text.length();
+    pending_commit_->cursor += text.length();
   }
 
   // If we are not handling key event, do not bother sending text result if the
@@ -708,8 +712,7 @@
       typing_session_manager_.CommitCharacters(text.length());
     }
     SendFakeProcessKeyEvent(false);
-    result_text_.clear();
-    result_text_cursor_ = 0;
+    pending_commit_ = absl::nullopt;
   }
 }
 
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h
index cda9460..3fb7169ba 100644
--- a/ui/base/ime/chromeos/input_method_chromeos.h
+++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -113,6 +113,15 @@
     std::vector<ui::ImeTextSpan> text_spans;
   };
 
+  // Representings a pending CommitText operation.
+  struct PendingCommit {
+    std::u16string text;
+
+    // Where the cursor should be placed in |text|.
+    // 0 <= |cursor| <= |text.length()|.
+    size_t cursor = 0;
+  };
+
   // Checks the availability of focused text input client and update focus
   // state.
   void UpdateContextFocusState();
@@ -177,11 +186,7 @@
   // Pending result text generated by the current pending key event.
   // It'll be sent to the focused text input client as soon as we receive the
   // processing result of the pending key event.
-  std::u16string result_text_;
-
-  // Where the cursor should be place after inserting |result_text_|.
-  // 0 <= |result_text_cursor_| <= |result_text_.length()|.
-  size_t result_text_cursor_ = 0;
+  absl::optional<PendingCommit> pending_commit_;
 
   std::u16string previous_surrounding_text_;
   gfx::Range previous_selection_range_;
diff --git a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
index 0b907ae..cef1ef6 100644
--- a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
+++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -1267,6 +1267,26 @@
   EXPECT_EQ(fake_text_input_client.selection(), gfx::Range(3, 3));
 }
 
+TEST_F(InputMethodChromeOSKeyEventTest, CommitTextEmptyRunsAfterKeyEvent) {
+  FakeTextInputClient fake_text_input_client(TEXT_INPUT_TYPE_TEXT);
+  InputMethodChromeOS ime(this);
+  ime.SetFocusedTextInputClient(&fake_text_input_client);
+  ui::CompositionText composition;
+  composition.text = u"hello";
+  ime.UpdateCompositionText(composition, /*cursor_pos=*/5, /*visible=*/true);
+
+  ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
+  ime.DispatchKeyEvent(&event);
+  ime.CommitText(
+      u"", TextInputClient::InsertTextCursorBehavior::kMoveCursorBeforeText);
+  std::move(mock_ime_engine_handler_->last_passed_callback())
+      .Run(/*handled=*/true);
+
+  EXPECT_EQ(fake_text_input_client.text(), u"");
+  EXPECT_FALSE(fake_text_input_client.HasCompositionText());
+  EXPECT_EQ(fake_text_input_client.selection(), gfx::Range(0, 0));
+}
+
 TEST_F(InputMethodChromeOSTest, CommitTextReplacesSelection) {
   FakeTextInputClient fake_text_input_client(TEXT_INPUT_TYPE_TEXT);
   fake_text_input_client.SetTextAndSelection(u"hello", gfx::Range(0, 5));
diff --git a/ui/base/ime/fake_text_input_client.cc b/ui/base/ime/fake_text_input_client.cc
index 1e3b7a4..2077fa4 100644
--- a/ui/base/ime/fake_text_input_client.cc
+++ b/ui/base/ime/fake_text_input_client.cc
@@ -32,7 +32,12 @@
 }
 
 void FakeTextInputClient::SetCompositionText(
-    const CompositionText& composition) {}
+    const CompositionText& composition) {
+  text_.insert(selection_.start(), composition.text);
+  const size_t new_cursor = selection_.start() + composition.text.length();
+  composition_range_ = gfx::Range(selection_.start(), new_cursor);
+  selection_ = gfx::Range(new_cursor, new_cursor);
+}
 
 uint32_t FakeTextInputClient::ConfirmCompositionText(bool keep_selection) {
   return UINT32_MAX;
@@ -43,18 +48,18 @@
 void FakeTextInputClient::InsertText(
     const std::u16string& text,
     TextInputClient::InsertTextCursorBehavior cursor_behavior) {
-  if (!composition_range_.is_empty()) {
-    text_.replace(composition_range_.start(), composition_range_.length(),
-                  text);
-  } else {
-    text_.replace(selection_.start(), selection_.length(), text);
-  }
+  const gfx::Range replacement_range =
+      composition_range_.is_empty() ? selection_ : composition_range_;
+
+  text_.replace(replacement_range.start(), replacement_range.length(), text);
 
   if (cursor_behavior ==
       TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText) {
-    selection_ = gfx::Range(selection_.start() + text.length(),
-                            selection_.end() + text.length());
+    selection_ = gfx::Range(replacement_range.start() + text.length(),
+                            replacement_range.start() + text.length());
   }
+
+  composition_range_ = gfx::Range();
 }
 
 void FakeTextInputClient::InsertChar(const KeyEvent& event) {}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js
index f71846c1..b39cfad1 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -299,11 +299,10 @@
     this.photosWelcomeCounter_ = value;
     const values = {};
     values[PHOTOS_WELCOME_COUNTER_KEY] = value;
-    chrome.storage.local.set(values);
+    xfm.storage.local.set(values);
   }
 
   /**
-   * chrome.storage.onChanged event handler.
    * xfm.storage.onChanged event handler.
    * @param {Object<Object>} changes Changes values.
    * @param {string} areaName "local" or "sync".
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc
index a7ade895..e1ab6f9a 100644
--- a/ui/gl/swap_chain_presenter.cc
+++ b/ui/gl/swap_chain_presenter.cc
@@ -443,9 +443,9 @@
     gfx::Size* swap_chain_size,
     gfx::Transform* transform,
     gfx::Rect* clip_rect) {
-  gfx::Rect onscreen_rect = overlay_onscreen_rect;
-  if (params.clip_rect)
-    onscreen_rect.Intersect(*clip_rect);
+  gfx::Rect clipped_onscreen_rect = overlay_onscreen_rect;
+  if (params.clip_rect.has_value())
+    clipped_onscreen_rect.Intersect(*clip_rect);
 
   // Because of the rounding when converting between pixels and DIPs, a
   // fullscreen video can become slightly larger than the monitor - e.g. on
@@ -458,8 +458,8 @@
   constexpr int kFullScreenMargin = 5;
 
   // The overlay must be positioned at (0, 0) in fullscreen mode.
-  if (std::abs(onscreen_rect.x()) >= kFullScreenMargin ||
-      std::abs(onscreen_rect.y()) >= kFullScreenMargin) {
+  if (std::abs(clipped_onscreen_rect.x()) >= kFullScreenMargin ||
+      std::abs(clipped_onscreen_rect.y()) >= kFullScreenMargin) {
     // Not fullscreen mode.
     return;
   }
@@ -474,22 +474,40 @@
   // dynamic refresh rates (24hz/48hz). Note: The DWM optimizations works for
   // both hardware and software overlays.
   // If no, do nothing.
-  if (std::abs(onscreen_rect.width() - monitor_size.width()) >=
+  if (std::abs(clipped_onscreen_rect.width() - monitor_size.width()) >=
           kFullScreenMargin ||
-      std::abs(onscreen_rect.height() - monitor_size.height()) >=
+      std::abs(clipped_onscreen_rect.height() - monitor_size.height()) >=
           kFullScreenMargin) {
     // Not fullscreen mode.
     return;
   }
 
+  // For most video playbacks, |clip_rect| is the same as
+  // |overlay_onscreen_rect| or close to it. If |clipped_onscreen_rect| has the
+  // size of the monitor but |overlay_onscreen_rect| is much bigger than the
+  // monitor size, we don't get the benefit of this optimization in this case.
+  // We should do nothing here. e.g. |overlay_onscreen_rect| is ~7680 x 4320 and
+  // it's clipped to ~3840 x 2160 to fit the monitor. Check
+  // |overlay_onscreen_rect| only if it's different from |clipped_onscreen_rect|
+  // when clipping is enabled. https://crbug.com/1213035
+  if (params.clip_rect.has_value()) {
+    if (std::abs(overlay_onscreen_rect.width() - monitor_size.width()) >=
+            kFullScreenMargin ||
+        std::abs(overlay_onscreen_rect.height() - monitor_size.height()) >=
+            kFullScreenMargin) {
+      return;
+    }
+  }
+
   // Adjust the clip rect.
-  if (params.clip_rect) {
+  if (params.clip_rect.has_value()) {
     *clip_rect = gfx::Rect(monitor_size);
   }
 
   // Adjust the swap chain size.
-  // The swap chain is either the size of onscreen_rect or min(onscreen_rect,
-  // content_rect). It might not need to update if it has the content size.
+  // The swap chain is either the size of overlay_onscreen_rect or
+  // min(overlay_onscreen_rect, content_rect). It might not need to update if it
+  // has the content size.
   if (std::abs(swap_chain_size->width() - monitor_size.width()) <
           kFullScreenMargin &&
       std::abs(swap_chain_size->height() - monitor_size.height()) <
@@ -499,8 +517,8 @@
 
   // Adjust the transform matrix.
   auto& transform_matrix = transform->matrix();
-  float dx = -onscreen_rect.x();
-  float dy = -onscreen_rect.y();
+  float dx = -clipped_onscreen_rect.x();
+  float dy = -clipped_onscreen_rect.y();
   transform_matrix.postTranslate(dx, dy, 0);
 
   float scale_x = monitor_size.width() * 1.0f / swap_chain_size->width();
@@ -610,14 +628,14 @@
 
   if (visual_info_.clip_rect.has_value() != params.clip_rect.has_value() ||
       visual_info_.clip_rect != clip_rect) {
-    if (params.clip_rect) {
+    if (params.clip_rect.has_value()) {
       visual_info_.clip_rect = clip_rect;
     }
     layer_tree_->SetNeedsRebuildVisualTree();
     // DirectComposition clips happen in the pre-transform visual space, while
     // cc/ clips happen post-transform. So the clip needs to go on a separate
     // parent visual that's untransformed.
-    if (params.clip_rect) {
+    if (params.clip_rect.has_value()) {
       Microsoft::WRL::ComPtr<IDCompositionRectangleClip> clip;
       dcomp_device_->CreateRectangleClip(&clip);
       DCHECK(clip);
diff --git a/url/android/gurl_android.cc b/url/android/gurl_android.cc
index a16d2b8..861bc6f 100644
--- a/url/android/gurl_android.cc
+++ b/url/android/gurl_android.cc
@@ -57,17 +57,6 @@
                                     gurl.parsed_for_possibly_invalid_spec()));
 }
 
-// As |GetArrayLength| makes no guarantees about the returned value (e.g., it
-// may be -1 if |array| is not a valid Java array), provide a safe wrapper
-// that always returns a valid, non-negative size.
-template <typename JavaArrayType>
-size_t SafeGetArrayLength(JNIEnv* env, const JavaRef<JavaArrayType>& jarray) {
-  DCHECK(jarray);
-  jsize length = env->GetArrayLength(jarray.obj());
-  DCHECK_GE(length, 0) << "Invalid array length: " << length;
-  return static_cast<size_t>(std::max(0, length));
-}
-
 }  // namespace
 
 // static
@@ -78,23 +67,6 @@
       reinterpret_cast<GURL*>(Java_GURL_toNativeGURL(env, j_gurl)));
 }
 
-void GURLAndroid::JavaGURLArrayToGURLVector(
-    JNIEnv* env,
-    const base::android::JavaRef<jobjectArray>& array,
-    std::vector<GURL>* out) {
-  DCHECK(out);
-  DCHECK(out->empty());
-  if (!array)
-    return;
-  size_t len = SafeGetArrayLength(env, array);
-  for (size_t i = 0; i < len; ++i) {
-    ScopedJavaLocalRef<jobject> j_gurl(
-        env, static_cast<jobject>(env->GetObjectArrayElement(array.obj(), i)));
-    out->emplace_back(
-        *reinterpret_cast<GURL*>(Java_GURL_toNativeGURL(env, j_gurl)));
-  }
-}
-
 // static
 ScopedJavaLocalRef<jobject> GURLAndroid::FromNativeGURL(JNIEnv* env,
                                                         const GURL& gurl) {
diff --git a/url/android/gurl_android.h b/url/android/gurl_android.h
index b0e3b729..b36538d 100644
--- a/url/android/gurl_android.h
+++ b/url/android/gurl_android.h
@@ -25,10 +25,6 @@
   static base::android::ScopedJavaLocalRef<jobjectArray> ToJavaArrayOfGURLs(
       JNIEnv* env,
       base::span<base::android::ScopedJavaLocalRef<jobject>> v);
-  static void JavaGURLArrayToGURLVector(
-      JNIEnv* env,
-      const base::android::JavaRef<jobjectArray>& gurl_array,
-      std::vector<GURL>* out);
 };
 
 }  // namespace url
diff --git a/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java b/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java
index f6b6832..93d2992c 100644
--- a/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java
+++ b/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java
@@ -25,7 +25,6 @@
     //    in the map.
     public static final String EXAMPLE_URL = "https://www.example.com/";
     public static final String URL_1 = "https://www.one.com/";
-    public static final String URL_1_NUMERAL = "https://www.1.com/";
     public static final String URL_1_WITH_PATH = "https://www.one.com/some_path.html";
     public static final String URL_2 = "https://www.two.com/";
     public static final String URL_3 = "https://www.three.com/";
@@ -57,9 +56,6 @@
         map.put(URL_1,
                 "78,1,true,0,5,0,-1,0,-1,8,11,0,-1,19,1,0,-1,0,-1,"
                         + "false,false,https://www.one.com/");
-        map.put(URL_1_NUMERAL,
-                "75,1,true,0,5,0,-1,0,-1,8,9,0,-1,17,1,0,-1,0,-1,"
-                        + "false,false,https://www.1.com/");
         map.put(URL_1_WITH_PATH,
                 "93,1,true,0,5,0,-1,0,-1,8,11,0,-1,19,15,0,-1,0,-1,"
                         + "false,false,https://www.one.com/some_path.html");
diff --git a/weblayer/browser/safe_browsing/client_side_detection_service_browsertest.cc b/weblayer/browser/safe_browsing/client_side_detection_service_browsertest.cc
index ca84869..090487b2 100644
--- a/weblayer/browser/safe_browsing/client_side_detection_service_browsertest.cc
+++ b/weblayer/browser/safe_browsing/client_side_detection_service_browsertest.cc
@@ -14,6 +14,7 @@
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
 #include "components/safe_browsing/core/proto/client_model.pb.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/test_utils.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -68,6 +69,10 @@
 
   base::RunLoop run_loop;
 
+  // Ensure that IPCs to set the model have propagated, otherwise they may
+  // interrupt classification.
+  content::RunAllTasksUntilIdle();
+
   content::RenderFrameHost* rfh = GetWebContents()->GetMainFrame();
   mojo::Remote<safe_browsing::mojom::PhishingDetector> phishing_detector;
   rfh->GetRemoteInterfaces()->GetInterface(